1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +02:00

Fix for Bug 170315 - [Content Assist] Completion contributors should be user selectable

This commit is contained in:
Anton Leherbauer 2007-01-24 16:11:48 +00:00
parent 774fde4cf9
commit db7ea396ea
43 changed files with 5190 additions and 1367 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

View file

@ -137,14 +137,12 @@ CPluginBuildConsolePreferencePage.name=Build Console
CPluginFileTypesPreferencePage.name=File Types
CodeFormatterPreferencePage.name=Code Style
CodeAssistPreferencePage.name=Content Assist
CodeAssistAdvancedPreferencePage.name=Advanced
SmartTypingPreferencePage.name=Typing
ColoringPreferencePage.name=Syntax Coloring
FoldingPreferencePage.name=Folding
HoverPreferencePage.name=Hovers
todoPageName=C/C++ Task Tags
todoTaskPrefName=Task Tags
Editors.DefaultTextEditor = Default Text Editor
AsmEditor.name = Assembly Editor
@ -334,8 +332,8 @@ c.contextType.name = C/C++
comment.contextType.name = Comment
# completion
completionContributors=Content Assist Completion Contributor
completionProposalComputer=Completion Proposal Computer
# Indexer Preference Name
indexerPrefName=Indexer
@ -363,3 +361,12 @@ navigatorContent.name = CDT Elements
OpenCallHierarchy.label = Open Call Hierarchy
OpenCallHierarchy.tooltip = Open Call Hierarchy
ParserProposalCategory=Parsing-based Proposals
DefaultProposalCategory= &Basic Proposals
TemplateProposalCategory= Te&mplate Proposals
TextProposalCategory= &Word Proposals
SpecificContentAssist.name= C/C++ Content Assist
SpecificContentAssist.desc= A parameterizable command that invokes content assist with a single completion proposal category
SpecificContentAssist.param= type

View file

@ -17,6 +17,7 @@
<extension-point id="IndexerPage" name="%indexerPage.name" schema="schema/IndexerPage.exsd"/>
<extension-point id="completionContributors" name="%completionContributors" schema="schema/completionContributors.exsd"/>
<extension-point id="ProposalFilter" name="%proposalFilter.name" schema="schema/ProposalFilter.exsd"/>
<extension-point id="completionProposalComputer" name="%completionProposalComputer" schema="schema/completionProposalComputer.exsd"/>
<extension
point="org.eclipse.core.runtime.adapters">
@ -609,6 +610,12 @@
class="org.eclipse.cdt.internal.ui.preferences.CodeAssistPreferencePage"
id="org.eclipse.cdt.ui.preferences.CodeAssistPreferencePage">
</page>
<page
name="%CodeAssistAdvancedPreferencePage.name"
category="org.eclipse.cdt.ui.preferences.CodeAssistPreferencePage"
class="org.eclipse.cdt.internal.ui.preferences.CodeAssistAdvancedPreferencePage"
id="org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced">
</page>
<page
name="%ColoringPreferencePage.name"
category="org.eclipse.cdt.ui.preferences.CEditorPreferencePage"
@ -1431,10 +1438,6 @@
class="org.eclipse.cdt.internal.ui.text.contentassist.DOMCompletionContributor"
id="DOM"
priority="1"/>
<contributor
class="org.eclipse.cdt.internal.ui.text.template.CTemplateCompletionProcessor"
id="CodeTemplates"
priority="2"/>
<contributor
class="org.eclipse.cdt.internal.ui.text.contentassist.KeywordCompletionContributor"
id="Keywords"
@ -1443,11 +1446,91 @@
class="org.eclipse.cdt.internal.ui.text.contentassist.HelpCompletionContributor"
id="Help"
priority="99"/>
<contributor
<!--contributor
class="org.eclipse.cdt.internal.ui.text.contentassist.PDOMCompletionContributor"
id="PDOM"
priority="3"/>
priority="3"/-->
</extension>
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="defaultProposalCategory"
name="%DefaultProposalCategory">
<proposalCategory/>
</extension>
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="parserProposalCategory"
name="%ParserProposalCategory">
<proposalCategory
icon="$nl$/icons/elcl16/codeassist_co.gif"/>
</extension>
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="templateProposalCategory"
name="%TemplateProposalCategory">
<proposalCategory
icon="$nl$/icons/elcl16/templateprop_co.gif"/>
</extension>
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="textProposalCategory"
name="%TextProposalCategory">
<proposalCategory
icon="$nl$/icons/elcl16/wordassist_co.gif"/>
</extension>
<!-- legacy completions (completionContributors) -->
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="LegacyCompletionProposalComputer">
<completionProposalComputer
class="org.eclipse.cdt.internal.ui.text.contentassist.LegacyCompletionProposalComputer"
categoryId="org.eclipse.cdt.ui.parserProposalCategory">
<partition type="__dftl_partition_content_type"/>
</completionProposalComputer>
</extension>
<!-- template proposals -->
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="TemplateCompletionProposalComputer">
<completionProposalComputer
class="org.eclipse.cdt.internal.ui.text.contentassist.TemplateCompletionProposalComputer"
categoryId="org.eclipse.cdt.ui.templateProposalCategory">
<partition type="__dftl_partition_content_type"/>
<partition type="__c_multiline_comment"/>
</completionProposalComputer>
</extension>
<!-- hippie word completions -->
<extension
point="org.eclipse.cdt.ui.completionProposalComputer"
id="HippieCompletionProposalComputer">
<completionProposalComputer
class="org.eclipse.cdt.internal.ui.text.contentassist.HippieProposalComputer"
categoryId="org.eclipse.cdt.ui.textProposalCategory">
<partition type="__c_singleline_comment"/>
<partition type="__c_multiline_comment"/>
<partition type="__c_string"/>
</completionProposalComputer>
</extension>
<!-- the parameterized content assist action and keybindings for our contributed computers -->
<extension
point="org.eclipse.ui.commands">
<command
categoryId="org.eclipse.ui.category.edit"
description="%SpecificContentAssist.desc"
id="org.eclipse.cdt.ui.specific_content_assist.command"
name="%SpecificContentAssist.name"
defaultHandler="org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistHandler">
<commandParameter
id="org.eclipse.cdt.ui.specific_content_assist.category_id"
name="%SpecificContentAssist.param"
optional="false"
values="org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistComputerParameter"/>
</command>
</extension>
<extension
point="org.eclipse.ui.popupMenus">
<objectContribution

View file

@ -11,6 +11,11 @@
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element deprecated="true" replacement="completionProposalComputer" />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="contributor" minOccurs="1" maxOccurs="unbounded"/>

View file

@ -0,0 +1,209 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.ui">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.ui" id="completionProposalComputer" name="Completion Proposal Computer"/>
</appInfo>
<documentation>
This extension point allows to contribute completion proposal computers to participate in the content assist process of the C/C++ editor.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element labelAttribute="name"/>
</appInfo>
</annotation>
<complexType>
<choice>
<element ref="completionProposalComputer"/>
<element ref="proposalCategory"/>
</choice>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
The fully qualified identifier of the target extension point
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
The identifier of the extension instance, unique within the declaring plug-in (the plug-in&apos;s identifier will be prepended to form a platform-wide unique id)
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
The optional name of the extension instance
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="completionProposalComputer">
<annotation>
<documentation>
A proposal computer contribution. If no partition types are specified, the computer is added to all partition types.
</documentation>
</annotation>
<complexType>
<sequence minOccurs="0" maxOccurs="6">
<element ref="partition"/>
</sequence>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
The name of the class that implements the contributed computer. The
class must be public and implement
&lt;samp&gt;org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer&lt;/samp&gt;
and must have a public 0-argument constructor.
</documentation>
<appInfo>
<meta.attribute kind="java"/>
</appInfo>
</annotation>
</attribute>
<attribute name="activate" type="boolean" use="default" value="false">
<annotation>
<documentation>
If the attribute is set to &quot;true&quot; it will force this plug-in to be loaded on content assist invocation.
</documentation>
</annotation>
</attribute>
<attribute name="categoryId" type="string" use="default" value="org.eclipse.cdt.ui.defaultProposalCategory">
<annotation>
<documentation>
The id of a &lt;tt&gt;proposalCategory&lt;/tt&gt;
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<element name="partition">
<annotation>
<appInfo>
<meta.element labelAttribute="type"/>
</appInfo>
</annotation>
<complexType>
<attribute name="type" use="required">
<annotation>
<documentation>
A C/C++ partition type for which the specified computer can provide completion proposals. See &lt;code&gt;IDocument.DEFAULT_CONTENT_TYPE&lt;/code&gt; and &lt;code&gt;ICPartitions&lt;/code&gt; for valid values.
</documentation>
</annotation>
<simpleType>
<restriction base="string">
<enumeration value="__dftl_partition_content_type">
</enumeration>
<enumeration value="__c_multiline_comment">
</enumeration>
<enumeration value="__c_singleline_comment">
</enumeration>
<enumeration value="__c_string">
</enumeration>
<enumeration value="__c_character">
</enumeration>
<enumeration value="__c_preprocessor">
</enumeration>
</restriction>
</simpleType>
</attribute>
</complexType>
</element>
<element name="proposalCategory">
<annotation>
<documentation>
A proposal category contribution defines categories of proposals used to group them in the UI.
</documentation>
</annotation>
<complexType>
<attribute name="icon" type="string">
<annotation>
<documentation>
The optional icon of the category, which can be displayed in the user preferences.
</documentation>
<appInfo>
<meta.attribute kind="resource"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
4.0
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
The following is an example of a completion proposal computer contribution:
&lt;p&gt;
&lt;pre&gt;
&lt;extension point=&quot;org.eclipse.cdt.ui.completionProposalComputer&quot;
id=&quot;textual_proposals&quot;
name=&quot;Text Proposals&quot;&gt;
&lt;proposalCategory icon=&quot;icons/wordcompletions.png&quot;/&gt;
&lt;/extension&gt;
&lt;extension point=&quot;org.eclipse.cdt.ui.completionProposalComputer&quot;
id=&quot;WordCompletionProposalComputer&quot;
name=&quot;Word Completion Proposal Computer&quot;&gt;
&lt;completionProposalComputer
class=&quot;org.eclipse.cdt.internal.ui.text.contentassist.HippieProposalComputer&quot;
categoryId=&quot;org.eclipse.ui.texteditor.textual_proposals&quot;&gt;
&lt;partition type=&quot;__c_multiline_comment&quot;/&gt;
&lt;/completionProposalComputer&gt;
&lt;/extension&gt;
&lt;/pre&gt;
&lt;/p&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
The contributed class must extend &lt;code&gt;org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer&lt;/code&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
see &lt;code&gt;org.eclipse.cdt.internal.ui.text.contentassist.HippieProposalComputer&lt;/code&gt; for an example.
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
Copyright (c) 2006, 2007 IBM Corporation and others.&lt;br&gt;
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 &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
</documentation>
</annotation>
</schema>

View file

@ -95,3 +95,5 @@ TextEditorDropAdapter.error.title=Drag and Drop
TextEditorDropAdapter.error.message=A problem occurred during drag and drop.
TextEditorDropAdapter.unreadableFile=Unreadable file: ''{0}''
TextEditorDropAdapter.noFile=Not a file: ''{0}''
OptionalMessageDialog_dontShowAgain= Do not show this &message again

View file

@ -0,0 +1,125 @@
/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.dialogs;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.CUIMessages;
/**
* This is a <code>MessageDialog</code> which allows the user
* to choose that the dialog isn't shown again the next time.
*/
public class OptionalMessageDialog extends MessageDialog {
// String constants for widgets
private static final String CHECKBOX_TEXT= CUIMessages.getString("OptionalMessageDialog_dontShowAgain"); //$NON-NLS-1$
// Dialog store id constants
private static final String STORE_ID= "OptionalMessageDialog.hide."; //$NON-NLS-1$
public static final int NOT_SHOWN= IDialogConstants.CLIENT_ID + 1;
private Button fHideDialogCheckBox;
private String fId;
/**
* Opens the dialog but only if the user hasn't choosen to hide it.
* Returns <code>NOT_SHOWN</code> if the dialog was not shown.
*/
public static int open(String id, Shell parent, String title, Image titleImage, String message, int dialogType, String[] buttonLabels, int defaultButtonIndex) {
if (!isDialogEnabled(id))
return OptionalMessageDialog.NOT_SHOWN;
MessageDialog dialog= new OptionalMessageDialog(id, parent, title, titleImage, message, dialogType, buttonLabels, defaultButtonIndex);
return dialog.open();
}
protected OptionalMessageDialog(String id, Shell parent, String title, Image titleImage, String message, int dialogType, String[] buttonLabels, int defaultButtonIndex) {
super(parent, title, titleImage, message, dialogType, buttonLabels, defaultButtonIndex);
fId= id;
}
protected Control createCustomArea(Composite parent) {
Composite composite= new Composite(parent, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
fHideDialogCheckBox= new Button(composite, SWT.CHECK | SWT.LEFT);
fHideDialogCheckBox.setText(CHECKBOX_TEXT);
fHideDialogCheckBox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setDialogEnabled(fId, !((Button)e.widget).getSelection());
}
});
applyDialogFont(fHideDialogCheckBox);
return fHideDialogCheckBox;
}
//--------------- Configuration handling --------------
/**
* Returns this dialog
*
* @return the settings to be used
*/
private static IDialogSettings getDialogSettings() {
IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings();
settings= settings.getSection(STORE_ID);
if (settings == null)
settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(STORE_ID);
return settings;
}
/**
* Answers whether the optional dialog is enabled and should be shown.
*/
public static boolean isDialogEnabled(String key) {
IDialogSettings settings= getDialogSettings();
return !settings.getBoolean(key);
}
/**
* Sets whether the optional dialog is enabled and should be shown.
*/
public static void setDialogEnabled(String key, boolean isEnabled) {
IDialogSettings settings= getDialogSettings();
settings.put(key, !isEnabled);
}
/**
* Clears all remembered information about hidden dialogs
*/
public static void clearAllRememberedStates() {
IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings();
settings.addNewSection(STORE_ID);
}
}

View file

@ -2271,9 +2271,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IR
setAction("ContentAssistProposal", action); //$NON-NLS-1$
markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
action = new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistTip.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
action= new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistContextInformation.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
setAction("ContentAssistTip", action); //$NON-NLS-1$
setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
markAsStateDependentAction("ContentAssistContextInformation", true); //$NON-NLS-1$
action = new OpenDeclarationsAction(this);
action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_DECL);
@ -2983,10 +2984,11 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IR
protected String[] collectContextMenuPreferencePages() {
// Add C/C++ Editor relevant pages
String[] parentPrefPageIds = super.collectContextMenuPreferencePages();
String[] prefPageIds = new String[parentPrefPageIds.length + 8];
String[] prefPageIds = new String[parentPrefPageIds.length + 9];
int nIds = 0;
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CEditorPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeAssistPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.HoverPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.FoldingPreferencePage"; //$NON-NLS-1$
prefPageIds[nIds++] = "org.eclipse.cdt.ui.preferences.CodeColoringPreferencePage"; //$NON-NLS-1$

View file

@ -0,0 +1,151 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
/**
* Action to run content assist on a specific proposal category.
*
* @since 4.0
*/
final class SpecificContentAssistAction extends Action implements IUpdate {
/**
* The category represented by this action.
*/
private final CompletionProposalCategory fCategory;
/**
* The content assist executor.
*/
private final SpecificContentAssistExecutor fExecutor= new SpecificContentAssistExecutor(CompletionProposalComputerRegistry.getDefault());
/**
* The editor.
*/
private CEditor fEditor;
/**
* Creates a new action for a certain proposal category.
*
* @param category
*/
public SpecificContentAssistAction(CompletionProposalCategory category) {
fCategory= category;
setText(category.getName());
setImageDescriptor(category.getImageDescriptor());
setActionDefinitionId("org.eclipse.cdt.ui.specific_content_assist.command"); //$NON-NLS-1$
}
/*
* @see org.eclipse.jface.action.Action#run()
*/
public void run() {
ITextEditor editor= getActiveEditor();
if (editor == null)
return;
fExecutor.invokeContentAssist(editor, fCategory.getId());
return;
}
private ITextEditor getActiveEditor() {
return fEditor;
}
/**
* Sets the active editor part.
*
* @param part the editor, possibly <code>null</code>
*/
public void setActiveEditor(IEditorPart part) {
CEditor editor;
if (part instanceof CEditor)
editor= (CEditor) part;
else
editor= null;
fEditor= editor;
setEnabled(computeEnablement(fEditor));
}
private boolean computeEnablement(ITextEditor editor) {
if (editor == null)
return false;
ITextOperationTarget target= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
boolean hasContentAssist= target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
if (!hasContentAssist)
return false;
ISelection selection= editor.getSelectionProvider().getSelection();
return isValidSelection(selection);
}
/**
* Computes the partition type at the selection start and checks whether the proposal category
* has any computers for this partition.
*
* @param selection the selection
* @return <code>true</code> if there are any computers for the selection
*/
private boolean isValidSelection(ISelection selection) {
if (!(selection instanceof ITextSelection))
return false;
int offset= ((ITextSelection) selection).getOffset();
IDocument document= getDocument();
if (document == null)
return false;
String contentType;
try {
contentType= TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, true);
} catch (BadLocationException x) {
return false;
}
return fCategory.hasComputers(contentType);
}
private IDocument getDocument() {
Assert.isTrue(fEditor != null);
IDocumentProvider provider= fEditor.getDocumentProvider();
if (provider == null)
return null;
IDocument document= provider.getDocument(fEditor.getEditorInput());
return document;
}
/*
* @see org.eclipse.ui.texteditor.IUpdate#update()
*/
public void update() {
setEnabled(computeEnablement(fEditor));
}
}

View file

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
/**
* A content assist executor can invoke content assist for a specific proposal category on an editor.
*
* @since 4.0
*/
public final class SpecificContentAssistExecutor {
private final CompletionProposalComputerRegistry fRegistry;
/**
* Creates a new executor.
*
* @param registry the computer registry to use for the enablement of proposal categories
*/
public SpecificContentAssistExecutor(CompletionProposalComputerRegistry registry) {
Assert.isNotNull(registry);
fRegistry= registry;
}
/**
* Invokes content assist on <code>editor</code>, showing only proposals computed by the
* <code>CompletionProposalCategory</code> with the given <code>categoryId</code>.
*
* @param editor the editor to invoke code assist on
* @param categoryId the id of the proposal category to show proposals for
*/
public void invokeContentAssist(final ITextEditor editor, String categoryId) {
Collection categories= fRegistry.getProposalCategories();
boolean[] inclusionState= new boolean[categories.size()];
boolean[] separateState= new boolean[categories.size()];
int i= 0;
for (Iterator it= categories.iterator(); it.hasNext(); i++) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
inclusionState[i]= cat.isIncluded();
cat.setIncluded(cat.getId().equals(categoryId));
separateState[i]= cat.isSeparateCommand();
cat.setSeparateCommand(false);
}
try {
ITextOperationTarget target= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
if (target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS))
target.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
} finally {
i= 0;
for (Iterator it= categories.iterator(); it.hasNext(); i++) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
cat.setIncluded(inclusionState[i]);
cat.setSeparateCommand(separateState[i]);
}
}
}
}

View file

@ -0,0 +1,698 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.IParameter;
import org.eclipse.core.commands.Parameterization;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalCategory;
import org.eclipse.cdt.internal.ui.text.contentassist.CompletionProposalComputerRegistry;
import org.eclipse.cdt.internal.ui.util.Messages;
import org.eclipse.cdt.internal.ui.util.PixelConverter;
import org.eclipse.cdt.internal.ui.util.SWTUtil;
/**
*
* @since 3.2
*/
final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock {
private static final Key PREF_EXCLUDED_CATEGORIES= getCDTUIKey(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
private static final Key PREF_CATEGORY_ORDER= getCDTUIKey(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
private static Key[] getAllKeys() {
return new Key[] {
PREF_EXCLUDED_CATEGORIES,
PREF_CATEGORY_ORDER,
};
}
private final class DefaultTableLabelProvider extends LabelProvider implements ITableLabelProvider {
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0)
return ((ModelElement) element).getImage();
return null;
}
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
public String getColumnText(Object element, int columnIndex) {
switch (columnIndex) {
case 0:
return ((ModelElement) element).getName();
case 1:
return ((ModelElement) element).getKeybindingAsString();
default:
Assert.isTrue(false);
return null;
}
}
/*
* @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
*/
public String getText(Object element) {
return getColumnText(element, 0); // needed to make the sorter work
}
}
private final class SeparateTableLabelProvider extends LabelProvider implements ITableLabelProvider {
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0)
return ((ModelElement) element).getImage();
return null;
}
/*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
public String getColumnText(Object element, int columnIndex) {
switch (columnIndex) {
case 0:
return ((ModelElement) element).getName();
default:
Assert.isTrue(false);
return null;
}
}
}
private final Comparator fCategoryComparator= new Comparator() {
private int getRank(Object o) {
return ((ModelElement) o).getRank();
}
public int compare(Object o1, Object o2) {
return getRank(o1) - getRank(o2);
}
};
private final class PreferenceModel {
private static final int LIMIT= 0xffff;
private static final String COLON= ":"; //$NON-NLS-1$
private static final String SEPARATOR= "\0"; //$NON-NLS-1$
private final List fElements;
/**
* The read-only list of elements.
*/
final List elements;
public PreferenceModel(CompletionProposalComputerRegistry registry) {
List categories= registry.getProposalCategories();
fElements= new ArrayList();
for (Iterator it= categories.iterator(); it.hasNext();) {
CompletionProposalCategory category= (CompletionProposalCategory) it.next();
if (category.hasComputers()) {
fElements.add(new ModelElement(category, this));
}
}
Collections.sort(fElements, fCategoryComparator);
elements= Collections.unmodifiableList(fElements);
}
public void moveUp(ModelElement category) {
int index= fElements.indexOf(category);
if (index > 0) {
Object item= fElements.remove(index);
fElements.add(index - 1, item);
writeOrderPreference(null, false);
}
}
public void moveDown(ModelElement category) {
int index= fElements.indexOf(category);
if (index < fElements.size() - 1) {
Object item= fElements.remove(index);
fElements.add(index + 1, item);
writeOrderPreference(null, false);
}
}
private void writeInclusionPreference(ModelElement changed, boolean isInDefaultCategory) {
StringBuffer buf= new StringBuffer();
for (Iterator it= fElements.iterator(); it.hasNext();) {
ModelElement item= (ModelElement) it.next();
boolean included= changed == item ? isInDefaultCategory : item.isInDefaultCategory();
if (!included)
buf.append(item.getId() + SEPARATOR);
}
String newValue= buf.toString();
String oldValue= setValue(PREF_EXCLUDED_CATEGORIES, newValue);
validateSettings(PREF_EXCLUDED_CATEGORIES, oldValue, newValue);
}
private void writeOrderPreference(ModelElement changed, boolean isSeparate) {
StringBuffer buf= new StringBuffer();
int i= 0;
for (Iterator it= fElements.iterator(); it.hasNext(); i++) {
ModelElement item= (ModelElement) it.next();
boolean separate= changed == item ? isSeparate : item.isSeparateCommand();
int rank= separate ? i : i + LIMIT;
buf.append(item.getId() + COLON + rank + SEPARATOR);
}
String newValue= buf.toString();
String oldValue= setValue(PREF_CATEGORY_ORDER, newValue);
validateSettings(PREF_CATEGORY_ORDER, oldValue, newValue);
}
private boolean readInclusionPreference(CompletionProposalCategory cat) {
String[] ids= getTokens(getValue(PREF_EXCLUDED_CATEGORIES), SEPARATOR);
for (int i= 0; i < ids.length; i++) {
if (ids[i].equals(cat.getId()))
return false;
}
return true;
}
private int readOrderPreference(CompletionProposalCategory cat) {
String[] sortOrderIds= getTokens(getValue(PREF_CATEGORY_ORDER), SEPARATOR);
for (int i= 0; i < sortOrderIds.length; i++) {
String[] idAndRank= getTokens(sortOrderIds[i], COLON);
if (idAndRank[0].equals(cat.getId()))
return Integer.parseInt(idAndRank[1]);
}
return LIMIT + 1;
}
public void update() {
Collections.sort(fElements, fCategoryComparator);
}
}
private final class ModelElement {
private final CompletionProposalCategory fCategory;
private final Command fCommand;
private final IParameter fParam;
private final PreferenceModel fPreferenceModel;
ModelElement(CompletionProposalCategory category, PreferenceModel model) {
fCategory= category;
ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
fCommand= commandSvc.getCommand("org.eclipse.cdt.ui.specific_content_assist.command"); //$NON-NLS-1$
IParameter type;
try {
type= fCommand.getParameters()[0];
} catch (NotDefinedException x) {
Assert.isTrue(false);
type= null;
}
fParam= type;
fPreferenceModel= model;
}
Image getImage() {
return CodeAssistAdvancedConfigurationBlock.this.getImage(fCategory.getImageDescriptor());
}
String getName() {
return fCategory.getDisplayName();
}
String getKeybindingAsString() {
final Parameterization[] params= { new Parameterization(fParam, fCategory.getId()) };
final ParameterizedCommand pCmd= new ParameterizedCommand(fCommand, params);
String key= getKeyboardShortcut(pCmd);
return key;
}
boolean isInDefaultCategory() {
return fPreferenceModel.readInclusionPreference(fCategory);
}
void setInDefaultCategory(boolean included) {
if (included != isInDefaultCategory())
fPreferenceModel.writeInclusionPreference(this, included);
}
String getId() {
return fCategory.getId();
}
int getRank() {
int rank= getInternalRank();
if (rank > PreferenceModel.LIMIT)
return rank - PreferenceModel.LIMIT;
return rank;
}
void moveUp() {
fPreferenceModel.moveUp(this);
}
void moveDown() {
fPreferenceModel.moveDown(this);
}
private int getInternalRank() {
return fPreferenceModel.readOrderPreference(fCategory);
}
boolean isSeparateCommand() {
return getInternalRank() < PreferenceModel.LIMIT;
}
void setSeparateCommand(boolean separate) {
if (separate != isSeparateCommand())
fPreferenceModel.writeOrderPreference(this, separate);
}
void update() {
fCategory.setIncluded(isInDefaultCategory());
int rank= getInternalRank();
fCategory.setSortOrder(rank);
fCategory.setSeparateCommand(rank < PreferenceModel.LIMIT);
}
}
/** element type: {@link ModelElement}. */
private final PreferenceModel fModel;
private final Map fImages= new HashMap();
private CheckboxTableViewer fDefaultViewer;
private CheckboxTableViewer fSeparateViewer;
private Button fUpButton;
private Button fDownButton;
CodeAssistAdvancedConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer container) {
super(statusListener, null, getAllKeys(), container);
fModel= new PreferenceModel(CompletionProposalComputerRegistry.getDefault());
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
*/
protected Control createContents(Composite parent) {
ScrolledPageContent scrolled= new ScrolledPageContent(parent, SWT.H_SCROLL | SWT.V_SCROLL);
scrolled.setExpandHorizontal(true);
scrolled.setExpandVertical(true);
Composite composite= new Composite(scrolled, SWT.NONE);
int columns= 2;
GridLayout layout= new GridLayout(columns, false);
composite.setLayout(layout);
createDefaultLabel(composite, columns);
createDefaultViewer(composite, columns);
createKeysLink(composite, columns);
createFiller(composite, columns);
createSeparateLabel(composite, columns);
createSeparateSection(composite);
createFiller(composite, columns);
updateControls();
if (fModel.elements.size() > 0) {
fDefaultViewer.getTable().select(0);
fSeparateViewer.getTable().select(0);
handleTableSelection();
}
scrolled.setContent(composite);
scrolled.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
return scrolled;
}
private void createDefaultLabel(Composite composite, int h_span) {
final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
String key= getKeyboardShortcut(pCmd);
if (key == null)
key= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_no_shortcut;
PixelConverter pixelConverter= new PixelConverter(composite);
int width= pixelConverter.convertWidthInCharsToPixels(40);
Label label= new Label(composite, SWT.NONE | SWT.WRAP);
label.setText(Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_page_description, new Object[] { key }));
GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
gd.widthHint= width;
label.setLayoutData(gd);
createFiller(composite, h_span);
label= new Label(composite, SWT.NONE | SWT.WRAP);
label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_description);
gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
gd.widthHint= width;
label.setLayoutData(gd);
}
private void createDefaultViewer(Composite composite, int h_span) {
fDefaultViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
Table table= fDefaultViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(false);
table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false, h_span, 1));
TableColumn nameColumn= new TableColumn(table, SWT.NONE);
nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_category_column_title);
nameColumn.setResizable(false);
TableColumn keyColumn= new TableColumn(table, SWT.NONE);
keyColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title);
keyColumn.setResizable(false);
fDefaultViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
boolean checked= event.getChecked();
ModelElement element= (ModelElement) event.getElement();
element.setInDefaultCategory(checked);
}
});
fDefaultViewer.setContentProvider(new ArrayContentProvider());
DefaultTableLabelProvider labelProvider= new DefaultTableLabelProvider();
fDefaultViewer.setLabelProvider(labelProvider);
fDefaultViewer.setInput(fModel.elements);
fDefaultViewer.setComparator(new ViewerComparator()); // sort alphabetically
final int ICON_AND_CHECKBOX_WITH= 50;
final int HEADER_MARGIN= 20;
int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
int minKeyWidth= computeWidth(table, keyColumn.getText()) + HEADER_MARGIN;
for (int i= 0; i < fModel.elements.size(); i++) {
minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
minKeyWidth= Math.max(minKeyWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 1)));
}
nameColumn.setWidth(minNameWidth);
keyColumn.setWidth(minKeyWidth);
}
private void createKeysLink(Composite composite, int h_span) {
Link link= new Link(composite, SWT.NONE | SWT.WRAP);
link.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_key_binding_hint);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
PreferencesUtil.createPreferenceDialogOn(getShell(), e.text, null, null);
}
});
PixelConverter pixelConverter= new PixelConverter(composite);
int width= pixelConverter.convertWidthInCharsToPixels(40);
// limit the size of the Link as it would take all it can get
GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
gd.widthHint= width;
link.setLayoutData(gd);
}
private void createFiller(Composite composite, int h_span) {
Label filler= new Label(composite, SWT.NONE);
filler.setVisible(false);
filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, h_span, 1));
}
private void createSeparateLabel(Composite composite, int h_span) {
PixelConverter pixelConverter= new PixelConverter(composite);
int width= pixelConverter.convertWidthInCharsToPixels(40);
Label label= new Label(composite, SWT.NONE | SWT.WRAP);
label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_description);
GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
gd.widthHint= width;
label.setLayoutData(gd);
}
private void createSeparateSection(Composite composite) {
createSeparateViewer(composite);
createButtonList(composite);
}
private void createSeparateViewer(Composite composite) {
fSeparateViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
Table table= fSeparateViewer.getTable();
table.setHeaderVisible(false);
table.setLinesVisible(false);
table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1));
TableColumn nameColumn= new TableColumn(table, SWT.NONE);
nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title);
nameColumn.setResizable(false);
fSeparateViewer.setContentProvider(new ArrayContentProvider());
ITableLabelProvider labelProvider= new SeparateTableLabelProvider();
fSeparateViewer.setLabelProvider(labelProvider);
fSeparateViewer.setInput(fModel.elements);
final int ICON_AND_CHECKBOX_WITH= 50;
final int HEADER_MARGIN= 20;
int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
for (int i= 0; i < fModel.elements.size(); i++) {
minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
}
nameColumn.setWidth(minNameWidth);
fSeparateViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
boolean checked= event.getChecked();
ModelElement element= (ModelElement) event.getElement();
element.setSeparateCommand(checked);
}
});
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleTableSelection();
}
});
}
private void createButtonList(Composite parent) {
Composite composite= new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
GridLayout layout= new GridLayout();
layout.marginWidth= 0;
layout.marginHeight= 0;
composite.setLayout(layout);
fUpButton= new Button(composite, SWT.PUSH | SWT.CENTER);
fUpButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Up);
fUpButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
int index= getSelectionIndex();
if (index != -1) {
((ModelElement) fModel.elements.get(index)).moveUp();
fSeparateViewer.refresh();
handleTableSelection();
}
}
});
fUpButton.setLayoutData(new GridData());
SWTUtil.setButtonDimensionHint(fUpButton);
fDownButton= new Button(composite, SWT.PUSH | SWT.CENTER);
fDownButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Down);
fDownButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
int index= getSelectionIndex();
if (index != -1) {
((ModelElement) fModel.elements.get(index)).moveDown();
fSeparateViewer.refresh();
handleTableSelection();
}
}
});
fDownButton.setLayoutData(new GridData());
SWTUtil.setButtonDimensionHint(fDownButton);
}
private void handleTableSelection() {
ModelElement item= getSelectedItem();
if (item != null) {
int index= getSelectionIndex();
fUpButton.setEnabled(index > 0);
fDownButton.setEnabled(index < fModel.elements.size() - 1);
} else {
fUpButton.setEnabled(false);
fDownButton.setEnabled(false);
}
}
private ModelElement getSelectedItem() {
return (ModelElement) ((IStructuredSelection) fSeparateViewer.getSelection()).getFirstElement();
}
private int getSelectionIndex() {
return fSeparateViewer.getTable().getSelectionIndex();
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
*/
protected void updateControls() {
super.updateControls();
fModel.update();
updateCheckedState();
fDefaultViewer.refresh();
fSeparateViewer.refresh();
handleTableSelection();
}
private void updateCheckedState() {
final int size= fModel.elements.size();
List defaultChecked= new ArrayList(size);
List separateChecked= new ArrayList(size);
for (Iterator it= fModel.elements.iterator(); it.hasNext();) {
ModelElement element= (ModelElement) it.next();
if (element.isInDefaultCategory())
defaultChecked.add(element);
if (element.isSeparateCommand())
separateChecked.add(element);
}
fDefaultViewer.setCheckedElements(defaultChecked.toArray(new Object[defaultChecked.size()]));
fSeparateViewer.setCheckedElements(separateChecked.toArray(new Object[separateChecked.size()]));
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer)
*/
protected boolean processChanges(IWorkbenchPreferenceContainer container) {
for (Iterator it= fModel.elements.iterator(); it.hasNext();) {
ModelElement item= (ModelElement) it.next();
item.update();
}
return super.processChanges(container);
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String)
*/
protected void validateSettings(Key changedKey, String oldValue, String newValue) {
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
*/
protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
// no builds triggered by our settings
return null;
}
/*
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#dispose()
*/
public void dispose() {
for (Iterator it= fImages.values().iterator(); it.hasNext();) {
Image image= (Image) it.next();
image.dispose();
}
super.dispose();
}
private int computeWidth(Control control, String name) {
if (name == null)
return 0;
GC gc= new GC(control);
try {
gc.setFont(JFaceResources.getDialogFont());
return gc.stringExtent(name).x + 10;
} finally {
gc.dispose();
}
}
private static String getKeyboardShortcut(ParameterizedCommand command) {
final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
final Binding[] bindings= bindingSvc.getBindings();
for (int i= 0; i < bindings.length; i++) {
Binding binding= bindings[i];
if (command.equals(binding.getParameterizedCommand())) {
TriggerSequence triggers= binding.getTriggerSequence();
return triggers.format();
}
}
return null;
}
private Image getImage(ImageDescriptor imgDesc) {
if (imgDesc == null)
return null;
Image img= (Image) fImages.get(imgDesc);
if (img == null) {
img= imgDesc.createImage(false);
fImages.put(imgDesc, img);
}
return img;
}
}

View file

@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.core.resources.IProject;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferencePage {
private CodeAssistAdvancedConfigurationBlock fConfigurationBlock;
public void createControl(Composite parent) {
IWorkbenchPreferenceContainer container= (IWorkbenchPreferenceContainer) getContainer();
fConfigurationBlock= new CodeAssistAdvancedConfigurationBlock(getNewStatusChangedListener(), container);
super.createControl(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.C_EDITOR_PREF_PAGE);
}
protected Control createPreferenceContent(Composite composite) {
return fConfigurationBlock.createContents(composite);
}
protected boolean hasProjectSpecificOptions(IProject project) {
return false;
}
protected String getPreferencePageID() {
return "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced"; //$NON-NLS-1$
}
protected String getPropertyPageID() {
return null;
}
/*
* @see org.eclipse.jface.dialogs.DialogPage#dispose()
*/
public void dispose() {
if (fConfigurationBlock != null) {
fConfigurationBlock.dispose();
}
super.dispose();
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
*/
protected void performDefaults() {
super.performDefaults();
if (fConfigurationBlock != null) {
fConfigurationBlock.performDefaults();
}
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#performOk()
*/
public boolean performOk() {
if (fConfigurationBlock != null && !fConfigurationBlock.performOk()) {
return false;
}
return super.performOk();
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#performApply()
*/
public void performApply() {
if (fConfigurationBlock != null) {
fConfigurationBlock.performApply();
}
}
}

View file

@ -45,13 +45,13 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.AUTOACTIVATION_DELAY));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.AUTOINSERT));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PREFIX_COMPLETION));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.TIMEOUT_DELAY));
// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.TIMEOUT_DELAY));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOT));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_ARROW));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOUBLECOLON));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.SHOW_DOCUMENTED_PROPOSALS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ORDER_PROPOSALS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE));
// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.SHOW_DOCUMENTED_PROPOSALS));
// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ORDER_PROPOSALS));
// overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.CURRENT_FILE_SEARCH_SCOPE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PROJECT_SEARCH_SCOPE));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PROPOSALS_FILTER));
@ -106,8 +106,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_sortingSection_title;
Group sortingGroup = addGroupBox(contentAssistComposite, label, 2);
label= PreferencesMessages.CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder;
addCheckBox(sortingGroup, label, ContentAssistPreference.ORDER_PROPOSALS, 0);
// label= PreferencesMessages.CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder;
// addCheckBox(sortingGroup, label, ContentAssistPreference.ORDER_PROPOSALS, 0);
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_proposalFilterSelect ;
addComboBox(sortingGroup, label, ContentAssistPreference.PROPOSALS_FILTER, 20, 0);
@ -147,7 +147,7 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
store.setDefault(ContentAssistPreference.CURRENT_FILE_SEARCH_SCOPE, true);
store.setDefault(ContentAssistPreference.PROJECT_SEARCH_SCOPE, false);
store.setDefault(ContentAssistPreference.TIMEOUT_DELAY, 3000);
// store.setDefault(ContentAssistPreference.TIMEOUT_DELAY, 3000);
store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_DOT, true);
store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_ARROW, true);
@ -156,8 +156,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
store.setDefault(ContentAssistPreference.AUTOINSERT, true);
store.setDefault(ContentAssistPreference.PREFIX_COMPLETION, true);
store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
// store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
// store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
store.setDefault(ContentAssistPreference.PROPOSALS_FILTER, ProposalFilterPreferencesUtil.getProposalFilternamesAsString()); // $NON_NLS 1$
}

View file

@ -21,44 +21,16 @@ public final class PreferencesMessages extends NLS {
// Do not instantiate
}
public static String OptionsConfigurationBlock_builderror_title;
public static String OptionsConfigurationBlock_builderror_message;
public static String OptionsConfigurationBlock_buildall_taskname;
public static String OptionsConfigurationBlock_buildproject_taskname;
public static String OptionsConfigurationBlock_parseerror_title;
public static String OptionsConfigurationBlock_parseerror_message;
public static String OptionsConfigurationBlock_parseall_taskname;
public static String OptionsConfigurationBlock_parseproject_taskname;
public static String TodoTaskPreferencePage_title;
public static String TodoTaskPropertyPage_useworkspacesettings_label;
public static String TodoTaskPropertyPage_useworkspacesettings_change;
public static String TodoTaskPropertyPage_useprojectsettings_label;
public static String TodoTaskConfigurationBlock_markers_tasks_high_priority;
public static String TodoTaskConfigurationBlock_markers_tasks_normal_priority;
public static String TodoTaskConfigurationBlock_markers_tasks_low_priority;
public static String TodoTaskConfigurationBlock_markers_tasks_label;
public static String TodoTaskConfigurationBlock_markers_tasks_add_button;
public static String TodoTaskConfigurationBlock_markers_tasks_remove_button;
public static String TodoTaskConfigurationBlock_markers_tasks_edit_button;
public static String TodoTaskConfigurationBlock_markers_tasks_name_column;
public static String TodoTaskConfigurationBlock_markers_tasks_priority_column;
public static String TodoTaskConfigurationBlock_needsbuild_title;
public static String TodoTaskConfigurationBlock_needsfullbuild_message;
public static String TodoTaskConfigurationBlock_needsprojectbuild_message;
public static String TodoTaskConfigurationBlock_needsparse_title;
public static String TodoTaskConfigurationBlock_needsfullparse_message;
public static String TodoTaskConfigurationBlock_needsprojectparse_message;
public static String TodoTaskInputDialog_new_title;
public static String TodoTaskInputDialog_edit_title;
public static String TodoTaskInputDialog_name_label;
public static String TodoTaskInputDialog_priority_label;
public static String TodoTaskInputDialog_priority_high;
public static String TodoTaskInputDialog_priority_normal;
public static String TodoTaskInputDialog_priority_low;
public static String TodoTaskInputDialog_error_enterName;
public static String TodoTaskInputDialog_error_comma;
public static String TodoTaskInputDialog_error_entryExists;
public static String TodoTaskInputDialog_error_noSpace;
public static String CodeAssistAdvancedConfigurationBlock_default_table_category_column_title;
public static String CodeAssistAdvancedConfigurationBlock_default_table_description;
public static String CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title;
public static String CodeAssistAdvancedConfigurationBlock_key_binding_hint;
public static String CodeAssistAdvancedConfigurationBlock_page_description;
public static String CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title;
public static String CodeAssistAdvancedConfigurationBlock_separate_table_description;
public static String CodeAssistAdvancedConfigurationBlock_no_shortcut;
public static String CodeAssistAdvancedConfigurationBlock_Up;
public static String CodeAssistAdvancedConfigurationBlock_Down;
public static String CEditorPreferencePage_link;
public static String CEditorPreferencePage_link_tooltip;
public static String CEditorPreferencePage_colors;

View file

@ -10,56 +10,6 @@
# Anton Leherbauer (Wind River Systems)
###############################################################################
OptionsConfigurationBlock_builderror_title=Preference Changes
OptionsConfigurationBlock_builderror_message=Problem while building. Check log for details.
OptionsConfigurationBlock_buildall_taskname=Build all...
OptionsConfigurationBlock_buildproject_taskname=Build project ''{0}''...
OptionsConfigurationBlock_parseerror_title=Preference Changes
OptionsConfigurationBlock_parseerror_message=Problem while parsing. Check log for details.
OptionsConfigurationBlock_parseall_taskname=Parse all...
OptionsConfigurationBlock_parseproject_taskname=Parse project ''{0}''...
TodoTaskPreferencePage_title=Task Tags
TodoTaskPropertyPage_useworkspacesettings_label=Use &workspace settings
TodoTaskPropertyPage_useworkspacesettings_change=&Configure Workspace Settings...
TodoTaskPropertyPage_useprojectsettings_label=Use pr&oject settings
TodoTaskConfigurationBlock_markers_tasks_high_priority=High
TodoTaskConfigurationBlock_markers_tasks_normal_priority=Normal
TodoTaskConfigurationBlock_markers_tasks_low_priority=Low
TodoTaskConfigurationBlock_markers_tasks_label=&Strings indicating tasks in Java comments:
TodoTaskConfigurationBlock_markers_tasks_add_button=Ne&w...
TodoTaskConfigurationBlock_markers_tasks_remove_button=Remo&ve
TodoTaskConfigurationBlock_markers_tasks_edit_button=Edi&t...
TodoTaskConfigurationBlock_markers_tasks_name_column=Tag
TodoTaskConfigurationBlock_markers_tasks_priority_column=Priority
TodoTaskConfigurationBlock_needsbuild_title=Task Tags Settings Changed
TodoTaskConfigurationBlock_needsfullbuild_message=The task tags settings have changed. A full rebuild is required to make changes effective. Do the full build now?
TodoTaskConfigurationBlock_needsprojectbuild_message=The task tags settings have changed. A rebuild of the project is required to make changes effective. Do the project build now?
TodoTaskConfigurationBlock_needsparse_title=Task Tags Settings Changed
TodoTaskConfigurationBlock_needsfullparse_message=The task tags settings have changed. A full re-parse is required to make changes effective. Do the full re-parse now?
TodoTaskConfigurationBlock_needsprojectparse_message=The task tags settings have changed. Re-parsing of the project is required to make changes effective. Do the project re-parse now?
TodoTaskInputDialog_new_title=New Task Tag
TodoTaskInputDialog_edit_title=Edit Task Tag
TodoTaskInputDialog_name_label=T&ag:
TodoTaskInputDialog_priority_label=&Priority:
TodoTaskInputDialog_priority_high=High
TodoTaskInputDialog_priority_normal=Normal
TodoTaskInputDialog_priority_low=Low
TodoTaskInputDialog_error_enterName=Enter task tag name.
TodoTaskInputDialog_error_comma=Name cannot contain a comma.
TodoTaskInputDialog_error_entryExists=Entry with the same name already exists.
TodoTaskInputDialog_error_noSpace=Name can not start or end with a whitespace.
CEditorPreferencePage_link=C/C++ Editor Preferences. Note that some preferences may be set on the <a href="org.eclipse.ui.preferencePages.GeneralTextEditor">Text Editors</a> preference page.
CEditorPreferencePage_link_tooltip=Show the shared text editor preferences
@ -87,6 +37,21 @@ CEditorPreferencePage_ContentAssistPage_parameterBackgroundColor=Parameter hint
CEditorPreferencePage_ContentAssistPage_parameterForegroundColor=Parameter hint foreground
CEditorPreferencePage_ContentAssistPage_autoActivationEnableDoubleColon=Enable "::" as trigger
CEditorPreferencePage_ContentAssistPage_sortingSection_title=Sorting and Filtering
# {0} will be replaced by the keyboard shortcut for the command (e.g. "Ctrl+Space", or "no shortcut")
CodeAssistAdvancedConfigurationBlock_page_description=Configure the behavior of the content assist ({0}) command.
# stand-in text if there is no keyboard shortcut in above statement
CodeAssistAdvancedConfigurationBlock_no_shortcut=no shortcut
CodeAssistAdvancedConfigurationBlock_default_table_description=Select the proposal kinds contained in the 'default' content assist list:
CodeAssistAdvancedConfigurationBlock_default_table_category_column_title=Default Proposal Kinds
CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title=Key Binding
# do not translate the href argument (org.eclipse.ui.preferencePages.Keys)
CodeAssistAdvancedConfigurationBlock_key_binding_hint=Individual key bindings can be assigned to each proposal kind on the <a href="org.eclipse.ui.preferencePages.Keys">Keys</a> preference page.
CodeAssistAdvancedConfigurationBlock_separate_table_description=Content assist cycling: Select the proposal kinds that are cycled through when repeatedly invoking content assist:
CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title=Separate Proposal Kinds
CodeAssistAdvancedConfigurationBlock_Up=&Up
CodeAssistAdvancedConfigurationBlock_Down=D&own
CEditorColoringConfigurationBlock_MultiLine=Multi-line comment
CEditorColoringConfigurationBlock_singleLine=Single-line comment
CEditorColoringConfigurationBlock_keywords=Keywords

View file

@ -1,300 +0,0 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.util.SWTUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField;
/**
*/
public class TodoTaskConfigurationBlock extends OptionsConfigurationBlock {
private static final String PREF_TRANSLATION_TASK_TAGS= CCorePreferenceConstants.TRANSLATION_TASK_TAGS;
private static final String PREF_TRANSLATION_TASK_PRIORITIES= CCorePreferenceConstants.TRANSLATION_TASK_PRIORITIES;
private static final String PRIORITY_HIGH= CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH;
private static final String PRIORITY_NORMAL= CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL;
private static final String PRIORITY_LOW= CCorePlugin.TRANSLATION_TASK_PRIORITY_LOW;
public static class TodoTask {
public String name;
public String priority;
}
private static class TodoTaskLabelProvider extends LabelProvider implements ITableLabelProvider {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
*/
public Image getImage(Object element) {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
*/
public String getText(Object element) {
return getColumnText(element, 0);
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
*/
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
*/
public String getColumnText(Object element, int columnIndex) {
TodoTask task= (TodoTask) element;
if (columnIndex == 0) {
return task.name;
}
if (PRIORITY_HIGH.equals(task.priority)) {
return PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_high_priority;
} else if (PRIORITY_NORMAL.equals(task.priority)) {
return PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_normal_priority;
} else if (PRIORITY_LOW.equals(task.priority)) {
return PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_low_priority;
}
return ""; //$NON-NLS-1$
}
}
private IStatus fTaskTagsStatus;
private ListDialogField fTodoTasksList;
public TodoTaskConfigurationBlock(IStatusChangeListener context, ICProject project) {
super(context, project);
TaskTagAdapter adapter= new TaskTagAdapter();
String[] buttons= new String[] {
PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_add_button,
PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_remove_button,
null,
PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_edit_button,
};
fTodoTasksList= new ListDialogField(adapter, buttons, new TodoTaskLabelProvider());
fTodoTasksList.setDialogFieldListener(adapter);
fTodoTasksList.setLabelText(PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_label);
fTodoTasksList.setRemoveButtonIndex(1);
String[] columnsHeaders= new String[] {
PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_name_column,
PreferencesMessages.TodoTaskConfigurationBlock_markers_tasks_priority_column,
};
fTodoTasksList.setTableColumns(new ListDialogField.ColumnsDescription(columnsHeaders, true));
unpackTodoTasks();
if (fTodoTasksList.getSize() > 0) {
fTodoTasksList.selectFirstElement();
} else {
fTodoTasksList.enableButton(3, false);
}
fTaskTagsStatus= new StatusInfo();
}
protected final String[] getAllKeys() {
return new String[] {
PREF_TRANSLATION_TASK_TAGS, PREF_TRANSLATION_TASK_PRIORITIES
};
}
public class TaskTagAdapter implements IListAdapter, IDialogFieldListener {
private boolean canEdit(ListDialogField field) {
return field.getSelectedElements().size() == 1;
}
public void customButtonPressed(ListDialogField field, int index) {
doTodoButtonPressed(index);
}
public void selectionChanged(ListDialogField field) {
field.enableButton(3, canEdit(field));
}
public void doubleClicked(ListDialogField field) {
if (canEdit(field)) {
doTodoButtonPressed(3);
}
}
public void dialogFieldChanged(DialogField field) {
validateSettings(PREF_TRANSLATION_TASK_TAGS, null);
}
}
protected Control createContents(Composite parent) {
setShell(parent.getShell());
Composite markersComposite= createMarkersTabContent(parent);
validateSettings(null, null);
return markersComposite;
}
private Composite createMarkersTabContent(Composite folder) {
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 2;
Composite markersComposite= new Composite(folder, SWT.NULL);
markersComposite.setLayout(layout);
fTodoTasksList.doFillIntoGrid(markersComposite, 3);
LayoutUtil.setHorizontalSpan(fTodoTasksList.getLabelControl(null), 2);
Table table= fTodoTasksList.getTableViewer().getTable();
GridData data= (GridData)fTodoTasksList.getListControl(null).getLayoutData();
data.grabExcessHorizontalSpace= true;
data.verticalAlignment= 0;
data.heightHint= SWTUtil.getTableHeightHint(table, 6);
return markersComposite;
}
protected void validateSettings(String changedKey, String newValue) {
if (changedKey != null) {
if (PREF_TRANSLATION_TASK_TAGS.equals(changedKey)) {
fTaskTagsStatus= validateTaskTags();
} else {
return;
}
} else {
fTaskTagsStatus= validateTaskTags();
}
IStatus status= fTaskTagsStatus; //StatusUtil.getMostSevere(new IStatus[] { fTaskTagsStatus });
fContext.statusChanged(status);
}
private IStatus validateTaskTags() {
return new StatusInfo();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#performOk(boolean)
*/
public boolean performOk(boolean enabled) {
packTodoTasks();
return super.performOk(enabled);
}
protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
String title= PreferencesMessages.TodoTaskConfigurationBlock_needsbuild_title;
String message;
if (fProject == null) {
message= PreferencesMessages.TodoTaskConfigurationBlock_needsfullbuild_message;
} else {
message= PreferencesMessages.TodoTaskConfigurationBlock_needsprojectbuild_message;
}
return new String[] { title, message };
}
protected String[] getFullReParseDialogStrings(boolean workspaceSettings) {
String title= PreferencesMessages.TodoTaskConfigurationBlock_needsparse_title;
String message;
if (fProject == null) {
message= PreferencesMessages.TodoTaskConfigurationBlock_needsfullparse_message;
} else {
message= PreferencesMessages.TodoTaskConfigurationBlock_needsprojectparse_message;
}
return new String[] { title, message };
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
*/
protected void updateControls() {
unpackTodoTasks();
}
private void unpackTodoTasks() {
String currTags= (String) fWorkingValues.get(PREF_TRANSLATION_TASK_TAGS);
String currPrios= (String) fWorkingValues.get(PREF_TRANSLATION_TASK_PRIORITIES);
String[] tags= getTokens(currTags, ","); //$NON-NLS-1$
String[] prios= getTokens(currPrios, ","); //$NON-NLS-1$
ArrayList elements= new ArrayList(tags.length);
for (int i= 0; i < tags.length; i++) {
TodoTask task= new TodoTask();
task.name= tags[i].trim();
task.priority= (i < prios.length) ? prios[i] : PRIORITY_NORMAL;
elements.add(task);
}
fTodoTasksList.setElements(elements);
}
private void packTodoTasks() {
StringBuffer tags= new StringBuffer();
StringBuffer prios= new StringBuffer();
List list= fTodoTasksList.getElements();
for (int i= 0; i < list.size(); i++) {
if (i > 0) {
tags.append(',');
prios.append(',');
}
TodoTask elem= (TodoTask) list.get(i);
tags.append(elem.name);
prios.append(elem.priority);
}
fWorkingValues.put(PREF_TRANSLATION_TASK_TAGS, tags.toString());
fWorkingValues.put(PREF_TRANSLATION_TASK_PRIORITIES, prios.toString());
}
void doTodoButtonPressed(int index) {
TodoTask edited= null;
if (index != 0) {
edited= (TodoTask) fTodoTasksList.getSelectedElements().get(0);
}
TodoTaskInputDialog dialog= new TodoTaskInputDialog(getShell(), edited, fTodoTasksList.getElements());
if (dialog.open() == Window.OK) {
if (edited != null) {
fTodoTasksList.replaceElement(edited, dialog.getResult());
} else {
fTodoTasksList.addElement(dialog.getResult());
}
}
}
}

View file

@ -1,162 +0,0 @@
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.dialogs.StatusDialog;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.preferences.TodoTaskConfigurationBlock.TodoTask;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ComboDialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField;
/**
* Dialog to enter a na new task tag
*/
public class TodoTaskInputDialog extends StatusDialog {
private class CompilerTodoTaskInputAdapter implements IDialogFieldListener {
public void dialogFieldChanged(DialogField field) {
doValidation();
}
}
private StringDialogField fNameDialogField;
private ComboDialogField fPriorityDialogField;
private List fExistingNames;
public TodoTaskInputDialog(Shell parent, TodoTask task, List existingEntries) {
super(parent);
fExistingNames= new ArrayList(existingEntries.size());
for (int i= 0; i < existingEntries.size(); i++) {
TodoTask curr= (TodoTask) existingEntries.get(i);
if (!curr.equals(task)) {
fExistingNames.add(curr.name);
}
}
if (task == null) {
setTitle(PreferencesMessages.TodoTaskInputDialog_new_title);
} else {
setTitle(PreferencesMessages.TodoTaskInputDialog_edit_title);
}
CompilerTodoTaskInputAdapter adapter= new CompilerTodoTaskInputAdapter();
fNameDialogField= new StringDialogField();
fNameDialogField.setLabelText(PreferencesMessages.TodoTaskInputDialog_name_label);
fNameDialogField.setDialogFieldListener(adapter);
fNameDialogField.setText((task != null) ? task.name : ""); //$NON-NLS-1$
String[] items= new String[] {
PreferencesMessages.TodoTaskInputDialog_priority_high,
PreferencesMessages.TodoTaskInputDialog_priority_normal,
PreferencesMessages.TodoTaskInputDialog_priority_low
};
fPriorityDialogField= new ComboDialogField(SWT.READ_ONLY);
fPriorityDialogField.setLabelText(PreferencesMessages.TodoTaskInputDialog_priority_label);
fPriorityDialogField.setItems(items);
if (task != null) {
if (CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH.equals(task.priority)) {
fPriorityDialogField.selectItem(0);
} else if (CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL.equals(task.priority)) {
fPriorityDialogField.selectItem(1);
} else {
fPriorityDialogField.selectItem(2);
}
} else {
fPriorityDialogField.selectItem(1);
}
}
public TodoTask getResult() {
TodoTask task= new TodoTask();
task.name= fNameDialogField.getText().trim();
switch (fPriorityDialogField.getSelectionIndex()) {
case 0 :
task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_HIGH;
break;
case 1 :
task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_NORMAL;
break;
default :
task.priority= CCorePlugin.TRANSLATION_TASK_PRIORITY_LOW;
break;
}
return task;
}
protected Control createDialogArea(Composite parent) {
Composite composite= (Composite) super.createDialogArea(parent);
Composite inner= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 2;
inner.setLayout(layout);
fNameDialogField.doFillIntoGrid(inner, 2);
fPriorityDialogField.doFillIntoGrid(inner, 2);
LayoutUtil.setHorizontalGrabbing(fNameDialogField.getTextControl(null));
LayoutUtil.setWidthHint(fNameDialogField.getTextControl(null), convertWidthInCharsToPixels(45));
fNameDialogField.postSetFocusOnDialogField(parent.getDisplay());
applyDialogFont(composite);
return composite;
}
void doValidation() {
StatusInfo status= new StatusInfo();
String newText= fNameDialogField.getText();
if (newText.length() == 0) {
status.setError(PreferencesMessages.TodoTaskInputDialog_error_enterName);
} else {
if (newText.indexOf(',') != -1) {
status.setError(PreferencesMessages.TodoTaskInputDialog_error_comma);
} else if (fExistingNames.contains(newText)) {
status.setError(PreferencesMessages.TodoTaskInputDialog_error_entryExists);
} else if (Character.isWhitespace(newText.charAt(0)) || Character.isWhitespace(newText.charAt(newText.length() - 1))) {
status.setError(PreferencesMessages.TodoTaskInputDialog_error_noSpace);
}
}
updateStatus(status);
}
/*
* @see org.eclipse.jface.window.Window#configureShell(Shell)
*/
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, ICHelpContextIds.TODO_TASK_INPUT_DIALOG);
}
}

View file

@ -1,99 +0,0 @@
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
/*
* The page to configure the compiler options.
*/
public class TodoTaskPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IStatusChangeListener {
public static final String ID= "org.eclipse.cdt.ui.propertyPages.TodoTaskPropertyPage"; //$NON-NLS-1$
private TodoTaskConfigurationBlock fConfigurationBlock;
public TodoTaskPreferencePage() {
setPreferenceStore(CUIPlugin.getDefault().getPreferenceStore());
//setDescription(PreferencesMessages.getString("TodoTaskPreferencePage.description")); //$NON-NLS-1$
// only used when page is shown programatically
setTitle(PreferencesMessages.TodoTaskPreferencePage_title);
fConfigurationBlock= new TodoTaskConfigurationBlock(this, null);
}
/*
* @see IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
}
/*
* @see PreferencePage#createControl(Composite)
*/
public void createControl(Composite parent) {
// added for 1GEUGE6: ITPJUI:WIN2000 - Help is the same on all preference pages
super.createControl(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.TODO_TASK_PREFERENCE_PAGE);
}
/*
* @see PreferencePage#createContents(Composite)
*/
protected Control createContents(Composite parent) {
Control result= fConfigurationBlock.createContents(parent);
Dialog.applyDialogFont(result);
return result;
}
/*
* @see IPreferencePage#performOk()
*/
public boolean performOk() {
if (!fConfigurationBlock.performOk(true)) {
return false;
}
return super.performOk();
}
/*
* @see PreferencePage#performDefaults()
*/
protected void performDefaults() {
fConfigurationBlock.performDefaults();
super.performDefaults();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.ui.wizards.IStatusChangeListener#statusChanged(org.eclipse.core.runtime.IStatus)
*/
public void statusChanged(IStatus status) {
setValid(!status.matches(IStatus.ERROR));
StatusUtil.applyToStatusLine(this, status);
}
}

View file

@ -1,220 +0,0 @@
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.preference.PreferenceNode;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
/**
* Property page used to configure project specific task tags settings
*/
public class TodoTaskPropertyPage extends PropertyPage {
private TodoTaskConfigurationBlock fConfigurationBlock;
private Control fConfigurationBlockControl;
private ControlEnableState fBlockEnableState;
private SelectionButtonDialogField fUseWorkspaceSettings;
private SelectionButtonDialogField fChangeWorkspaceSettings;
private SelectionButtonDialogField fUseProjectSettings;
IStatus fBlockStatus;
public TodoTaskPropertyPage() {
fBlockStatus= new StatusInfo();
fBlockEnableState= null;
IDialogFieldListener listener= new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
doDialogFieldChanged(field);
}
};
fUseWorkspaceSettings= new SelectionButtonDialogField(SWT.RADIO);
fUseWorkspaceSettings.setDialogFieldListener(listener);
fUseWorkspaceSettings.setLabelText(PreferencesMessages.TodoTaskPropertyPage_useworkspacesettings_label);
fChangeWorkspaceSettings= new SelectionButtonDialogField(SWT.PUSH);
fChangeWorkspaceSettings.setLabelText(PreferencesMessages.TodoTaskPropertyPage_useworkspacesettings_change);
fChangeWorkspaceSettings.setDialogFieldListener(listener);
fUseWorkspaceSettings.attachDialogField(fChangeWorkspaceSettings);
fUseProjectSettings= new SelectionButtonDialogField(SWT.RADIO);
fUseProjectSettings.setDialogFieldListener(listener);
fUseProjectSettings.setLabelText(PreferencesMessages.TodoTaskPropertyPage_useprojectsettings_label);
}
/*
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
super.createControl(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ICHelpContextIds.TODO_TASK_PROPERTY_PAGE);
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#createContents(Composite)
*/
protected Control createContents(Composite parent) {
IStatusChangeListener listener= new IStatusChangeListener() {
public void statusChanged(IStatus status) {
fBlockStatus= status;
doStatusChanged();
}
};
fConfigurationBlock= new TodoTaskConfigurationBlock(listener, getProject());
Composite composite= new Composite(parent, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 1;
composite.setLayout(layout);
fUseWorkspaceSettings.doFillIntoGrid(composite, 1);
LayoutUtil.setHorizontalGrabbing(fUseWorkspaceSettings.getSelectionButton(null));
fChangeWorkspaceSettings.doFillIntoGrid(composite, 1);
GridData data= (GridData) fChangeWorkspaceSettings.getSelectionButton(null).getLayoutData();
data.horizontalIndent= convertWidthInCharsToPixels(3);
data.horizontalAlignment= GridData.BEGINNING;
fUseProjectSettings.doFillIntoGrid(composite, 1);
data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL );
data.horizontalSpan= 1;
data.horizontalIndent= convertWidthInCharsToPixels(2);
fConfigurationBlockControl= fConfigurationBlock.createContents(composite);
fConfigurationBlockControl.setLayoutData(data);
boolean useProjectSettings= fConfigurationBlock.hasProjectSpecificOptions();
fUseProjectSettings.setSelection(useProjectSettings);
fUseWorkspaceSettings.setSelection(!useProjectSettings);
updateEnableState();
Dialog.applyDialogFont(composite);
return composite;
}
private boolean useProjectSettings() {
return fUseProjectSettings.isSelected();
}
void doDialogFieldChanged(DialogField field) {
if (field == fChangeWorkspaceSettings) {
TodoTaskPreferencePage page= new TodoTaskPreferencePage();
showPreferencePage(TodoTaskPreferencePage.ID, page);
} else {
updateEnableState();
doStatusChanged();
}
}
/**
* Method statusChanged.
*/
void doStatusChanged() {
updateStatus(useProjectSettings() ? fBlockStatus : new StatusInfo());
}
/**
* Method getProject.
*/
private ICProject getProject() {
return (ICProject) getElement().getAdapter(ICElement.class);
}
private void updateEnableState() {
if (useProjectSettings()) {
if (fBlockEnableState != null) {
fBlockEnableState.restore();
fBlockEnableState= null;
}
} else {
if (fBlockEnableState == null) {
fBlockEnableState= ControlEnableState.disable(fConfigurationBlockControl);
}
}
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#performDefaults()
*/
protected void performDefaults() {
if (useProjectSettings()) {
fUseProjectSettings.setSelection(false);
fUseWorkspaceSettings.setSelection(true);
fConfigurationBlock.performDefaults();
}
super.performDefaults();
}
/*
* @see org.eclipse.jface.preference.IPreferencePage#performOk()
*/
public boolean performOk() {
return fConfigurationBlock.performOk(useProjectSettings());
}
private void updateStatus(IStatus status) {
setValid(!status.matches(IStatus.ERROR));
StatusUtil.applyToStatusLine(this, status);
}
private boolean showPreferencePage(String id, IPreferencePage page) {
final IPreferenceNode targetNode = new PreferenceNode(id, page);
PreferenceManager manager = new PreferenceManager();
manager.addToRoot(targetNode);
final PreferenceDialog dialog = new PreferenceDialog(getShell(), manager);
final boolean [] result = new boolean[] { false };
BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
public void run() {
dialog.create();
dialog.setMessage(targetNode.getLabelText());
result[0]= (dialog.open() == Window.OK);
}
});
return result[0];
}
}

View file

@ -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
@ -58,6 +58,8 @@ public final class CHeuristicScanner implements Symbols {
private static final char EQUAL= '=';
private static final char LANGLE= '<';
private static final char RANGLE= '>';
private static final char DOT= '.';
private static final char MINUS= '-';
/**
* Specifies the stop condition, upon which the <code>scanXXX</code> methods will decide whether
@ -401,6 +403,10 @@ public final class CHeuristicScanner implements Symbols {
return TokenLESSTHAN;
case RANGLE:
return TokenGREATERTHAN;
case DOT:
return TokenDOT;
case MINUS:
return TokenMINUS;
}
// else
@ -551,13 +557,31 @@ public final class CHeuristicScanner implements Symbols {
* @return the matching peer character position, or <code>NOT_FOUND</code>
*/
public int findOpeningPeer(int start, char openingPeer, char closingPeer) {
return findOpeningPeer(start, CHeuristicScanner.UNBOUND, openingPeer, closingPeer);
}
/**
* Returns the position of the opening peer character (backward search). Any scopes introduced by closing peers
* are skipped. All peers accounted for must reside in the default partition.
*
* <p>Note that <code>start</code> must not point to the closing peer, but to the first
* character being searched.</p>
*
* @param start the start position
* @param bound the bound
* @param openingPeer the opening peer character (e.g. '{')
* @param closingPeer the closing peer character (e.g. '}')
* @return the matching peer character position, or <code>NOT_FOUND</code>
*/
public int findOpeningPeer(int start, int bound, char openingPeer, char closingPeer) {
Assert.isLegal(start < fDocument.getLength());
try {
final CharacterMatch match= new CharacterMatch(new char[] {openingPeer, closingPeer});
int depth= 1;
start += 1;
while (true) {
start= scanBackward(start - 1, UNBOUND, new CharacterMatch(new char[] {openingPeer, closingPeer}));
start= scanBackward(start - 1, bound, match);
if (start == NOT_FOUND)
return NOT_FOUND;
@ -587,7 +611,7 @@ public final class CHeuristicScanner implements Symbols {
if (offset < 1 || offset >= fDocument.getLength())
return null;
int begin= findOpeningPeer(offset - 1, LBRACE, RBRACE);
int begin= findOpeningPeer(offset - 1, CHeuristicScanner.UNBOUND, LBRACE, RBRACE);
int end= findClosingPeer(offset, LBRACE, RBRACE);
if (begin == NOT_FOUND || end == NOT_FOUND)
return null;
@ -821,7 +845,7 @@ public final class CHeuristicScanner implements Symbols {
case TokenELSE:
return true;
case TokenRPAREN:
position= findOpeningPeer(fPos, LPAREN, RPAREN);
position= findOpeningPeer(fPos, CHeuristicScanner.UNBOUND, LPAREN, RPAREN);
if (position > 0) {
switch (previousToken(position - 1, bound)) {
case TokenIF:
@ -880,4 +904,31 @@ public final class CHeuristicScanner implements Symbols {
}
return false;
}
/**
* Returns <code>true</code> if the document, when scanned backwards from <code>start</code>
* appears to contain a field reference, i.e. a (optional) name preceded by a <code>.</code> or <code>-&gt;</code>
* The <code>start</code> must be before the operator.
*
* @param start the position after the field reference operator.
* @param bound the first position in <code>fDocument</code> to not consider any more, with
* <code>bound</code> &lt; <code>start</code>, or <code>UNBOUND</code>
* @return <code>true</code> if the current position looks like a field reference
*/
public boolean looksLikeFieldReferenceBackward(int start, int bound) {
int token= previousToken(start - 1, bound);
if (token == Symbols.TokenIDENT) { // field name
token= previousToken(getPosition(), bound);
}
if (token == Symbols.TokenDOT) {
return true;
}
if (token == Symbols.TokenGREATERTHAN) {
token= previousToken(getPosition(), bound);
if (token == Symbols.TokenMINUS) {
return true;
}
}
return false;
}
}

View file

@ -81,9 +81,8 @@ import org.eclipse.cdt.internal.ui.editor.CDocumentProvider;
import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverDescriptor;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverProxy;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProcessor2;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
import org.eclipse.cdt.internal.ui.text.template.CTemplateCompletionProcessor;
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
@ -346,10 +345,21 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
IContentAssistProcessor processor = new CCompletionProcessor2(getEditor());
IContentAssistProcessor processor = new CContentAssistProcessor(getEditor(), assistant, IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
assistant.setContentAssistProcessor(new CTemplateCompletionProcessor(getEditor()), ICPartitions.C_MULTI_LINE_COMMENT);
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_MULTI_LINE_COMMENT);
assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_COMMENT);
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_SINGLE_LINE_COMMENT);
assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_COMMENT);
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_STRING);
assistant.setContentAssistProcessor(processor, ICPartitions.C_STRING);
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_PREPROCESSOR);
assistant.setContentAssistProcessor(processor, ICPartitions.C_PREPROCESSOR);
ContentAssistPreference.configure(assistant, fPreferenceStore);
assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);

View file

@ -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
@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin, Google
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
@ -30,6 +31,8 @@ public interface Symbols {
int TokenEQUAL= 12;
int TokenLESSTHAN= 13;
int TokenGREATERTHAN= 14;
int TokenDOT= 15;
int TokenMINUS= 16;
int TokenIF= 109;
int TokenDO= 1010;
int TokenFOR= 1011;

View file

@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
/**
* Describes the context of a content assist invocation in a C/C++ editor.
* <p>
* Clients may use but not subclass this class.
* </p>
*
* @since 4.0
*/
public class CContentAssistInvocationContext extends ContentAssistInvocationContext {
private final IEditorPart fEditor;
private ITranslationUnit fTU= null;
private boolean fTUComputed= false;
/**
* Creates a new context.
*
* @param viewer the viewer used by the editor
* @param offset the invocation offset
* @param editor the editor that content assist is invoked in
*/
public CContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor) {
super(viewer, offset);
Assert.isNotNull(editor);
fEditor= editor;
}
/**
* Creates a new context.
*
* @param unit the translation unit in <code>document</code>
*/
public CContentAssistInvocationContext(ITranslationUnit unit) {
super();
fTU= unit;
fTUComputed= true;
fEditor= null;
}
/**
* Returns the translation unit that content assist is invoked in, <code>null</code> if there
* is none.
*
* @return the translation unit that content assist is invoked in, possibly <code>null</code>
*/
public ITranslationUnit getTranslationUnit() {
if (!fTUComputed) {
fTUComputed= true;
fTU= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
}
return fTU;
}
/**
* Returns the project of the translation unit that content assist is invoked in,
* <code>null</code> if none.
*
* @return the current C project, possibly <code>null</code>
*/
public ICProject getProject() {
ITranslationUnit unit= getTranslationUnit();
return unit == null ? null : unit.getCProject();
}
/**
* Get the editor content assist is invoked in.
*
* @return the editor, may be <code>null</code>
*/
public IEditorPart getEditor() {
return fEditor;
}
}

View file

@ -0,0 +1,63 @@
/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
/**
* C/C++ content assist processor.
*/
public class CContentAssistProcessor extends ContentAssistProcessor {
private IContextInformationValidator fValidator;
private final IEditorPart fEditor;
public CContentAssistProcessor(IEditorPart editor, ContentAssistant assistant, String partition) {
super(assistant, partition);
fEditor= editor;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
if (fValidator == null) {
fValidator= new CParameterListValidator();
}
return fValidator;
}
/*
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#filterAndSort(java.util.List, org.eclipse.core.runtime.IProgressMonitor)
*/
protected List filterAndSortProposals(List proposals, IProgressMonitor monitor, ContentAssistInvocationContext context) {
return proposals;
}
/*
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
*/
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
return new CContentAssistInvocationContext(viewer, offset, fEditor);
}
}

View file

@ -0,0 +1,331 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.resource.ImageDescriptor;
import org.osgi.framework.Bundle;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.ui.util.Messages;
/**
* Describes a category extension to the "completionProposalComputer" extension point.
*
* @since 4.0
*/
public final class CompletionProposalCategory {
/** The extension schema name of the icon attribute. */
private static final String ICON= "icon"; //$NON-NLS-1$
private final String fId;
private final String fName;
private final IConfigurationElement fElement;
/** The image descriptor for this category, or <code>null</code> if none specified. */
private final ImageDescriptor fImage;
private boolean fIsSeparateCommand= true;
private boolean fIsEnabled= true;
private boolean fIsIncluded= true;
private final CompletionProposalComputerRegistry fRegistry;
private int fSortOrder= 0x10000;
private String fLastError= null;
CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) {
fElement= element;
fRegistry= registry;
IExtension parent= (IExtension) element.getParent();
fId= parent.getUniqueIdentifier();
checkNotNull(fId, "id"); //$NON-NLS-1$
String name= parent.getLabel();
if (name == null)
fName= fId;
else
fName= name;
String icon= element.getAttribute(ICON);
ImageDescriptor img= null;
if (icon != null) {
Bundle bundle= getBundle();
if (bundle != null) {
Path path= new Path(icon);
URL url= FileLocator.find(bundle, path, null);
img= ImageDescriptor.createFromURL(url);
}
}
fImage= img;
}
CompletionProposalCategory(String id, String name, CompletionProposalComputerRegistry registry) {
fRegistry= registry;
fId= id;
fName= name;
fElement= null;
fImage= null;
}
private Bundle getBundle() {
String namespace= fElement.getDeclaringExtension().getContributor().getName();
Bundle bundle= Platform.getBundle(namespace);
return bundle;
}
/**
* Checks an element that must be defined according to the extension
* point schema. Throws an
* <code>InvalidRegistryObjectException</code> if <code>obj</code>
* is <code>null</code>.
*/
private void checkNotNull(Object obj, String attribute) throws InvalidRegistryObjectException {
if (obj == null) {
Object[] args= { getId(), fElement.getContributor().getName(), attribute };
String message= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_illegal_attribute_message, args);
IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, null);
CUIPlugin.getDefault().log(status);
throw new InvalidRegistryObjectException();
}
}
/**
* Returns the identifier of the described extension.
*
* @return Returns the id
*/
public String getId() {
return fId;
}
/**
* Returns the name of the described extension.
*
* @return Returns the name
*/
public String getName() {
return fName;
}
/**
* Returns the name of the described extension
* without mnemonic hint in order to be displayed
* in a message.
*
* @return Returns the name
*/
public String getDisplayName() {
return LegacyActionTools.removeMnemonics(fName);
}
/**
* Returns the image descriptor of the described category.
*
* @return the image descriptor of the described category
*/
public ImageDescriptor getImageDescriptor() {
return fImage;
}
/**
* Sets the separate command state of the category.
*
* @param enabled the new enabled state.
*/
public void setSeparateCommand(boolean enabled) {
fIsSeparateCommand= enabled;
}
/**
* Returns the enablement state of the category.
*
* @return the enablement state of the category
*/
public boolean isSeparateCommand() {
return fIsSeparateCommand;
}
/**
* @param included the included
*/
public void setIncluded(boolean included) {
fIsIncluded= included;
}
/**
* @return included
*/
public boolean isIncluded() {
return fIsIncluded;
}
public boolean isEnabled() {
return fIsEnabled;
}
public void setEnabled(boolean isEnabled) {
fIsEnabled= isEnabled;
}
/**
* Returns <code>true</code> if the category contains any computers, <code>false</code>
* otherwise.
*
* @return <code>true</code> if the category contains any computers, <code>false</code>
* otherwise
*/
public boolean hasComputers() {
List descriptors= fRegistry.getProposalComputerDescriptors();
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
return true;
}
return false;
}
/**
* Returns <code>true</code> if the category contains any computers in the given partition, <code>false</code>
* otherwise.
*
* @param partition the partition
* @return <code>true</code> if the category contains any computers, <code>false</code>
* otherwise
*/
public boolean hasComputers(String partition) {
List descriptors= fRegistry.getProposalComputerDescriptors(partition);
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
return true;
}
return false;
}
/**
* @return sortOrder
*/
public int getSortOrder() {
return fSortOrder;
}
/**
* @param sortOrder the sortOrder
*/
public void setSortOrder(int sortOrder) {
fSortOrder= sortOrder;
}
/**
* Safely computes completion proposals of all computers of this category through their
* extension. If an extension is disabled, throws an exception or otherwise does not adhere to
* the contract described in {@link ICompletionProposalComputer}, it is disabled.
*
* @param context the invocation context passed on to the extension
* @param partition the partition type where to invocation occurred
* @param monitor the progress monitor passed on to the extension
* @return the list of computed completion proposals (element type:
* {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
fLastError= null;
List result= new ArrayList();
List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
result.addAll(desc.computeCompletionProposals(context, monitor));
if (fLastError == null)
fLastError= desc.getErrorMessage();
}
return result;
}
/**
* Safely computes context information objects of all computers of this category through their
* extension. If an extension is disabled, throws an exception or otherwise does not adhere to
* the contract described in {@link ICompletionProposalComputer}, it is disabled.
*
* @param context the invocation context passed on to the extension
* @param partition the partition type where to invocation occurred
* @param monitor the progress monitor passed on to the extension
* @return the list of computed context information objects (element type:
* {@link org.eclipse.jface.text.contentassist.IContextInformation})
*/
public List computeContextInformation(ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
fLastError= null;
List result= new ArrayList();
List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
result.addAll(desc.computeContextInformation(context, monitor));
if (fLastError == null)
fLastError= desc.getErrorMessage();
}
return result;
}
/**
* Returns the error message from the computers in this category.
*
* @return the error message from the computers in this category
*/
public String getErrorMessage() {
return fLastError;
}
/**
* Notifies the computers in this category of a proposal computation session start.
*/
public void sessionStarted() {
List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors());
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
desc.sessionStarted();
if (fLastError == null)
fLastError= desc.getErrorMessage();
}
}
/**
* Notifies the computers in this category of a proposal computation session end.
*/
public void sessionEnded() {
List descriptors= new ArrayList(fRegistry.getProposalComputerDescriptors());
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this)
desc.sessionEnded();
if (fLastError == null)
fLastError= desc.getErrorMessage();
}
}
}

View file

@ -0,0 +1,550 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.PerformanceStats;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.IDocument;
import org.osgi.framework.Bundle;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.ui.util.Messages;
/**
* The description of an extension to the
* <code>org.eclipse.cdt.ui.completionProposalComputer</code> extension point. Instances are
* immutable. Instances can be obtained from a {@link CompletionProposalComputerRegistry}.
*
* @see CompletionProposalComputerRegistry
* @since 4.0
*/
final class CompletionProposalComputerDescriptor {
/** The default category id. */
private static final String DEFAULT_CATEGORY_ID= "org.eclipse.cdt.ui.defaultProposalCategory"; //$NON-NLS-1$
/** The extension schema name of the category id attribute. */
private static final String CATEGORY_ID= "categoryId"; //$NON-NLS-1$
/** The extension schema name of the partition type attribute. */
private static final String TYPE= "type"; //$NON-NLS-1$
/** The extension schema name of the class attribute. */
private static final String CLASS= "class"; //$NON-NLS-1$
/** The extension schema name of the activate attribute. */
private static final String ACTIVATE= "activate"; //$NON-NLS-1$
/** The extension schema name of the partition child elements. */
private static final String PARTITION= "partition"; //$NON-NLS-1$
/** Set of Java partition types. */
private static final Set PARTITION_SET;
/** The name of the performance event used to trace extensions. */
private static final String PERFORMANCE_EVENT= CUIPlugin.getPluginId() + "/perf/content_assist/extensions"; //$NON-NLS-1$
/**
* If <code>true</code>, execution time of extensions is measured and the data forwarded to
* core's {@link PerformanceStats} service.
*/
private static final boolean MEASURE_PERFORMANCE= PerformanceStats.isEnabled(PERFORMANCE_EVENT);
/**
* Independently of the {@link PerformanceStats} service, any operation that takes longer than
* {@value} milliseconds will be flagged as an violation. This timeout does not apply to the
* first invocation, as it may take longer due to plug-in initialization etc. See also
* {@link #fIsReportingDelay}.
*/
private static final long MAX_DELAY= 5000;
/* log constants */
private static final String COMPUTE_COMPLETION_PROPOSALS= "computeCompletionProposals()"; //$NON-NLS-1$
private static final String COMPUTE_CONTEXT_INFORMATION= "computeContextInformation()"; //$NON-NLS-1$
private static final String SESSION_STARTED= "sessionStarted()"; //$NON-NLS-1$
private static final String SESSION_ENDED= "sessionEnded()"; //$NON-NLS-1$
static {
Set partitions= new HashSet();
partitions.add(IDocument.DEFAULT_CONTENT_TYPE);
partitions.add(ICPartitions.C_PREPROCESSOR);
partitions.add(ICPartitions.C_MULTI_LINE_COMMENT);
partitions.add(ICPartitions.C_SINGLE_LINE_COMMENT);
partitions.add(ICPartitions.C_STRING);
partitions.add(ICPartitions.C_CHARACTER);
PARTITION_SET= Collections.unmodifiableSet(partitions);
}
/** The identifier of the extension. */
private final String fId;
/** The name of the extension. */
private final String fName;
/** The class name of the provided <code>IJavaCompletionProposalComputer</code>. */
private final String fClass;
/** The activate attribute value. */
private final boolean fActivate;
/** The partition of the extension (element type: {@link String}). */
private final Set fPartitions;
/** The configuration element of this extension. */
private final IConfigurationElement fElement;
/** The registry we are registered with. */
private final CompletionProposalComputerRegistry fRegistry;
/** The computer, if instantiated, <code>null</code> otherwise. */
private ICompletionProposalComputer fComputer;
/** The ui category. */
private final CompletionProposalCategory fCategory;
/** The first error message in the most recent operation, or <code>null</code>. */
private String fLastError;
/**
* Tells whether to inform the user when <code>MAX_DELAY</code> has been exceeded.
* We start timing execution after the first session because the first may take
* longer due to plug-in activation and initialization.
*/
private boolean fIsReportingDelay= false;
/** The start of the last operation. */
private long fStart;
/**
* Creates a new descriptor.
*
* @param element the configuration element to read
* @param registry the computer registry creating this descriptor
*/
CompletionProposalComputerDescriptor(IConfigurationElement element, CompletionProposalComputerRegistry registry, List categories) throws InvalidRegistryObjectException {
Assert.isLegal(registry != null);
Assert.isLegal(element != null);
fRegistry= registry;
fElement= element;
IExtension extension= element.getDeclaringExtension();
fId= extension.getUniqueIdentifier();
checkNotNull(fId, "id"); //$NON-NLS-1$
String name= extension.getLabel();
if (name.length() == 0)
fName= fId;
else
fName= name;
Set partitions= new HashSet();
IConfigurationElement[] children= element.getChildren(PARTITION);
if (children.length == 0) {
fPartitions= PARTITION_SET; // add to all partition types if no partition is configured
} else {
for (int i= 0; i < children.length; i++) {
String type= children[i].getAttribute(TYPE);
checkNotNull(type, TYPE);
partitions.add(type);
}
fPartitions= Collections.unmodifiableSet(partitions);
}
String activateAttribute= element.getAttribute(ACTIVATE);
fActivate= Boolean.valueOf(activateAttribute).booleanValue();
fClass= element.getAttribute(CLASS);
checkNotNull(fClass, CLASS);
String categoryId= element.getAttribute(CATEGORY_ID);
if (categoryId == null)
categoryId= DEFAULT_CATEGORY_ID;
CompletionProposalCategory category= null;
for (Iterator it= categories.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
if (cat.getId().equals(categoryId)) {
category= cat;
break;
}
}
if (category == null) {
// create a category if it does not exist
fCategory= new CompletionProposalCategory(categoryId, fName, registry);
categories.add(fCategory);
} else {
fCategory= category;
}
}
/**
* Checks an element that must be defined according to the extension
* point schema. Throws an
* <code>InvalidRegistryObjectException</code> if <code>obj</code>
* is <code>null</code>.
*/
private void checkNotNull(Object obj, String attribute) throws InvalidRegistryObjectException {
if (obj == null) {
Object[] args= { getId(), fElement.getContributor().getName(), attribute };
String message= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_illegal_attribute_message, args);
IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, null);
CUIPlugin.getDefault().log(status);
throw new InvalidRegistryObjectException();
}
}
/**
* Returns the identifier of the described extension.
*
* @return Returns the id
*/
public String getId() {
return fId;
}
/**
* Returns the name of the described extension.
*
* @return Returns the name
*/
public String getName() {
return fName;
}
/**
* Returns the partition types of the described extension.
*
* @return the set of partition types (element type: {@link String})
*/
public Set getPartitions() {
return fPartitions;
}
/**
* Returns a cached instance of the computer as described in the
* extension's xml. The computer is
* {@link #createComputer() created} the first time that this method
* is called and then cached.
*
* @return a new instance of the completion proposal computer as
* described by this descriptor
* @throws CoreException if the creation fails
* @throws InvalidRegistryObjectException if the extension is not
* valid any longer (e.g. due to plug-in unloading)
*/
private synchronized ICompletionProposalComputer getComputer() throws CoreException, InvalidRegistryObjectException {
if (fComputer == null && (fActivate || isPluginLoaded()))
fComputer= createComputer();
return fComputer;
}
private boolean isPluginLoaded() {
Bundle bundle= getBundle();
return bundle != null && bundle.getState() == Bundle.ACTIVE;
}
private Bundle getBundle() {
String namespace= fElement.getDeclaringExtension().getContributor().getName();
Bundle bundle= Platform.getBundle(namespace);
return bundle;
}
/**
* Returns a new instance of the computer as described in the
* extension's xml. Note that the safest way to access the computer
* is by using the {@linkplain #computeCompletionProposals}
* and {@linkplain #computeContextInformation}
* methods. These delegate the functionality to the contributed
* computer, but handle instance creation and any exceptions thrown.
*
* @return a new instance of the completion proposal computer as
* described by this descriptor
* @throws CoreException if the creation fails
* @throws InvalidRegistryObjectException if the extension is not
* valid any longer (e.g. due to plug-in unloading)
*/
public ICompletionProposalComputer createComputer() throws CoreException, InvalidRegistryObjectException {
return (ICompletionProposalComputer) fElement.createExecutableExtension(CLASS);
}
/**
* Safely computes completion proposals through the described extension. If the extension
* is disabled, throws an exception or otherwise does not adhere to the contract described in
* {@link ICompletionProposalComputer}, an empty list is returned.
*
* @param context the invocation context passed on to the extension
* @param monitor the progress monitor passed on to the extension
* @return the list of computed completion proposals (element type:
* {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (!isEnabled())
return Collections.EMPTY_LIST;
IStatus status;
try {
ICompletionProposalComputer computer= getComputer();
if (computer == null) // not active yet
return Collections.EMPTY_LIST;
try {
PerformanceStats stats= startMeter(context, computer);
List proposals= computer.computeCompletionProposals(context, monitor);
stopMeter(stats, COMPUTE_COMPLETION_PROPOSALS);
if (proposals != null) {
fLastError= computer.getErrorMessage();
return proposals;
}
} finally {
fIsReportingDelay= true;
}
status= createAPIViolationStatus(COMPUTE_COMPLETION_PROPOSALS);
} catch (InvalidRegistryObjectException x) {
status= createExceptionStatus(x);
} catch (CoreException x) {
status= createExceptionStatus(x);
} catch (RuntimeException x) {
status= createExceptionStatus(x);
} finally {
monitor.done();
}
fRegistry.informUser(this, status);
return Collections.EMPTY_LIST;
}
/**
* Safely computes context information objects through the described extension. If the extension
* is disabled, throws an exception or otherwise does not adhere to the contract described in
* {@link ICompletionProposalComputer}, an empty list is returned.
*
* @param context the invocation context passed on to the extension
* @param monitor the progress monitor passed on to the extension
* @return the list of computed context information objects (element type:
* {@link org.eclipse.jface.text.contentassist.IContextInformation})
*/
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (!isEnabled())
return Collections.EMPTY_LIST;
IStatus status;
try {
ICompletionProposalComputer computer= getComputer();
if (computer == null) // not active yet
return Collections.EMPTY_LIST;
PerformanceStats stats= startMeter(context, computer);
List proposals= computer.computeContextInformation(context, monitor);
stopMeter(stats, COMPUTE_CONTEXT_INFORMATION);
if (proposals != null) {
fLastError= computer.getErrorMessage();
return proposals;
}
status= createAPIViolationStatus(COMPUTE_CONTEXT_INFORMATION);
} catch (InvalidRegistryObjectException x) {
status= createExceptionStatus(x);
} catch (CoreException x) {
status= createExceptionStatus(x);
} catch (RuntimeException x) {
status= createExceptionStatus(x);
} finally {
monitor.done();
}
fRegistry.informUser(this, status);
return Collections.EMPTY_LIST;
}
/**
* Notifies the described extension of a proposal computation session start.
* <p><em>
* Note: This method is called every time code assist is invoked and
* is <strong>not</strong> filtered by partition type.
* </em></p>
*/
public void sessionStarted() {
if (!isEnabled())
return;
IStatus status;
try {
ICompletionProposalComputer computer= getComputer();
if (computer == null) // not active yet
return;
PerformanceStats stats= startMeter(SESSION_STARTED, computer);
computer.sessionStarted();
stopMeter(stats, SESSION_ENDED);
return;
} catch (InvalidRegistryObjectException x) {
status= createExceptionStatus(x);
} catch (CoreException x) {
status= createExceptionStatus(x);
} catch (RuntimeException x) {
status= createExceptionStatus(x);
}
fRegistry.informUser(this, status);
}
/**
* Notifies the described extension of a proposal computation session end.
* <p><em>
* Note: This method is called every time code assist is invoked and
* is <strong>not</strong> filtered by partition type.
* </em></p>
*/
public void sessionEnded() {
if (!isEnabled())
return;
IStatus status;
try {
ICompletionProposalComputer computer= getComputer();
if (computer == null) // not active yet
return;
PerformanceStats stats= startMeter(SESSION_ENDED, computer);
computer.sessionEnded();
stopMeter(stats, SESSION_ENDED);
return;
} catch (InvalidRegistryObjectException x) {
status= createExceptionStatus(x);
} catch (CoreException x) {
status= createExceptionStatus(x);
} catch (RuntimeException x) {
status= createExceptionStatus(x);
}
fRegistry.informUser(this, status);
}
private PerformanceStats startMeter(Object context, ICompletionProposalComputer computer) {
final PerformanceStats stats;
if (MEASURE_PERFORMANCE) {
stats= PerformanceStats.getStats(PERFORMANCE_EVENT, computer);
stats.startRun(context.toString());
} else {
stats= null;
}
if (fIsReportingDelay) {
fStart= System.currentTimeMillis();
}
return stats;
}
private void stopMeter(final PerformanceStats stats, String operation) {
if (MEASURE_PERFORMANCE) {
stats.endRun();
if (stats.isFailure()) {
IStatus status= createPerformanceStatus(operation);
fRegistry.informUser(this, status);
return;
}
}
if (fIsReportingDelay) {
long current= System.currentTimeMillis();
if (current - fStart > MAX_DELAY) {
IStatus status= createPerformanceStatus(operation);
fRegistry.informUser(this, status);
}
}
}
private IStatus createExceptionStatus(InvalidRegistryObjectException x) {
// extension has become invalid - log & disable
String blame= createBlameMessage();
String reason= ContentAssistMessages.CompletionProposalComputerDescriptor_reason_invalid;
return new Status(IStatus.INFO, CUIPlugin.getPluginId(), IStatus.OK, blame + " " + reason, x); //$NON-NLS-1$
}
private IStatus createExceptionStatus(CoreException x) {
// unable to instantiate the extension - log & disable
String blame= createBlameMessage();
String reason= ContentAssistMessages.CompletionProposalComputerDescriptor_reason_instantiation;
return new Status(IStatus.ERROR, CUIPlugin.getPluginId(), IStatus.OK, blame + " " + reason, x); //$NON-NLS-1$
}
private IStatus createExceptionStatus(RuntimeException x) {
// misbehaving extension - log & disable
String blame= createBlameMessage();
String reason= ContentAssistMessages.CompletionProposalComputerDescriptor_reason_runtime_ex;
return new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, blame + " " + reason, x); //$NON-NLS-1$
}
private IStatus createAPIViolationStatus(String operation) {
String blame= createBlameMessage();
Object[] args= {operation};
String reason= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_reason_API, args);
return new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, blame + " " + reason, null); //$NON-NLS-1$
}
private IStatus createPerformanceStatus(String operation) {
String blame= createBlameMessage();
Object[] args= {operation};
String reason= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_reason_performance, args);
return new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, blame + " " + reason, null); //$NON-NLS-1$
}
private String createBlameMessage() {
Object[] args= { getName(), fElement.getDeclaringExtension().getContributor().getName() };
String disable= Messages.format(ContentAssistMessages.CompletionProposalComputerDescriptor_blame_message, args);
return disable;
}
/**
* Returns the enablement state of the described extension.
*
* @return the enablement state of the described extension
*/
private boolean isEnabled() {
return fCategory.isEnabled();
}
CompletionProposalCategory getCategory() {
return fCategory;
}
/**
* Returns the error message from the described extension.
*
* @return the error message from the described extension
*/
public String getErrorMessage() {
return fLastError;
}
/**
* Returns the contributor of the described extension.
*
* @return the contributor of the described extension
*/
IContributor getContributor() {
try {
return fElement.getContributor();
} catch (InvalidRegistryObjectException e) {
return null;
}
}
}

View file

@ -0,0 +1,394 @@
/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Link;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.util.Messages;
/**
* A registry for all extensions to the
* <code>org.eclipse.cdt.ui.completionProposalComputer</code>
* extension point.
*
* @since 4.0
*/
public final class CompletionProposalComputerRegistry {
private static final String EXTENSION_POINT= "completionProposalComputer"; //$NON-NLS-1$
/** The singleton instance. */
private static CompletionProposalComputerRegistry fgSingleton= null;
/**
* Returns the default computer registry.
* <p>
* TODO keep this or add some other singleton, e.g. JavaPlugin?
* </p>
*
* @return the singleton instance
*/
public static synchronized CompletionProposalComputerRegistry getDefault() {
if (fgSingleton == null) {
fgSingleton= new CompletionProposalComputerRegistry();
}
return fgSingleton;
}
/**
* The sets of descriptors, grouped by partition type (key type:
* {@link String}, value type:
* {@linkplain List List&lt;CompletionProposalComputerDescriptor&gt;}).
*/
private final Map fDescriptorsByPartition= new HashMap();
/**
* Unmodifiable versions of the sets stored in
* <code>fDescriptorsByPartition</code> (key type: {@link String},
* value type:
* {@linkplain List List&lt;CompletionProposalComputerDescriptor&gt;}).
*/
private final Map fPublicDescriptorsByPartition= new HashMap();
/**
* All descriptors (element type:
* {@link CompletionProposalComputerDescriptor}).
*/
private final List fDescriptors= new ArrayList();
/**
* Unmodifiable view of <code>fDescriptors</code>
*/
private final List fPublicDescriptors= Collections.unmodifiableList(fDescriptors);
private final List fCategories= new ArrayList();
private final List fPublicCategories= Collections.unmodifiableList(fCategories);
/**
* <code>true</code> if this registry has been loaded.
*/
private boolean fLoaded= false;
/**
* Creates a new instance.
*/
public CompletionProposalComputerRegistry() {
}
/**
* Returns the list of {@link CompletionProposalComputerDescriptor}s describing all extensions
* to the <code>javaCompletionProposalComputer</code> extension point for the given partition
* type.
* <p>
* A valid partition is either one of the constants defined in
* {@link org.eclipse.cdt.ui.text.ICPartitions} or
* {@link org.eclipse.jface.text.IDocument#DEFAULT_CONTENT_TYPE}. An empty list is returned if
* there are no extensions for the given partition.
* </p>
* <p>
* The returned list is read-only and is sorted in the order that the extensions were read in.
* There are no duplicate elements in the returned list. The returned list may change if plug-ins
* are loaded or unloaded while the application is running or if an extension violates the API
* contract of {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}. When
* computing proposals, it is therefore imperative to copy the returned list before iterating
* over it.
* </p>
*
* @param partition
* the partition type for which to retrieve the computer descriptors
* @return the list of extensions to the <code>javaCompletionProposalComputer</code> extension
* point (element type: {@link CompletionProposalComputerDescriptor})
*/
List getProposalComputerDescriptors(String partition) {
ensureExtensionPointRead();
List result= (List) fPublicDescriptorsByPartition.get(partition);
return result != null ? result : Collections.EMPTY_LIST;
}
/**
* Returns the list of {@link CompletionProposalComputerDescriptor}s describing all extensions
* to the <code>javaCompletionProposalComputer</code> extension point.
* <p>
* The returned list is read-only and is sorted in the order that the extensions were read in.
* There are no duplicate elements in the returned list. The returned list may change if plug-ins
* are loaded or unloaded while the application is running or if an extension violates the API
* contract of {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}. When
* computing proposals, it is therefore imperative to copy the returned list before iterating
* over it.
* </p>
*
* @return the list of extensions to the <code>javaCompletionProposalComputer</code> extension
* point (element type: {@link CompletionProposalComputerDescriptor})
*/
List getProposalComputerDescriptors() {
ensureExtensionPointRead();
return fPublicDescriptors;
}
/**
* Returns the list of proposal categories contributed to the
* <code>javaCompletionProposalComputer</code> extension point.
* <p>
* <p>
* The returned list is read-only and is sorted in the order that the extensions were read in.
* There are no duplicate elements in the returned list. The returned list may change if
* plug-ins are loaded or unloaded while the application is running.
* </p>
*
* @return list of proposal categories contributed to the
* <code>javaCompletionProposalComputer</code> extension point (element type:
* {@link CompletionProposalCategory})
*/
public List getProposalCategories() {
ensureExtensionPointRead();
return fPublicCategories;
}
/**
* Ensures that the extensions are read and stored in
* <code>fDescriptorsByPartition</code>.
*/
private void ensureExtensionPointRead() {
boolean reload;
synchronized (this) {
reload= !fLoaded;
fLoaded= true;
}
if (reload)
reload();
}
/**
* Reloads the extensions to the extension point.
* <p>
* This method can be called more than once in order to reload from
* a changed extension registry.
* </p>
*/
public void reload() {
IExtensionRegistry registry= Platform.getExtensionRegistry();
List elements= new ArrayList(Arrays.asList(registry.getConfigurationElementsFor(CUIPlugin.getPluginId(), EXTENSION_POINT)));
Map map= new HashMap();
List all= new ArrayList();
List categories= getCategories(elements);
for (Iterator iter= elements.iterator(); iter.hasNext();) {
IConfigurationElement element= (IConfigurationElement) iter.next();
try {
CompletionProposalComputerDescriptor desc= new CompletionProposalComputerDescriptor(element, this, categories);
Set partitions= desc.getPartitions();
for (Iterator it= partitions.iterator(); it.hasNext();) {
String partition= (String) it.next();
List list= (List) map.get(partition);
if (list == null) {
list= new ArrayList();
map.put(partition, list);
}
list.add(desc);
}
all.add(desc);
} catch (InvalidRegistryObjectException x) {
/*
* Element is not valid any longer as the contributing plug-in was unloaded or for
* some other reason. Do not include the extension in the list and inform the user
* about it.
*/
Object[] args= {element.toString()};
String message= Messages.format(ContentAssistMessages.CompletionProposalComputerRegistry_invalid_message, args);
IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, x);
informUser(status);
}
}
synchronized (this) {
fCategories.clear();
fCategories.addAll(categories);
Set partitions= map.keySet();
fDescriptorsByPartition.keySet().retainAll(partitions);
fPublicDescriptorsByPartition.keySet().retainAll(partitions);
for (Iterator it= partitions.iterator(); it.hasNext();) {
String partition= (String) it.next();
List old= (List) fDescriptorsByPartition.get(partition);
List current= (List) map.get(partition);
if (old != null) {
old.clear();
old.addAll(current);
} else {
fDescriptorsByPartition.put(partition, current);
fPublicDescriptorsByPartition.put(partition, Collections.unmodifiableList(current));
}
}
fDescriptors.clear();
fDescriptors.addAll(all);
}
}
private List getCategories(List elements) {
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
String preference= store.getString(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
Set disabled= new HashSet();
StringTokenizer tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$
while (tok.hasMoreTokens())
disabled.add(tok.nextToken());
Map ordered= new HashMap();
preference= store.getString(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$
while (tok.hasMoreTokens()) {
StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$
String id= inner.nextToken();
int rank= Integer.parseInt(inner.nextToken());
ordered.put(id, new Integer(rank));
}
List categories= new ArrayList();
for (Iterator iter= elements.iterator(); iter.hasNext();) {
IConfigurationElement element= (IConfigurationElement) iter.next();
try {
if (element.getName().equals("proposalCategory")) { //$NON-NLS-1$
iter.remove(); // remove from list to leave only computers
CompletionProposalCategory category= new CompletionProposalCategory(element, this);
categories.add(category);
category.setIncluded(!disabled.contains(category.getId()));
Integer rank= (Integer) ordered.get(category.getId());
if (rank != null) {
int r= rank.intValue();
boolean separate= r < 0xffff;
category.setSeparateCommand(separate);
category.setSortOrder(r);
}
}
} catch (InvalidRegistryObjectException x) {
/*
* Element is not valid any longer as the contributing plug-in was unloaded or for
* some other reason. Do not include the extension in the list and inform the user
* about it.
*/
Object[] args= {element.toString()};
String message= Messages.format(ContentAssistMessages.CompletionProposalComputerRegistry_invalid_message, args);
IStatus status= new Status(IStatus.WARNING, CUIPlugin.getPluginId(), IStatus.OK, message, x);
informUser(status);
}
}
return categories;
}
/**
* Log the status and inform the user about a misbehaving extension.
*
* @param descriptor the descriptor of the misbehaving extension
* @param status a status object that will be logged
*/
void informUser(CompletionProposalComputerDescriptor descriptor, IStatus status) {
CUIPlugin.getDefault().log(status);
String title= ContentAssistMessages.CompletionProposalComputerRegistry_error_dialog_title;
CompletionProposalCategory category= descriptor.getCategory();
IContributor culprit= descriptor.getContributor();
Set affectedPlugins= getAffectedContributors(category, culprit);
final String avoidHint;
final String culpritName= culprit == null ? null : culprit.getName();
if (affectedPlugins.isEmpty())
avoidHint= Messages.format(ContentAssistMessages.CompletionProposalComputerRegistry_messageAvoidanceHint, new Object[] {culpritName, category.getDisplayName()});
else
avoidHint= Messages.format(ContentAssistMessages.CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning, new Object[] {culpritName, category.getDisplayName(), toString(affectedPlugins)});
String message= status.getMessage();
// inlined from MessageDialog.openError
MessageDialog dialog = new MessageDialog(CUIPlugin.getActiveWorkbenchShell(), title, null /* default image */, message, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0) {
protected Control createCustomArea(Composite parent) {
Link link= new Link(parent, SWT.NONE);
link.setText(avoidHint);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
PreferencesUtil.createPreferenceDialogOn(getShell(), "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$
}
});
GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
gridData.widthHint= this.getMinimumMessageWidth();
link.setLayoutData(gridData);
return link;
}
};
dialog.open();
}
/**
* Returns the names of contributors affected by disabling a category.
*
* @param category the category that would be disabled
* @param culprit the culprit plug-in, which is not included in the returned list
* @return the names of the contributors other than <code>culprit</code> that contribute to <code>category</code> (element type: {@link String})
*/
private Set getAffectedContributors(CompletionProposalCategory category, IContributor culprit) {
Set affectedPlugins= new HashSet();
for (Iterator it= getProposalComputerDescriptors().iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc= (CompletionProposalComputerDescriptor) it.next();
CompletionProposalCategory cat= desc.getCategory();
if (cat.equals(category)) {
IContributor contributor= desc.getContributor();
if (contributor != null && !culprit.equals(contributor))
affectedPlugins.add(contributor.getName());
}
}
return affectedPlugins;
}
private Object toString(Collection collection) {
// strip brackets off AbstractCollection.toString()
String string= collection.toString();
return string.substring(1, string.length() - 1);
}
private void informUser(IStatus status) {
CUIPlugin.getDefault().log(status);
String title= ContentAssistMessages.CompletionProposalComputerRegistry_error_dialog_title;
String message= status.getMessage();
MessageDialog.openError(CUIPlugin.getActiveWorkbenchShell(), title, message);
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.commands.IParameterValues;
/**
* Map of parameters for the specific content assist command.
*
* @since 4.0
*/
public final class ContentAssistComputerParameter implements IParameterValues {
/*
* @see org.eclipse.core.commands.IParameterValues#getParameterValues()
*/
public Map getParameterValues() {
Collection descriptors= CompletionProposalComputerRegistry.getDefault().getProposalCategories();
Map map= new HashMap(descriptors.size());
for (Iterator it= descriptors.iterator(); it.hasNext();) {
CompletionProposalCategory category= (CompletionProposalCategory) it.next();
map.put(category.getDisplayName(), category.getId());
}
return map;
}
}

View file

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.internal.ui.editor.SpecificContentAssistExecutor;
/**
* A command handler to invoke a content assist for a specific proposal category.
*
* @since 4.0
*/
public final class ContentAssistHandler extends AbstractHandler {
private final SpecificContentAssistExecutor fExecutor= new SpecificContentAssistExecutor(CompletionProposalComputerRegistry.getDefault());
public ContentAssistHandler() {
}
/*
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
ITextEditor editor= getActiveEditor();
if (editor == null)
return null;
String categoryId= event.getParameter("org.eclipse.cdt.ui.specific_content_assist.category_id"); //$NON-NLS-1$
if (categoryId == null)
return null;
fExecutor.invokeContentAssist(editor, categoryId);
return null;
}
private ITextEditor getActiveEditor() {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window != null) {
IWorkbenchPage page= window.getActivePage();
if (page != null) {
IEditorPart editor= page.getActiveEditor();
if (editor instanceof ITextEditor)
return (ITextEditor) editor;
}
}
return null;
}
}

View file

@ -0,0 +1,59 @@
/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import org.eclipse.osgi.util.NLS;
/**
* Helper class to get NLSed messages.
*/
final class ContentAssistMessages extends NLS {
private static final String BUNDLE_NAME= ContentAssistMessages.class.getName();
private ContentAssistMessages() {
// Do not instantiate
}
public static String CompletionProposalComputerRegistry_messageAvoidanceHint;
public static String CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning;
public static String ContentAssistProcessor_all_disabled_message;
public static String ContentAssistProcessor_all_disabled_preference_link;
public static String ContentAssistProcessor_all_disabled_title;
static {
NLS.initializeMessages(BUNDLE_NAME, ContentAssistMessages.class);
}
public static String ContentAssistProcessor_computing_proposals;
public static String ContentAssistProcessor_collecting_proposals;
public static String ContentAssistProcessor_sorting_proposals;
public static String ContentAssistProcessor_computing_contexts;
public static String ContentAssistProcessor_collecting_contexts;
public static String ContentAssistProcessor_sorting_contexts;
public static String CompletionProposalComputerDescriptor_illegal_attribute_message;
public static String CompletionProposalComputerDescriptor_reason_invalid;
public static String CompletionProposalComputerDescriptor_reason_instantiation;
public static String CompletionProposalComputerDescriptor_reason_runtime_ex;
public static String CompletionProposalComputerDescriptor_reason_API;
public static String CompletionProposalComputerDescriptor_reason_performance;
public static String CompletionProposalComputerDescriptor_blame_message;
public static String CompletionProposalComputerRegistry_invalid_message;
public static String CompletionProposalComputerRegistry_error_dialog_title;
public static String ContentAssistProcessor_defaultProposalCategory;
public static String ContentAssistProcessor_toggle_affordance_press_gesture;
public static String ContentAssistProcessor_toggle_affordance_click_gesture;
public static String ContentAssistProcessor_toggle_affordance_update_message;
public static String ContentAssistProcessor_empty_message;
public static String ContentAssistHistory_serialize_error;
public static String ContentAssistHistory_deserialize_error;
}

View file

@ -0,0 +1,53 @@
###############################################################################
# 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
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# IBM Corporation - initial API and implementation
# Anton Leherbauer (Wind River Systems)
###############################################################################
CompletionProposalComputerRegistry_error_dialog_title=Problems During Content Assist
# {0} is the plug-in id of the contributing plug-in, {1} the display name of the proposal category
CompletionProposalComputerRegistry_messageAvoidanceHint=To avoid this message, disable the ''{0}'' plug-in or disable the ''{1}'' category on the <a>content assist</a> preference page.
# {0} is the plug-in id of the contributing plug-in, {1} the display name of the proposal category, {2} the comma-separated list of plug-ins other than {0} the contribute to the category
CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning=To avoid this message, disable the ''{0}'' plug-in or disable the ''{1}'' category on the <a>content assist</a> preference page. Note that disabling the category will also affect completion proposals from the following plug-ins: {2}.
# {0} is the extension id
CompletionProposalComputerRegistry_invalid_message=The extension ''{0}'' has become invalid.
CompletionProposalComputerDescriptor_reason_invalid=The extension has become invalid.
CompletionProposalComputerDescriptor_reason_instantiation=Unable to instantiate the extension.
CompletionProposalComputerDescriptor_reason_runtime_ex=The extension has thrown a runtime exception.
# {0} specifies an operation name, e.g. "computeProposals"
CompletionProposalComputerDescriptor_reason_API=The extension violated the API contract of the ''{0}'' operation.
CompletionProposalComputerDescriptor_reason_performance=The extension took too long to return from the ''{0}'' operation.
# {0} is the name of an extension, {1} the contributing plug-in name
CompletionProposalComputerDescriptor_blame_message= The ''{0}'' proposal computer from the ''{1}'' plug-in did not complete normally.
# {0} is the identifier of an extension, {1} the contributing plug-in, {2} a required but missing xml attribute
CompletionProposalComputerDescriptor_illegal_attribute_message= The extension "{0}" from plug-in "{1}" did not specify a value for the required "{2}" attribute. Disabling the extension.
ContentAssistProcessor_computing_proposals=Computing completion proposals
ContentAssistProcessor_collecting_proposals=Collecting proposals
ContentAssistProcessor_sorting_proposals=Sorting
ContentAssistProcessor_computing_contexts=Computing context information
ContentAssistProcessor_all_disabled_title=No Default Proposal Kinds
ContentAssistProcessor_all_disabled_message=No proposal kinds are enabled for the 'default' content assist list.
# {0} will be replaced by the label of the 'restore defaults' button
# The preference page should match the title of the 'C/C++ > Editor > Content Assist > Advanced' preference page
ContentAssistProcessor_all_disabled_preference_link=Change the settings on the <a>Advanced Content Assist preference page</a> or click ''{0}'' to restore the default behavior.
ContentAssistProcessor_collecting_contexts=Collecting context information
ContentAssistProcessor_sorting_contexts=Sorting
ContentAssistProcessor_defaultProposalCategory=Default Proposals
# {0} will be replaced by a keyboard shortcut (accelerator)
ContentAssistProcessor_toggle_affordance_press_gesture=Press ''{0}''
ContentAssistProcessor_toggle_affordance_click_gesture=Click
# {0} will be replaced by a title describing the displayed proposal category, {1} by either the press_gesture or click_gesture message above, {2} by the name of the next proposal category
ContentAssistProcessor_toggle_affordance_update_message={1} to show {2}
# {0} will be replaced by a title describing the displayed proposal category
ContentAssistProcessor_empty_message= No {0}
ContentAssistHistory_serialize_error=Problems writing content assist history to XML
ContentAssistHistory_deserialize_error=Problems reading content assist history from XML

View file

@ -28,7 +28,7 @@ import org.eclipse.jface.util.PropertyChangeEvent;
public class ContentAssistPreference {
/** Preference key for content assist auto activation */
// /** Preference key for content assist auto activation (unused) */
// public final static String AUTOACTIVATION= "content_assist_autoactivation";
/** Preference key for content assist auto activation delay */
public final static String AUTOACTIVATION_DELAY= "content_assist_autoactivation_delay"; //$NON-NLS-1$
@ -52,14 +52,14 @@ public class ContentAssistPreference {
public final static String AUTOACTIVATION_TRIGGERS_ARROW= "content_assist_autoactivation_trigger_arrow"; //$NON-NLS-1$
public final static String AUTOACTIVATION_TRIGGERS_DOUBLECOLON= "content_assist_autoactivation_trigger_doublecolon"; //$NON-NLS-1$
/** Preference key for visibility of proposals (unused) */
public final static String SHOW_DOCUMENTED_PROPOSALS= "content_assist_show_visible_proposals"; //$NON-NLS-1$
/** Preference key for alphabetic ordering of proposals */
public final static String ORDER_PROPOSALS= "content_assist_order_proposals"; //$NON-NLS-1$
/** Preference key for case sensitivity of propsals */
// /** Preference key for visibility of proposals (unused) */
// public final static String SHOW_DOCUMENTED_PROPOSALS= "content_assist_show_visible_proposals"; //$NON-NLS-1$
// /** Preference key for alphabetic ordering of proposals (unused) */
// public final static String ORDER_PROPOSALS= "content_assist_order_proposals"; //$NON-NLS-1$
// /** Preference key for case sensitivity of propsals */
// public final static String CASE_SENSITIVITY= "content_assist_case_sensitivity";
/** Preference key for adding includes on code assist (unused) */
public final static String ADD_INCLUDE= "content_assist_add_import"; //$NON-NLS-1$
// /** Preference key for adding includes on code assist (unused) */
// public final static String ADD_INCLUDE= "content_assist_add_import"; //$NON-NLS-1$
/** Preference key for completion search scope (unused) */
public final static String CURRENT_FILE_SEARCH_SCOPE= "content_assist_current_file_search_scope"; //$NON-NLS-1$
/** Preference key for completion search scope (unused) */
@ -77,16 +77,16 @@ public class ContentAssistPreference {
return getColor(store, key, textTools.getColorManager());
}
private static CCompletionProcessor2 getCProcessor(ContentAssistant assistant) {
private static CContentAssistProcessor getCProcessor(ContentAssistant assistant) {
IContentAssistProcessor p= assistant.getContentAssistProcessor(IDocument.DEFAULT_CONTENT_TYPE);
if (p instanceof CCompletionProcessor2)
return (CCompletionProcessor2) p;
if (p instanceof CContentAssistProcessor)
return (CContentAssistProcessor) p;
return null;
}
private static void configureCProcessor(ContentAssistant assistant, IPreferenceStore store) {
CCompletionProcessor2 jcp= getCProcessor(assistant);
if (jcp == null)
CContentAssistProcessor ccp= getCProcessor(assistant);
if (ccp == null)
return;
String triggers = ""; //$NON-NLS-1$
@ -99,19 +99,20 @@ public class ContentAssistPreference {
boolean useDoubleColonAsTrigger = store.getBoolean(AUTOACTIVATION_TRIGGERS_DOUBLECOLON);
if(useDoubleColonAsTrigger)
triggers += ":"; //$NON-NLS-1$
jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
//jcp.restrictProposalsToVisibility(enabled);
ccp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
// boolean enabled;
// enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
// ccp.restrictProposalsToVisibility(enabled);
//
// enabled= store.getBoolean(CASE_SENSITIVITY);
//jcp.restrictProposalsToMatchingCases(enabled);
// ccp.restrictProposalsToMatchingCases(enabled);
enabled= store.getBoolean(ORDER_PROPOSALS);
jcp.orderProposalsAlphabetically(enabled);
// enabled= store.getBoolean(ORDER_PROPOSALS);
// ccp.orderProposalsAlphabetically(enabled);
enabled= store.getBoolean(ADD_INCLUDE);
jcp.allowAddingIncludes(enabled);
// enabled= store.getBoolean(ADD_INCLUDE);
// ccp.allowAddingIncludes(enabled);
}
@ -157,8 +158,8 @@ public class ContentAssistPreference {
private static void changeCProcessor(ContentAssistant assistant, IPreferenceStore store, String key) {
CCompletionProcessor2 jcp= getCProcessor(assistant);
if (jcp == null)
CContentAssistProcessor ccp= getCProcessor(assistant);
if (ccp == null)
return;
if ( (AUTOACTIVATION_TRIGGERS_DOT.equals(key))
@ -177,22 +178,23 @@ public class ContentAssistPreference {
if (useDoubleColonAsTrigger){
triggers += ":"; //$NON-NLS-1$
}
jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
} else if (SHOW_DOCUMENTED_PROPOSALS.equals(key)) {
//boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
//jcp.restrictProposalsToVisibility(enabled);
ccp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray());
}
// else if (SHOW_DOCUMENTED_PROPOSALS.equals(key)) {
// boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS);
// ccp.restrictProposalsToVisibility(enabled);
// }
// else if (CASE_SENSITIVITY.equals(key)) {
// boolean enabled= store.getBoolean(CASE_SENSITIVITY);
// jcp.restrictProposalsToMatchingCases(enabled);
// ccp.restrictProposalsToMatchingCases(enabled);
// }
// else if (ORDER_PROPOSALS.equals(key)) {
// boolean enable= store.getBoolean(ORDER_PROPOSALS);
// ccp.orderProposalsAlphabetically(enable);
// } else if (ADD_INCLUDE.equals(key)) {
// boolean enabled= store.getBoolean(ADD_INCLUDE);
// ccp.allowAddingIncludes(enabled);
// }
else if (ORDER_PROPOSALS.equals(key)) {
boolean enable= store.getBoolean(ORDER_PROPOSALS);
jcp.orderProposalsAlphabetically(enable);
} else if (ADD_INCLUDE.equals(key)) {
boolean enabled= store.getBoolean(ADD_INCLUDE);
jcp.allowAddingIncludes(enabled);
}
}
/**

View file

@ -0,0 +1,557 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistantExtension2;
import org.eclipse.jface.text.contentassist.IContentAssistantExtension3;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.internal.ui.CUIMessages;
import org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog;
import org.eclipse.cdt.internal.ui.util.Messages;
/**
* A content assist processor that aggregates the proposals of the
* {@link org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer}s contributed via the
* <code>org.eclipse.cdt.ui.completionProposalComputer</code> extension point.
* <p>
* Subclasses may extend:
* <ul>
* <li><code>createContext</code> to provide the context object passed to the computers</li>
* <li><code>createProgressMonitor</code> to change the way progress is reported</li>
* <li><code>filterAndSort</code> to add sorting and filtering</li>
* <li><code>getContextInformationValidator</code> to add context validation (needed if any
* contexts are provided)</li>
* <li><code>getErrorMessage</code> to change error reporting</li>
* </ul>
* </p>
*
* @since 4.0
*/
public class ContentAssistProcessor implements IContentAssistProcessor {
private static final boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/ResultCollector")); //$NON-NLS-1$//$NON-NLS-2$
/**
* Dialog settings key for the "all categories are disabled" warning dialog. See
* {@link OptionalMessageDialog}.
*/
private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; //$NON-NLS-1$
private static final Comparator ORDER_COMPARATOR= new Comparator() {
public int compare(Object o1, Object o2) {
CompletionProposalCategory d1= (CompletionProposalCategory) o1;
CompletionProposalCategory d2= (CompletionProposalCategory) o2;
return d1.getSortOrder() - d2.getSortOrder();
}
};
private final List fCategories;
private final String fPartition;
private final ContentAssistant fAssistant;
private char[] fCompletionAutoActivationCharacters;
/* cycling stuff */
private int fRepetition= -1;
private List/*<List<CompletionProposalCategory>>*/ fCategoryIteration= null;
private String fIterationGesture= null;
private int fNumberOfComputedResults= 0;
private String fErrorMessage;
public ContentAssistProcessor(ContentAssistant assistant, String partition) {
Assert.isNotNull(partition);
Assert.isNotNull(assistant);
fPartition= partition;
fCategories= CompletionProposalComputerRegistry.getDefault().getProposalCategories();
fAssistant= assistant;
fAssistant.addCompletionListener(new ICompletionListener() {
/*
* @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionStarted(org.eclipse.jface.text.contentassist.ContentAssistEvent)
*/
public void assistSessionStarted(ContentAssistEvent event) {
if (event.processor != ContentAssistProcessor.this)
return;
fIterationGesture= getIterationGesture();
KeySequence binding= getIterationBinding();
// this may show the warning dialog if all categories are disabled
fCategoryIteration= getCategoryIteration();
for (Iterator it= fCategories.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
cat.sessionStarted();
}
fRepetition= 0;
if (event.assistant instanceof IContentAssistantExtension2) {
IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant;
if (fCategoryIteration.size() == 1) {
extension.setRepeatedInvocationMode(false);
extension.setShowEmptyList(false);
} else {
extension.setRepeatedInvocationMode(true);
extension.setStatusLineVisible(true);
extension.setStatusMessage(createIterationMessage());
extension.setShowEmptyList(true);
if (extension instanceof IContentAssistantExtension3) {
IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension;
((ContentAssistant) ext3).setRepeatedInvocationTrigger(binding);
}
}
}
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionEnded(org.eclipse.jface.text.contentassist.ContentAssistEvent)
*/
public void assistSessionEnded(ContentAssistEvent event) {
if (event.processor != ContentAssistProcessor.this)
return;
for (Iterator it= fCategories.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
cat.sessionEnded();
}
fCategoryIteration= null;
fRepetition= -1;
fIterationGesture= null;
if (event.assistant instanceof IContentAssistantExtension2) {
IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant;
extension.setShowEmptyList(false);
extension.setRepeatedInvocationMode(false);
extension.setStatusLineVisible(false);
if (extension instanceof IContentAssistantExtension3) {
IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension;
((ContentAssistant) ext3).setRepeatedInvocationTrigger(null);
}
}
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionListener#selectionChanged(org.eclipse.jface.text.contentassist.ICompletionProposal, boolean)
*/
public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {}
});
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
*/
public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
long start= DEBUG ? System.currentTimeMillis() : 0;
clearState();
IProgressMonitor monitor= createProgressMonitor();
monitor.beginTask(ContentAssistMessages.ContentAssistProcessor_computing_proposals, fCategories.size() + 1);
ContentAssistInvocationContext context= createContext(viewer, offset);
long setup= DEBUG ? System.currentTimeMillis() : 0;
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_proposals);
List proposals= collectProposals(viewer, offset, monitor, context);
long collect= DEBUG ? System.currentTimeMillis() : 0;
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_proposals);
List filtered= filterAndSortProposals(proposals, monitor, context);
fNumberOfComputedResults= filtered.size();
long filter= DEBUG ? System.currentTimeMillis() : 0;
ICompletionProposal[] result= (ICompletionProposal[]) filtered.toArray(new ICompletionProposal[filtered.size()]);
monitor.done();
if (DEBUG) {
System.err.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$
System.err.println("Code Assist (setup):\t" + (setup - start) ); //$NON-NLS-1$
System.err.println("Code Assist (collect):\t" + (collect - setup) ); //$NON-NLS-1$
System.err.println("Code Assist (sort):\t" + (filter - collect) ); //$NON-NLS-1$
}
return result;
}
private void clearState() {
fErrorMessage=null;
fNumberOfComputedResults= 0;
}
private List collectProposals(ITextViewer viewer, int offset, IProgressMonitor monitor, ContentAssistInvocationContext context) {
List proposals= new ArrayList();
List providers= getCategories();
for (Iterator it= providers.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
List computed= cat.computeCompletionProposals(context, fPartition, new SubProgressMonitor(monitor, 1));
proposals.addAll(computed);
if (fErrorMessage == null)
fErrorMessage= cat.getErrorMessage();
}
return proposals;
}
/**
* Filters and sorts the proposals. The passed list may be modified
* and returned, or a new list may be created and returned.
*
* @param proposals the list of collected proposals (element type:
* {@link ICompletionProposal})
* @param monitor a progress monitor
* @param context TODO
* @return the list of filtered and sorted proposals, ready for
* display (element type: {@link ICompletionProposal})
*/
protected List filterAndSortProposals(List proposals, IProgressMonitor monitor, ContentAssistInvocationContext context) {
return proposals;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
clearState();
IProgressMonitor monitor= createProgressMonitor();
monitor.beginTask(ContentAssistMessages.ContentAssistProcessor_computing_contexts, fCategories.size() + 1);
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_contexts);
List proposals= collectContextInformation(viewer, offset, monitor);
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_contexts);
List filtered= filterAndSortContextInformation(proposals, monitor);
fNumberOfComputedResults= filtered.size();
IContextInformation[] result= (IContextInformation[]) filtered.toArray(new IContextInformation[filtered.size()]);
monitor.done();
return result;
}
private List collectContextInformation(ITextViewer viewer, int offset, IProgressMonitor monitor) {
List proposals= new ArrayList();
ContentAssistInvocationContext context= createContext(viewer, offset);
List providers= getCategories();
for (Iterator it= providers.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
List computed= cat.computeContextInformation(context, fPartition, new SubProgressMonitor(monitor, 1));
proposals.addAll(computed);
if (fErrorMessage == null)
fErrorMessage= cat.getErrorMessage();
}
return proposals;
}
/**
* Filters and sorts the context information objects. The passed
* list may be modified and returned, or a new list may be created
* and returned.
*
* @param contexts the list of collected proposals (element type:
* {@link IContextInformation})
* @param monitor a progress monitor
* @return the list of filtered and sorted proposals, ready for
* display (element type: {@link IContextInformation})
*/
protected List filterAndSortContextInformation(List contexts, IProgressMonitor monitor) {
return contexts;
}
/**
* Sets this processor's set of characters triggering the activation of the
* completion proposal computation.
*
* @param activationSet the activation set
*/
public final void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
fCompletionAutoActivationCharacters= activationSet;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
public final char[] getCompletionProposalAutoActivationCharacters() {
return fCompletionAutoActivationCharacters;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
*/
public char[] getContextInformationAutoActivationCharacters() {
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
*/
public String getErrorMessage() {
if (fNumberOfComputedResults > 0)
return null;
if (fErrorMessage != null)
return fErrorMessage;
return CUIMessages.getString("CEditor.contentassist.noCompletions"); //$NON-NLS-1$
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
return null;
}
/**
* Creates a progress monitor.
* <p>
* The default implementation creates a
* <code>NullProgressMonitor</code>.
* </p>
*
* @return a progress monitor
*/
protected IProgressMonitor createProgressMonitor() {
return new NullProgressMonitor();
}
/**
* Creates the context that is passed to the completion proposal
* computers.
*
* @param viewer the viewer that content assist is invoked on
* @param offset the content assist offset
* @return the context to be passed to the computers
*/
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
return new ContentAssistInvocationContext(viewer, offset);
}
private List getCategories() {
if (fCategoryIteration == null)
return fCategories;
int iteration= fRepetition % fCategoryIteration.size();
fAssistant.setStatusMessage(createIterationMessage());
fAssistant.setEmptyMessage(createEmptyMessage());
fRepetition++;
// fAssistant.setShowMessage(fRepetition % 2 != 0);
//
return (List) fCategoryIteration.get(iteration);
}
private List getCategoryIteration() {
List sequence= new ArrayList();
sequence.add(getDefaultCategories());
for (Iterator it= getSeparateCategories().iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
sequence.add(Collections.singletonList(cat));
}
return sequence;
}
private List getDefaultCategories() {
// default mix - enable all included computers
List included= getDefaultCategoriesUnchecked();
if (IDocument.DEFAULT_CONTENT_TYPE.equals(fPartition) && included.isEmpty() && !fCategories.isEmpty())
if (informUserAboutEmptyDefaultCategory())
// preferences were restored - recompute the default categories
included= getDefaultCategoriesUnchecked();
return included;
}
private List getDefaultCategoriesUnchecked() {
List included= new ArrayList();
for (Iterator it= fCategories.iterator(); it.hasNext();) {
CompletionProposalCategory category= (CompletionProposalCategory) it.next();
if (category.isIncluded() && category.hasComputers(fPartition))
included.add(category);
}
return included;
}
/**
* Informs the user about the fact that there are no enabled categories in the default content
* assist set and shows a link to the preferences.
*/
private boolean informUserAboutEmptyDefaultCategory() {
if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) {
final Shell shell= CUIPlugin.getActiveWorkbenchShell();
String title= ContentAssistMessages.ContentAssistProcessor_all_disabled_title;
String message= ContentAssistMessages.ContentAssistProcessor_all_disabled_message;
// see PreferencePage#createControl for the 'defaults' label
final String restoreButtonLabel= JFaceResources.getString("defaults"); //$NON-NLS-1$
final String linkMessage= Messages.format(ContentAssistMessages.ContentAssistProcessor_all_disabled_preference_link, LegacyActionTools.removeMnemonics(restoreButtonLabel));
final int restoreId= IDialogConstants.CLIENT_ID + 10;
final int settingsId= IDialogConstants.CLIENT_ID + 11;
final OptionalMessageDialog dialog= new OptionalMessageDialog(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY, shell, title, null /* default image */, message, MessageDialog.WARNING, new String[] { restoreButtonLabel, IDialogConstants.CLOSE_LABEL }, 1) {
/*
* @see org.eclipse.cdt.internal.ui.dialogs.OptionalMessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite)
*/
protected Control createCustomArea(Composite composite) {
// wrap link and checkbox in one composite without space
Composite parent= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.verticalSpacing= 0;
parent.setLayout(layout);
Composite linkComposite= new Composite(parent, SWT.NONE);
layout= new GridLayout();
layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
linkComposite.setLayout(layout);
Link link= new Link(linkComposite, SWT.NONE);
link.setText(linkMessage);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setReturnCode(settingsId);
close();
}
});
GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
gridData.widthHint= this.getMinimumMessageWidth();
link.setLayoutData(gridData);
// create checkbox and "don't show this message" prompt
super.createCustomArea(parent);
return parent;
}
/*
* @see org.eclipse.jface.dialogs.MessageDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
*/
protected void createButtonsForButtonBar(Composite parent) {
Button[] buttons= new Button[2];
buttons[0]= createButton(parent, restoreId, restoreButtonLabel, false);
buttons[1]= createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true);
setButtons(buttons);
}
};
int returnValue= dialog.open();
if (restoreId == returnValue || settingsId == returnValue) {
if (restoreId == returnValue) {
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
store.setToDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
store.setToDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
}
if (settingsId == returnValue)
PreferencesUtil.createPreferenceDialogOn(shell, "org.eclipse.cdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$
CompletionProposalComputerRegistry registry= CompletionProposalComputerRegistry.getDefault();
registry.reload();
return true;
}
}
return false;
}
private List getSeparateCategories() {
ArrayList sorted= new ArrayList();
for (Iterator it= fCategories.iterator(); it.hasNext();) {
CompletionProposalCategory category= (CompletionProposalCategory) it.next();
if (category.isSeparateCommand() && category.hasComputers(fPartition))
sorted.add(category);
}
Collections.sort(sorted, ORDER_COMPARATOR);
return sorted;
}
private String createEmptyMessage() {
return Messages.format(ContentAssistMessages.ContentAssistProcessor_empty_message, new String[]{getCategoryLabel(fRepetition)});
}
private String createIterationMessage() {
return Messages.format(ContentAssistMessages.ContentAssistProcessor_toggle_affordance_update_message, new String[]{ getCategoryLabel(fRepetition), fIterationGesture, getCategoryLabel(fRepetition + 1) });
}
private String getCategoryLabel(int repetition) {
int iteration= repetition % fCategoryIteration.size();
if (iteration == 0)
return ContentAssistMessages.ContentAssistProcessor_defaultProposalCategory;
return toString((CompletionProposalCategory) ((List) fCategoryIteration.get(iteration)).get(0));
}
private String toString(CompletionProposalCategory category) {
return category.getDisplayName();
}
private String getIterationGesture() {
TriggerSequence binding= getIterationBinding();
return binding != null ?
Messages.format(ContentAssistMessages.ContentAssistProcessor_toggle_affordance_press_gesture, new Object[] { binding.format() })
: ContentAssistMessages.ContentAssistProcessor_toggle_affordance_click_gesture;
}
private KeySequence getIterationBinding() {
final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
TriggerSequence binding= bindingSvc.getBestActiveBindingFor(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
if (binding instanceof KeySequence)
return (KeySequence) binding;
return null;
}
}

View file

@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.texteditor.HippieProposalProcessor;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
/**
* A computer wrapper for the hippie processor.
*
* @since 4.0
*/
public final class HippieProposalComputer implements ICompletionProposalComputer {
/** The wrapped processor. */
private final HippieProposalProcessor fProcessor= new HippieProposalProcessor();
/**
* Default ctor to make it instantiatable via the extension mechanism.
*/
public HippieProposalComputer() {
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
return Arrays.asList(fProcessor.computeCompletionProposals(context.getViewer(), context.getInvocationOffset()));
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
return Arrays.asList(fProcessor.computeContextInformation(context.getViewer(), context.getInvocationOffset()));
}
/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposalComputer#getErrorMessage()
*/
public String getErrorMessage() {
return fProcessor.getErrorMessage();
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionStarted()
*/
public void sessionStarted() {
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionEnded()
*/
public void sessionEnded() {
}
}

View file

@ -0,0 +1,203 @@
/*******************************************************************************
* 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.contentassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationExtension;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
import org.eclipse.cdt.internal.ui.text.Symbols;
/**
* A proposal computer wrapping the legacy {@link CCompletionProcessor2}.
*
* @since 4.0
*/
public class LegacyCompletionProposalComputer implements ICompletionProposalComputer {
private static final class ContextInformationWrapper implements IContextInformation, IContextInformationExtension {
private final IContextInformation fContextInformation;
private int fPosition;
public ContextInformationWrapper(IContextInformation contextInformation) {
fContextInformation= contextInformation;
}
/*
* @see IContextInformation#getContextDisplayString()
*/
public String getContextDisplayString() {
return fContextInformation.getContextDisplayString();
}
/*
* @see IContextInformation#getImage()
*/
public Image getImage() {
return fContextInformation.getImage();
}
/*
* @see IContextInformation#getInformationDisplayString()
*/
public String getInformationDisplayString() {
return fContextInformation.getInformationDisplayString();
}
/*
* @see IContextInformationExtension#getContextInformationPosition()
*/
public int getContextInformationPosition() {
return fPosition;
}
public void setContextInformationPosition(int position) {
fPosition= position;
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformation#equals(java.lang.Object)
*/
public boolean equals(Object object) {
if (object instanceof ContextInformationWrapper)
return fContextInformation.equals(((ContextInformationWrapper) object).fContextInformation);
else
return fContextInformation.equals(object);
}
}
private CCompletionProcessor2 fCompletionProcessor;
/**
* Default constructor is required (executable extension).
*/
public LegacyCompletionProposalComputer() {
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext= (CContentAssistInvocationContext)context;
return internalComputeCompletionProposals(context.getInvocationOffset(), cContext, monitor);
}
return Collections.EMPTY_LIST;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext= (CContentAssistInvocationContext)context;
int contextInformationPosition= guessContextInformationPosition(cContext);
if (contextInformationPosition >= 0) {
List result= addContextInformations(cContext, contextInformationPosition, monitor);
return result;
}
}
return Collections.EMPTY_LIST;
}
protected int guessContextInformationPosition(ContentAssistInvocationContext context) {
final int contextPosition= context.getInvocationOffset();
IDocument document= context.getDocument();
CHeuristicScanner scanner= new CHeuristicScanner(document);
int bound= Math.max(-1, contextPosition - 200);
// try the innermost scope of parentheses that looks like a method call
int pos= contextPosition - 1;
do {
int paren= scanner.findOpeningPeer(pos, bound, '(', ')');
if (paren == CHeuristicScanner.NOT_FOUND)
break;
int token= scanner.previousToken(paren - 1, bound);
// next token must be a method name (identifier) or the closing angle of a
// constructor call of a template type.
if (token == Symbols.TokenIDENT || token == Symbols.TokenGREATERTHAN) {
return paren - 1;
}
pos= paren - 1;
} while (true);
return context.getInvocationOffset();
}
private List addContextInformations(CContentAssistInvocationContext context, int offset, IProgressMonitor monitor) {
List proposals= internalComputeCompletionProposals(offset, context, monitor);
List result= new ArrayList(proposals.size());
for (Iterator it= proposals.iterator(); it.hasNext();) {
ICompletionProposal proposal= (ICompletionProposal) it.next();
IContextInformation contextInformation= proposal.getContextInformation();
if (contextInformation != null) {
ContextInformationWrapper wrapper= new ContextInformationWrapper(contextInformation);
wrapper.setContextInformationPosition(offset);
result.add(wrapper);
}
}
return result;
}
private List internalComputeCompletionProposals(int offset, CContentAssistInvocationContext context, IProgressMonitor monitor) {
IEditorPart editor= context.getEditor();
if (editor != null) {
fCompletionProcessor= new CCompletionProcessor2(editor);
ICompletionProposal[] proposals= fCompletionProcessor.computeCompletionProposals(context.getViewer(), offset);
if (proposals != null) {
return Arrays.asList(proposals);
}
}
return Collections.EMPTY_LIST;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#getErrorMessage()
*/
public String getErrorMessage() {
if (fCompletionProcessor != null) {
return fCompletionProcessor.getErrorMessage();
}
return null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionEnded()
*/
public void sessionEnded() {
fCompletionProcessor= null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionStarted()
*/
public void sessionStarted() {
}
}

View file

@ -0,0 +1,149 @@
/*******************************************************************************
* 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.contentassist;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.corext.template.c.CContextType;
import org.eclipse.cdt.internal.corext.template.c.CommentContextType;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
import org.eclipse.cdt.internal.ui.text.template.TemplateEngine;
/**
* A completion proposal computer for templates.
*
* @since 4.0
*/
public class TemplateCompletionProposalComputer implements ICompletionProposalComputer {
private final TemplateEngine fCTemplateEngine;
private final TemplateEngine fCommentTemplateEngine;
/**
* Default constructor is required (executable extension).
*/
public TemplateCompletionProposalComputer() {
TemplateContextType contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CContextType.ID);
if (contextType == null) {
contextType= new CContextType();
CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
}
if (contextType != null)
fCTemplateEngine= new TemplateEngine(contextType);
else
fCTemplateEngine= null;
contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CommentContextType.ID);
if (contextType == null) {
contextType= new CommentContextType();
CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
}
if (contextType != null)
fCommentTemplateEngine= new TemplateEngine(contextType);
else
fCommentTemplateEngine= null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
ITextViewer viewer= context.getViewer();
int offset= context.getInvocationOffset();
TemplateEngine engine= null;
try {
String partition= TextUtilities.getContentType(viewer.getDocument(), ICPartitions.C_PARTITIONING, offset, true);
if (partition.equals(ICPartitions.C_MULTI_LINE_COMMENT)) {
engine= fCommentTemplateEngine;
} else {
if (isValidContext(context)) {
engine= fCTemplateEngine;
}
}
} catch (BadLocationException x) {
return Collections.EMPTY_LIST;
}
if (engine != null && context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext= (CContentAssistInvocationContext)context;
ITranslationUnit tUnit = cContext.getTranslationUnit();
if (tUnit == null) {
return Collections.EMPTY_LIST;
}
engine.reset();
engine.complete(viewer, offset, tUnit);
List result= engine.getResults();
return result;
}
return Collections.EMPTY_LIST;
}
/**
* Checks whether the given invocation context looks valid for template completion.
*
* @param context the content assist invocation context
* @return <code>false</code> if the given invocation context looks like a field reference
*/
private boolean isValidContext(ContentAssistInvocationContext context) {
CHeuristicScanner scanner= new CHeuristicScanner(context.getDocument());
int start= context.getInvocationOffset();
return !scanner.looksLikeFieldReferenceBackward(start, Math.max(0, start-100));
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
return Collections.EMPTY_LIST;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#getErrorMessage()
*/
public String getErrorMessage() {
return null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionStarted()
*/
public void sessionStarted() {
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionEnded()
*/
public void sessionEnded() {
if (fCommentTemplateEngine != null) {
fCommentTemplateEngine.reset();
}
if (fCTemplateEngine != null) {
fCTemplateEngine.reset();
}
}
}

View file

@ -1,182 +0,0 @@
/*******************************************************************************
* 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.template;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
import org.eclipse.cdt.internal.corext.template.c.CContextType;
import org.eclipse.cdt.internal.corext.template.c.CommentContextType;
/**
* A completion processor for templates.
* Can be used directly as implementation of {@link IContentAssistProcessor} or
* as implementation of the extension point interface {@link ICompletionContributor}.
*
* @since 4.0
*/
public class CTemplateCompletionProcessor implements IContentAssistProcessor, ICompletionContributor {
private static final ICompletionProposal[] NO_PROPOSALS= new ICompletionProposal[0];
private static final IContextInformation[] NO_CONTEXTS= new IContextInformation[0];
private IEditorPart fEditor;
private final TemplateEngine fCTemplateEngine;
private final TemplateEngine fCommentTemplateEngine;
/**
* Create a new template completion processor to be used as <code>IContentAssistProcessor</code>.
*
* @param editor the editor, may not be <code>null</code>
*/
public CTemplateCompletionProcessor(IEditorPart editor) {
this();
Assert.isNotNull(editor);
fEditor= editor;
}
/**
* Default constructor is required (executable extension).
*/
public CTemplateCompletionProcessor() {
TemplateContextType contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CContextType.ID);
if (contextType == null) {
contextType= new CContextType();
CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
}
if (contextType != null)
fCTemplateEngine= new TemplateEngine(contextType);
else
fCTemplateEngine= null;
contextType= CUIPlugin.getDefault().getTemplateContextRegistry().getContextType(CommentContextType.ID);
if (contextType == null) {
contextType= new CommentContextType();
CUIPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
}
if (contextType != null)
fCommentTemplateEngine= new TemplateEngine(contextType);
else
fCommentTemplateEngine= null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
Assert.isNotNull(fEditor);
TemplateEngine engine;
try {
String partition= TextUtilities.getContentType(viewer.getDocument(), ICPartitions.C_PARTITIONING, offset, true);
if (partition.equals(ICPartitions.C_MULTI_LINE_COMMENT))
engine= fCommentTemplateEngine;
else
engine= fCTemplateEngine;
} catch (BadLocationException x) {
return NO_PROPOSALS;
}
if (engine != null) {
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(fEditor.getEditorInput());
if (workingCopy == null)
return NO_PROPOSALS;
engine.reset();
engine.complete(viewer, offset, workingCopy);
List result= engine.getResults();
return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]);
}
return NO_PROPOSALS;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
return NO_CONTEXTS;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
public char[] getCompletionProposalAutoActivationCharacters() {
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
*/
public char[] getContextInformationAutoActivationCharacters() {
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
*/
public String getErrorMessage() {
return null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionContributor#contributeCompletionProposals(org.eclipse.jface.text.ITextViewer, int, org.eclipse.cdt.core.model.IWorkingCopy, org.eclipse.cdt.core.dom.ast.ASTCompletionNode, java.lang.String, java.util.List)
*/
public void contributeCompletionProposals(ITextViewer viewer, int offset,
IWorkingCopy workingCopy, ASTCompletionNode completionNode,
String prefix, List proposals) {
// TODO We should use the completion node to determine the proper context for the templates
// For now we just keep the current behavior
TemplateEngine engine;
try {
String partition= TextUtilities.getContentType(viewer.getDocument(), ICPartitions.C_PARTITIONING, offset, true);
if (partition.equals(ICPartitions.C_MULTI_LINE_COMMENT))
engine= fCommentTemplateEngine;
else
engine= fCTemplateEngine;
} catch (BadLocationException x) {
return;
}
if (engine != null) {
engine.reset();
engine.complete(viewer, offset, workingCopy);
List result= engine.getResults();
proposals.addAll(result);
}
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* Copyright (c) 2005, 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
@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui;
@ -26,7 +27,6 @@ import org.eclipse.cdt.internal.ui.text.ICColorConstants;
*
* @since 2.0
*/
public class PreferenceConstants {
private PreferenceConstants() {
@ -671,6 +671,27 @@ public class PreferenceConstants {
*/
public static final String CVIEW_GROUP_INCLUDES= "org.eclipse.cdt.ui.cview.groupincludes"; //$NON-NLS-1$
/**
* A named preference that controls which completion proposal categories
* have been excluded from the default proposal list.
* <p>
* Value is of type <code>String</code>, a "\0"-separated list of identifiers.
* </p>
*
* @since 4.0
*/
public static final String CODEASSIST_EXCLUDED_CATEGORIES= "content_assist_disabled_computers"; //$NON-NLS-1$
/**
* A named preference that controls the order of the specific code assist commands.
* <p>
* Value is of type <code>String</code>, a "\0"-separated list of identifiers.
* </p>
*
* @since 4.0
*/
public static final String CODEASSIST_CATEGORY_ORDER= "content_assist_category_order"; //$NON-NLS-1$
/**
* A named preference that controls whether folding is enabled in the C editor.
* <p>
@ -985,5 +1006,9 @@ public class PreferenceConstants {
store.setDefault(PreferenceConstants.EDITOR_ESCAPE_STRINGS, false);
store.setDefault(PreferenceConstants.ENSURE_NEWLINE_AT_EOF, false);
// content assist
store.setDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, "org.eclipse.cdt.ui.textProposalCategory\0"); //$NON-NLS-1$
store.setDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER, "org.eclipse.cdt.ui.parserProposalCategory:65539\0org.eclipse.cdt.ui.textProposalCategory:65541\0org.eclipse.cdt.ui.templateProposalCategory:2\0"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,195 @@
/*******************************************************************************
* Copyright (c) 2005, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui.text.contentassist;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
/**
* Describes the context of an invocation of content assist in a text viewer. The context knows the
* document, the invocation offset and can lazily compute the identifier prefix preceding the
* invocation offset. It may know the viewer.
* <p>
* Subclasses may add information to their environment. For example, source code editors may provide
* specific context information such as an AST.
* </p>
* <p>
* Clients may instantiate and subclass.
* </p>
*
* @since 4.0
*/
public class ContentAssistInvocationContext {
/* state */
private final ITextViewer fViewer;
private final IDocument fDocument;
private final int fOffset;
/* cached additional info */
private CharSequence fPrefix;
/**
* Equivalent to
* {@linkplain #ContentAssistInvocationContext(ITextViewer, int) ContentAssistInvocationContext(viewer, viewer.getSelectedRange().x)}.
*
* @param viewer the text viewer that content assist is invoked in
*/
public ContentAssistInvocationContext(ITextViewer viewer) {
this(viewer, viewer.getSelectedRange().x);
}
/**
* Creates a new context for the given viewer and offset.
*
* @param viewer the text viewer that content assist is invoked in
* @param offset the offset into the viewer's document where content assist is invoked at
*/
public ContentAssistInvocationContext(ITextViewer viewer, int offset) {
Assert.isNotNull(viewer);
fViewer= viewer;
fDocument= null;
fOffset= offset;
}
/**
* Creates a new context with no viewer or invocation offset set.
*/
protected ContentAssistInvocationContext() {
fDocument= null;
fViewer= null;
fOffset= -1;
}
/**
* Creates a new context for the given document and offset.
*
* @param document the document that content assist is invoked in
* @param offset the offset into the document where content assist is invoked at
*/
public ContentAssistInvocationContext(IDocument document, int offset) {
Assert.isNotNull(document);
Assert.isTrue(offset >= 0);
fViewer= null;
fDocument= document;
fOffset= offset;
}
/**
* Returns the invocation offset.
*
* @return the invocation offset
*/
public final int getInvocationOffset() {
return fOffset;
}
/**
* Returns the viewer, <code>null</code> if not available.
*
* @return the viewer, possibly <code>null</code>
*/
public final ITextViewer getViewer() {
return fViewer;
}
/**
* Returns the document that content assist is invoked on, or <code>null</code> if not known.
*
* @return the document or <code>null</code>
*/
public IDocument getDocument() {
if (fDocument == null) {
if (fViewer == null)
return null;
return fViewer.getDocument();
}
return fDocument;
}
/**
* Computes the identifier (as specified by {@link Character#isJavaIdentifierPart(char)}) that
* immediately precedes the invocation offset.
*
* @return the prefix preceding the content assist invocation offset, <code>null</code> if
* there is no document
* @throws BadLocationException if accessing the document fails
*/
public CharSequence computeIdentifierPrefix() throws BadLocationException {
if (fPrefix == null) {
IDocument document= getDocument();
if (document == null)
return null;
int end= getInvocationOffset();
int start= end;
while (--start >= 0) {
if (!Character.isJavaIdentifierPart(document.getChar(start)))
break;
}
start++;
fPrefix= document.get(start, end - start);
}
return fPrefix;
}
/**
* Invocation contexts are equal if they describe the same context and are of the same type.
* This implementation checks for <code>null</code> values and class equality. Subclasses
* should extend this method by adding checks for their context relevant fields (but not
* necessarily cached values).
* <p>
* Example:
*
* <pre>
* class MyContext extends ContentAssistInvocationContext {
* private final Object fState;
* private Object fCachedInfo;
*
* ...
*
* public boolean equals(Object obj) {
* if (!super.equals(obj))
* return false;
* MyContext other= (MyContext) obj;
* return fState.equals(other.fState);
* }
* }
* </pre>
*
* </p>
* <p>
* Subclasses should also extend {@link Object#hashCode()}.
* </p>
*
* @param obj {@inheritDoc}
* @return {@inheritDoc}
*/
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!getClass().equals(obj.getClass()))
return false;
ContentAssistInvocationContext other= (ContentAssistInvocationContext) obj;
return (fViewer == null && other.fViewer == null || fViewer != null && fViewer.equals(other.fViewer)) && fOffset == other.fOffset && (fDocument == null && other.fDocument == null || fDocument != null && fDocument.equals(other.fDocument));
}
/*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 23459213 << 5 | (fViewer == null ? 0 : fViewer.hashCode() << 3) | fOffset;
}
}

View file

@ -0,0 +1,74 @@
/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui.text.contentassist;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
/**
* Computes completions and context information displayed by the C/C++ editor content assistant.
* Contributions to the <tt>org.eclipse.cdt.ui.completionProposalComputer</tt> extension point
* must implement this interface.
*
* @since 4.0
*/
public interface ICompletionProposalComputer {
/**
* Informs the computer that a content assist session has started. This call will always be
* followed by a {@link #sessionEnded()} call, but not necessarily by calls to
* {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals}
* or
* {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}.
*/
void sessionStarted();
/**
* Returns a list of completion proposals valid at the given invocation context.
*
* @param context the context of the content assist invocation
* @param monitor a progress monitor to report progress. The monitor is private to this
* invocation, i.e. there is no need for the receiver to spawn a sub monitor.
* @return a list of completion proposals (element type: {@link ICompletionProposal})
*/
List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor);
/**
* Returns context information objects valid at the given invocation context.
*
* @param context the context of the content assist invocation
* @param monitor a progress monitor to report progress. The monitor is private to this
* invocation, i.e. there is no need for the receiver to spawn a sub monitor.
* @return a list of context information objects (element type: {@link IContextInformation})
*/
List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor);
/**
* Returns the reason why this computer was unable to produce any completion proposals or
* context information.
*
* @return an error message or <code>null</code> if no error occurred
*/
String getErrorMessage();
/**
* Informs the computer that a content assist session has ended. This call will always be after
* any calls to
* {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals}
* and
* {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}.
*/
void sessionEnded();
}