mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 06:45:43 +02:00
Bug 104792 - Content proposal filtering feature.
This commit is contained in:
parent
c1c8415408
commit
e0a9f12895
13 changed files with 594 additions and 44 deletions
|
@ -121,5 +121,12 @@
|
||||||
id="org.eclipse.cdt.ui.tests.DOMAST.DOMAST.IncludeStatementFilter">
|
id="org.eclipse.cdt.ui.tests.DOMAST.DOMAST.IncludeStatementFilter">
|
||||||
</filter>
|
</filter>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.cdt.ui.ProposalFilter">
|
||||||
|
<ProposalFilter
|
||||||
|
class="org.eclipse.cdt.ui.tests.text.contentassist.TestProposalFilter"
|
||||||
|
id="org.eclipse.cdt.ui.tests.TestProposalFilter"
|
||||||
|
name="Testing Completion Filter"/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package org.eclipse.cdt.ui.tests.text.contentassist;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
|
||||||
|
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil.ComboState;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.core.runtime.IConfigurationElement;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test covers the convenience methods
|
||||||
|
* in org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil
|
||||||
|
*/
|
||||||
|
public class ProposalFilterPreferencesTest extends TestCase {
|
||||||
|
|
||||||
|
public void testPreferences() {
|
||||||
|
// Check that the test filter is among the filternames
|
||||||
|
String[] filterNames = ProposalFilterPreferencesUtil.getProposalFilterNames();
|
||||||
|
int index = -1 ;
|
||||||
|
for (int i = 0; i < filterNames.length; i++) {
|
||||||
|
String name = filterNames[i];
|
||||||
|
if (name.equals("Testing Completion Filter")) {
|
||||||
|
index = i ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue("Did not find expected filter!", index>=0);
|
||||||
|
|
||||||
|
// Set the preference to the tested filter
|
||||||
|
IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
String filterComboStateString = store.getString(ContentAssistPreference.PROPOSALS_FILTER);
|
||||||
|
ProposalFilterPreferencesUtil.ComboState state = ProposalFilterPreferencesUtil.getComboState(filterComboStateString);
|
||||||
|
StringBuffer newStateText = new StringBuffer();
|
||||||
|
newStateText.append(index+1); // First entry is always the <Default Filter>, index+1 must be selected
|
||||||
|
for (int i = 0; i < state.items.length; i++) {
|
||||||
|
String item = state.items[i];
|
||||||
|
newStateText.append(";");
|
||||||
|
newStateText.append(item);
|
||||||
|
}
|
||||||
|
store.setValue(ContentAssistPreference.PROPOSALS_FILTER, newStateText.toString());
|
||||||
|
|
||||||
|
// Now we can test preferred filter retrieval:
|
||||||
|
IConfigurationElement preferredElement = ProposalFilterPreferencesUtil.getPreferredFilterElement();
|
||||||
|
String extensionId = preferredElement.getAttribute("id");
|
||||||
|
assertNotNull("Configuration element was not found!", extensionId);
|
||||||
|
assertEquals("Unexpected element id", "org.eclipse.cdt.ui.tests.TestProposalFilter", extensionId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.eclipse.cdt.ui.tests.text.contentassist;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.text.ICCompletionProposal;
|
||||||
|
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy filter implementation for testing purposes
|
||||||
|
*/
|
||||||
|
public class TestProposalFilter implements IProposalFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This dummy filter method will return the original proposals unmodified.
|
||||||
|
*/
|
||||||
|
public ICCompletionProposal[] filterProposals(
|
||||||
|
ICCompletionProposal[] proposals) {
|
||||||
|
return proposals ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
<extension-point id="textHovers" name="%textHoversName"/>
|
<extension-point id="textHovers" name="%textHoversName"/>
|
||||||
<extension-point id="IndexerPage" name="Indexer Page" schema="schema/IndexerPage.exsd"/>
|
<extension-point id="IndexerPage" name="Indexer Page" schema="schema/IndexerPage.exsd"/>
|
||||||
<extension-point id="completionContributors" name="%completionContributors" schema="schema/completionContributors.exsd"/>
|
<extension-point id="completionContributors" name="%completionContributors" schema="schema/completionContributors.exsd"/>
|
||||||
|
<extension-point id="ProposalFilter" name="Code Completion Proposal Filter" schema="schema/ProposalFilter.exsd"/>
|
||||||
|
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.core.runtime.adapters">
|
point="org.eclipse.core.runtime.adapters">
|
||||||
|
|
122
core/org.eclipse.cdt.ui/schema/ProposalFilter.exsd
Normal file
122
core/org.eclipse.cdt.ui/schema/ProposalFilter.exsd
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
<?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="CodeCompletionFilter" name="Code Completion Filter"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
This extension point allows contributors to make their implementation of ICompletionFilter known to the platform.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<element name="extension">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element ref="ProposalFilter"/>
|
||||||
|
</sequence>
|
||||||
|
<attribute name="point" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="id" type="string">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="name" type="string">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.attribute translatable="true"/>
|
||||||
|
</appInfo>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="ProposalFilter">
|
||||||
|
<complexType>
|
||||||
|
<attribute name="id" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="name" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.attribute translatable="true"/>
|
||||||
|
</appInfo>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="class" type="string" use="required">
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.attribute kind="java"/>
|
||||||
|
</appInfo>
|
||||||
|
</annotation>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.section type="since"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
CDT 3.1
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.section type="examples"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
[Enter extension point usage example here.]
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.section type="apiInfo"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
[Enter API information here.]
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.section type="implementation"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
[Enter information about supplied implementation of this extension point.]
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<appInfo>
|
||||||
|
<meta.section type="copyright"/>
|
||||||
|
</appInfo>
|
||||||
|
<documentation>
|
||||||
|
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
</schema>
|
|
@ -33,6 +33,7 @@ import org.eclipse.swt.graphics.RGB;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Button;
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Combo;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.swt.widgets.Group;
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
@ -63,6 +64,16 @@ public abstract class AbstractPreferencePage extends PreferencePage implements I
|
||||||
fOverlayStore.setValue((String) fTextFields.get(text), text.getText());
|
fOverlayStore.setValue((String) fTextFields.get(text), text.getText());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected Map fComboBoxes = new HashMap();
|
||||||
|
private ModifyListener fComboBoxListener = new ModifyListener() {
|
||||||
|
public void modifyText(ModifyEvent e) {
|
||||||
|
Combo combo = (Combo) e.widget;
|
||||||
|
String state = ProposalFilterPreferencesUtil.comboStateAsString(combo);
|
||||||
|
fOverlayStore.setValue((String) fComboBoxes.get(combo), state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
protected Map fCheckBoxes = new HashMap();
|
protected Map fCheckBoxes = new HashMap();
|
||||||
private SelectionListener fCheckBoxListener = new SelectionListener() {
|
private SelectionListener fCheckBoxListener = new SelectionListener() {
|
||||||
|
@ -157,6 +168,24 @@ public abstract class AbstractPreferencePage extends PreferencePage implements I
|
||||||
return textControl;
|
return textControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addComboBox(Composite composite, String label, String key, int textLimit, int indentation) {
|
||||||
|
|
||||||
|
Label labelControl = new Label(composite, SWT.NONE);
|
||||||
|
labelControl.setText(label);
|
||||||
|
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
|
||||||
|
gd.horizontalIndent = indentation;
|
||||||
|
labelControl.setLayoutData(gd);
|
||||||
|
|
||||||
|
Combo comboControl = new Combo(composite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY); // TODO: When will the combo be disposed?
|
||||||
|
gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
|
||||||
|
gd.widthHint = convertWidthInCharsToPixels(textLimit + 1);
|
||||||
|
comboControl.setLayoutData(gd);
|
||||||
|
comboControl.setTextLimit(textLimit);
|
||||||
|
fComboBoxes.put(comboControl, key);
|
||||||
|
comboControl.addModifyListener(fComboBoxListener); // TODO: When will the listener be removed?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected void addFiller(Composite composite) {
|
protected void addFiller(Composite composite) {
|
||||||
PixelConverter pixelConverter= new PixelConverter(composite);
|
PixelConverter pixelConverter= new PixelConverter(composite);
|
||||||
Label filler= new Label(composite, SWT.LEFT );
|
Label filler= new Label(composite, SWT.LEFT );
|
||||||
|
@ -292,11 +321,22 @@ public abstract class AbstractPreferencePage extends PreferencePage implements I
|
||||||
String key = (String) fTextFields.get(t);
|
String key = (String) fTextFields.get(t);
|
||||||
t.setText(fOverlayStore.getString(key));
|
t.setText(fOverlayStore.getString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e = fComboBoxes.keySet().iterator();
|
||||||
|
while (e.hasNext()) {
|
||||||
|
Combo c = (Combo) e.next();
|
||||||
|
String key = (String) fComboBoxes.get(c);
|
||||||
|
String state = fOverlayStore.getString(key);
|
||||||
|
// Interpret the state string as a Combo state description
|
||||||
|
ProposalFilterPreferencesUtil.restoreComboFromString(c, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
|
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
|
||||||
*/
|
*/
|
||||||
public void init(IWorkbench workbench) {
|
public void init(IWorkbench workbench) {
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
|
||||||
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE));
|
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.CURRENT_FILE_SEARCH_SCOPE));
|
||||||
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PROJECT_SEARCH_SCOPE));
|
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.PROJECT_SEARCH_SCOPE));
|
||||||
|
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PROPOSALS_FILTER));
|
||||||
|
|
||||||
OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
|
OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
|
||||||
overlayKeys.toArray(keys);
|
overlayKeys.toArray(keys);
|
||||||
|
@ -135,7 +136,10 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
|
||||||
// label= PreferencesMessages.getString("CEditorPreferencePage.ContentAssistPage.parameterForegroundColor");
|
// label= PreferencesMessages.getString("CEditorPreferencePage.ContentAssistPage.parameterForegroundColor");
|
||||||
// addColorButton(contentAssistComposite, label, ContentAssistPreference.PARAMETERS_FOREGROUND, 0);
|
// addColorButton(contentAssistComposite, label, ContentAssistPreference.PARAMETERS_FOREGROUND, 0);
|
||||||
|
|
||||||
initializeFields();
|
label = PreferencesMessages.getString("CEditorPreferencePage.ContentAssistPage.proposalFilterSelect") ; //$NON-NLS-1$
|
||||||
|
addComboBox(contentAssistComposite, label, ContentAssistPreference.PROPOSALS_FILTER, 20, 0);
|
||||||
|
|
||||||
|
initializeFields();
|
||||||
|
|
||||||
PlatformUI.getWorkbench().getHelpSystem().setHelp(contentAssistComposite, ICHelpContextIds.C_EDITOR_CONTENT_ASSIST_PREF_PAGE);
|
PlatformUI.getWorkbench().getHelpSystem().setHelp(contentAssistComposite, ICHelpContextIds.C_EDITOR_CONTENT_ASSIST_PREF_PAGE);
|
||||||
|
|
||||||
|
@ -168,6 +172,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
|
||||||
PreferenceConverter.setDefault(store, ContentAssistPreference.PARAMETERS_FOREGROUND, new RGB(0, 0, 0));
|
PreferenceConverter.setDefault(store, ContentAssistPreference.PARAMETERS_FOREGROUND, new RGB(0, 0, 0));
|
||||||
store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
|
store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
|
||||||
store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
|
store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
|
||||||
|
store.setDefault(ContentAssistPreference.PROPOSALS_FILTER, ProposalFilterPreferencesUtil.getProposalFilternamesAsString()); // $NON_NLS 1$
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ CEditorPreferencePage.ContentAssistPage.autoActivationGroupTitle=Auto activation
|
||||||
CEditorPreferencePage.ContentAssistPage.autoActivationEnableDot=Enable "." as trigger
|
CEditorPreferencePage.ContentAssistPage.autoActivationEnableDot=Enable "." as trigger
|
||||||
CEditorPreferencePage.ContentAssistPage.autoActivationEnableArrow=Enable "->" as trigger
|
CEditorPreferencePage.ContentAssistPage.autoActivationEnableArrow=Enable "->" as trigger
|
||||||
CEditorPreferencePage.ContentAssistPage.autoActivationDelay=dela&y (ms)
|
CEditorPreferencePage.ContentAssistPage.autoActivationDelay=dela&y (ms)
|
||||||
|
CEditorPreferencePage.ContentAssistPage.proposalFilterSelect=Completion Proposal Filter:
|
||||||
CEditorPreferencePage.ContentAssistPage.completionProposalBackgroundColor=&Background for completion proposals:
|
CEditorPreferencePage.ContentAssistPage.completionProposalBackgroundColor=&Background for completion proposals:
|
||||||
CEditorPreferencePage.ContentAssistPage.completionProposalForegroundColor=&Foreground for completion proposals:
|
CEditorPreferencePage.ContentAssistPage.completionProposalForegroundColor=&Foreground for completion proposals:
|
||||||
CEditorPreferencePage.ContentAssistPage.parameterBackgroundColor=Bac&kground for method parameters:
|
CEditorPreferencePage.ContentAssistPage.parameterBackgroundColor=Bac&kground for method parameters:
|
||||||
|
@ -260,3 +261,4 @@ PathEntryVariableSelectionDialog.ExtensionDialog.description = Choose extension
|
||||||
|
|
||||||
#Indexer
|
#Indexer
|
||||||
IndexerPrefs.description=Sets default Indexer Options for new Projects
|
IndexerPrefs.description=Sets default Indexer Options for new Projects
|
||||||
|
ProposalFilterPreferencesUtil.defaultFilterName=<Default Filter>
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
package org.eclipse.cdt.internal.ui.preferences;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.core.runtime.IConfigurationElement;
|
||||||
|
import org.eclipse.core.runtime.IExtension;
|
||||||
|
import org.eclipse.core.runtime.IExtensionPoint;
|
||||||
|
import org.eclipse.core.runtime.InvalidRegistryObjectException;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.swt.widgets.Combo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class which encapsulates several utility functions
|
||||||
|
* related to code completion preference settings.
|
||||||
|
*/
|
||||||
|
public class ProposalFilterPreferencesUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private default constructor prevents instantiation
|
||||||
|
*/
|
||||||
|
private ProposalFilterPreferencesUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of proposal filter names
|
||||||
|
* (i.e. the human-readable text for display
|
||||||
|
* to fill into the Combo)
|
||||||
|
*/
|
||||||
|
public static String[] getProposalFilterNames() {
|
||||||
|
ArrayList names = new ArrayList();
|
||||||
|
try {
|
||||||
|
IExtensionPoint point = Platform.getExtensionRegistry()
|
||||||
|
.getExtensionPoint(CUIPlugin.PLUGIN_ID, "ProposalFilter"); //$NON-NLS-1$
|
||||||
|
if (point != null) {
|
||||||
|
IExtension[] extensions = point.getExtensions();
|
||||||
|
for (int i = 0; i < extensions.length; i++) {
|
||||||
|
IExtension extension = extensions[i];
|
||||||
|
IConfigurationElement[] elements = extension
|
||||||
|
.getConfigurationElements();
|
||||||
|
for (int j = 0; j < elements.length; ++j) {
|
||||||
|
IConfigurationElement element = elements[j];
|
||||||
|
if ("ProposalFilter".equals(element.getName())) { //$NON-NLS-1$
|
||||||
|
String filterName = element.getAttribute("name");
|
||||||
|
if (null != filterName) {
|
||||||
|
names.add(filterName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InvalidRegistryObjectException e) {
|
||||||
|
// No action required since we will at least be using the fail-safe default filter
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
}
|
||||||
|
String[] filterNames = (String[]) names
|
||||||
|
.toArray(new String[names.size()]);
|
||||||
|
return filterNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up all contributed completion proposal filters
|
||||||
|
* and return their names as a semicolon-separated list
|
||||||
|
* plus a leading entry for the selected index 0,
|
||||||
|
* plus a leading <default> entry. <br>
|
||||||
|
* A Combo may be initialized from this string.
|
||||||
|
* @return The list of filter names
|
||||||
|
*/
|
||||||
|
public static String getProposalFilternamesAsString() {
|
||||||
|
StringBuffer filterNames = new StringBuffer("0;");
|
||||||
|
filterNames.append("<Default Filter>"); // TODO: NP externalize this!
|
||||||
|
String[] names = getProposalFilterNames();
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
String name = names[i];
|
||||||
|
filterNames.append(";");
|
||||||
|
filterNames.append(name);
|
||||||
|
}
|
||||||
|
return filterNames.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the configuration element which corresponds
|
||||||
|
* to the human-readable filter name
|
||||||
|
* @param filterName The human-readable filter name
|
||||||
|
* @return The configuration element, or null if there is none
|
||||||
|
*/
|
||||||
|
public static IConfigurationElement getElementForName(String filterName) {
|
||||||
|
IConfigurationElement element = null;
|
||||||
|
IExtensionPoint point = Platform.getExtensionRegistry()
|
||||||
|
.getExtensionPoint(CUIPlugin.PLUGIN_ID, "ProposalFilter"); //$NON-NLS-1$
|
||||||
|
if (point != null) {
|
||||||
|
try {
|
||||||
|
IExtension[] extensions = point.getExtensions();
|
||||||
|
if (extensions.length >= 1) {
|
||||||
|
for (int i = 0; i < extensions.length; i++) {
|
||||||
|
IExtension extension = extensions[i];
|
||||||
|
|
||||||
|
IConfigurationElement[] elements = extension
|
||||||
|
.getConfigurationElements();
|
||||||
|
|
||||||
|
for (int j = 0; j < elements.length; ++j) {
|
||||||
|
IConfigurationElement testElement = elements[j];
|
||||||
|
if ("ProposalFilter".equals(testElement.getName())) { //$NON-NLS-1$
|
||||||
|
String testName = testElement
|
||||||
|
.getAttribute("name");
|
||||||
|
if ((null != testName)
|
||||||
|
&& (filterName.equals(testName))) {
|
||||||
|
element = testElement;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Did we find the corresponding element?
|
||||||
|
if (null != element)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InvalidRegistryObjectException e) {
|
||||||
|
// In case of failure we'll just return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state of a Combo consists of the list of entries
|
||||||
|
* and the index of the selected entry.
|
||||||
|
* This method converts the state of the given Combo
|
||||||
|
* to a string representation for storage in a preference store. <br>
|
||||||
|
* The string contains a semicolon-separated list of entries.
|
||||||
|
* The first entry is the index of the selected entry.
|
||||||
|
* The following entries are the texts of the individual fields. <br>
|
||||||
|
* Since the semicolon is the separator, the entries cannot contain semicolons.
|
||||||
|
* This method will replace semicolons with commas if any are found.
|
||||||
|
* @param combo The Combo whose state shall be converted
|
||||||
|
* @return A string representation of the Combo state
|
||||||
|
*/
|
||||||
|
public static String comboStateAsString(Combo combo) {
|
||||||
|
StringBuffer text = new StringBuffer();
|
||||||
|
int selectionIndex = combo.getSelectionIndex();
|
||||||
|
text.append(selectionIndex);
|
||||||
|
String[] entries = combo.getItems();
|
||||||
|
for (int i = 0; i < entries.length; i++) {
|
||||||
|
text.append(";");
|
||||||
|
String entry = entries[i].replaceAll(";", ",");
|
||||||
|
text.append(entry);
|
||||||
|
}
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state of a Combo consists of the list of entries
|
||||||
|
* and the index of the selected entry.
|
||||||
|
* This method takes a string representation of the state (e.g. from a preference store)
|
||||||
|
* and restores it into the Combo. <br>
|
||||||
|
* For a description of the text format see method comboStateAsString().
|
||||||
|
* @param combo The combo to be restored.
|
||||||
|
* @param text The text representation of the state.
|
||||||
|
*/
|
||||||
|
public static void restoreComboFromString(Combo combo, String text) {
|
||||||
|
try {
|
||||||
|
int endFirstEntry = text.indexOf(";");
|
||||||
|
if (endFirstEntry > 0) { // First entry must contain at least one character
|
||||||
|
String selectedString = text.substring(0, endFirstEntry);
|
||||||
|
int selectedIndex = Integer.parseInt(selectedString);
|
||||||
|
String[] entryList = text.substring(endFirstEntry + 1,
|
||||||
|
text.length()).split(";");
|
||||||
|
combo.setItems(entryList);
|
||||||
|
combo.select(selectedIndex);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// If this fails we just return the unmodified Combo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class wraps the data to initialize a Combo
|
||||||
|
*/
|
||||||
|
public static class ComboState {
|
||||||
|
public int selectedIndex;
|
||||||
|
|
||||||
|
public String[] items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to extract the state of a Combo
|
||||||
|
* from the state string stored e.g. in a preference store
|
||||||
|
* @param comboPreference The state string
|
||||||
|
* @return A ComboState instance.
|
||||||
|
*/
|
||||||
|
public static ComboState getComboState(String comboPreference) {
|
||||||
|
ComboState state = new ComboState();
|
||||||
|
try {
|
||||||
|
int endFirstEntry = comboPreference.indexOf(";");
|
||||||
|
if (endFirstEntry > 0) { // First entry must contain at least one character
|
||||||
|
String selectedString = comboPreference.substring(0,
|
||||||
|
endFirstEntry);
|
||||||
|
state.selectedIndex = Integer.parseInt(selectedString);
|
||||||
|
state.items = comboPreference.substring(endFirstEntry + 1,
|
||||||
|
comboPreference.length()).split(";");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// If this fails we return an empty ComboState
|
||||||
|
state.items = new String[0];
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the setting for the preferred proposal filter
|
||||||
|
* and return it's configuration element.
|
||||||
|
* @return The configuration element, or null if none is found.
|
||||||
|
*/
|
||||||
|
public static IConfigurationElement getPreferredFilterElement() {
|
||||||
|
IConfigurationElement preferredElement = null;
|
||||||
|
try {
|
||||||
|
IPreferenceStore store = CUIPlugin.getDefault()
|
||||||
|
.getPreferenceStore();
|
||||||
|
String filterComboStateString = store
|
||||||
|
.getString(ContentAssistPreference.PROPOSALS_FILTER);
|
||||||
|
ComboState state = getComboState(filterComboStateString);
|
||||||
|
preferredElement = getElementForName(state.items[state.selectedIndex]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// If anything goes wrong we'll just return null
|
||||||
|
}
|
||||||
|
return preferredElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,6 @@
|
||||||
package org.eclipse.cdt.internal.ui.text.contentassist;
|
package org.eclipse.cdt.internal.ui.text.contentassist;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.CDOM;
|
import org.eclipse.cdt.core.dom.CDOM;
|
||||||
|
@ -22,17 +21,21 @@ import org.eclipse.cdt.core.dom.IASTServiceProvider.UnsupportedDialectException;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
|
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
|
||||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
import org.eclipse.cdt.core.model.IWorkingCopy;
|
||||||
import org.eclipse.cdt.internal.ui.CUIMessages;
|
import org.eclipse.cdt.internal.ui.CUIMessages;
|
||||||
|
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
|
||||||
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
|
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
|
||||||
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
|
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
import org.eclipse.cdt.ui.text.ICCompletionProposal;
|
import org.eclipse.cdt.ui.text.ICCompletionProposal;
|
||||||
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
|
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
|
||||||
|
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IStorage;
|
import org.eclipse.core.resources.IStorage;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IConfigurationElement;
|
import org.eclipse.core.runtime.IConfigurationElement;
|
||||||
import org.eclipse.core.runtime.IExtension;
|
import org.eclipse.core.runtime.IExtension;
|
||||||
import org.eclipse.core.runtime.IExtensionPoint;
|
import org.eclipse.core.runtime.IExtensionPoint;
|
||||||
|
import org.eclipse.core.runtime.InvalidRegistryObjectException;
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
@ -128,48 +131,12 @@ public class CCompletionProcessor2 implements IContentAssistProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ICCompletionProposal[] propsArray = null;
|
IProposalFilter filter = getCompletionFilter();
|
||||||
|
ICCompletionProposal[] proposalsInput = (ICCompletionProposal[]) proposals.toArray(new ICCompletionProposal[proposals.size()]) ;
|
||||||
|
|
||||||
if (!proposals.isEmpty()) {
|
ICCompletionProposal[] proposalsFiltered = filter.filterProposals(proposalsInput);
|
||||||
errorMessage = null;
|
|
||||||
propsArray = (ICCompletionProposal[])proposals.toArray(new ICCompletionProposal[proposals.size()]);
|
|
||||||
CCompletionProposalComparator propsComp = new CCompletionProposalComparator();
|
|
||||||
propsComp.setOrderAlphabetically(true);
|
|
||||||
Arrays.sort(propsArray, propsComp);
|
|
||||||
|
|
||||||
// remove duplicates but leave the ones with return types
|
|
||||||
|
|
||||||
int last = 0;
|
|
||||||
int removed = 0;
|
|
||||||
for (int i = 1; i < propsArray.length; ++i) {
|
|
||||||
if (propsComp.compare(propsArray[last], propsArray[i]) == 0) {
|
|
||||||
// We want to leave the one that has the return string if any
|
|
||||||
boolean lastReturn = propsArray[last].getIdString() != propsArray[last].getDisplayString();
|
|
||||||
boolean iReturn = propsArray[i].getIdString() != propsArray[i].getDisplayString();
|
|
||||||
|
|
||||||
if (!lastReturn && iReturn)
|
|
||||||
// flip i down to last
|
|
||||||
propsArray[last] = propsArray[i];
|
|
||||||
|
|
||||||
// Remove the duplicate
|
|
||||||
propsArray[i] = null;
|
|
||||||
++removed;
|
|
||||||
} else
|
|
||||||
// update last
|
|
||||||
last = i;
|
|
||||||
}
|
|
||||||
if (removed > 0) {
|
|
||||||
// Strip out the null entries
|
|
||||||
ICCompletionProposal[] newArray = new ICCompletionProposal[propsArray.length - removed];
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < propsArray.length; ++i)
|
|
||||||
if (propsArray[i] != null)
|
|
||||||
newArray[j++] = propsArray[i];
|
|
||||||
propsArray = newArray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return propsArray;
|
return proposalsFiltered;
|
||||||
|
|
||||||
} catch (UnsupportedDialectException e) {
|
} catch (UnsupportedDialectException e) {
|
||||||
errorMessage = CUIMessages.getString(dialectError);
|
errorMessage = CUIMessages.getString(dialectError);
|
||||||
|
@ -179,6 +146,32 @@ public class CCompletionProcessor2 implements IContentAssistProcessor {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IProposalFilter getCompletionFilter() {
|
||||||
|
IProposalFilter filter = null;
|
||||||
|
try {
|
||||||
|
IConfigurationElement filterElement = ProposalFilterPreferencesUtil.getPreferredFilterElement();
|
||||||
|
if (null != filterElement) {
|
||||||
|
Object contribObject = filterElement
|
||||||
|
.createExecutableExtension("class"); //$NON-NLS-1$
|
||||||
|
if ((contribObject instanceof IProposalFilter)) {
|
||||||
|
filter = (IProposalFilter) contribObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InvalidRegistryObjectException e) {
|
||||||
|
// No action required since we will be using the fail-safe default filter
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
// No action required since we will be using the fail-safe default filter
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == filter) {
|
||||||
|
// fail-safe default implementation
|
||||||
|
filter = new DefaultProposalFilter();
|
||||||
|
}
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
private String scanPrefix(IDocument document, int end) {
|
private String scanPrefix(IDocument document, int end) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -63,7 +63,9 @@ public class ContentAssistPreference {
|
||||||
public final static String CURRENT_FILE_SEARCH_SCOPE= "content_assist_current_file_search_scope"; //$NON-NLS-1$
|
public final static String CURRENT_FILE_SEARCH_SCOPE= "content_assist_current_file_search_scope"; //$NON-NLS-1$
|
||||||
/** Preference key for completion search scope */
|
/** Preference key for completion search scope */
|
||||||
public final static String PROJECT_SEARCH_SCOPE= "content_assist_project_search_scope"; //$NON-NLS-1$
|
public final static String PROJECT_SEARCH_SCOPE= "content_assist_project_search_scope"; //$NON-NLS-1$
|
||||||
|
/** Preference key for completion filtering */
|
||||||
|
public final static String PROPOSALS_FILTER= "content_assist_proposal_filter"; //$NON_NLS 1$
|
||||||
|
|
||||||
private static Color getColor(IPreferenceStore store, String key, IColorManager manager) {
|
private static Color getColor(IPreferenceStore store, String key, IColorManager manager) {
|
||||||
RGB rgb= PreferenceConverter.getColor(store, key);
|
RGB rgb= PreferenceConverter.getColor(store, key);
|
||||||
return manager.getColor(rgb);
|
return manager.getColor(rgb);
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package org.eclipse.cdt.internal.ui.text.contentassist;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.text.ICCompletionProposal;
|
||||||
|
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default code completion filter: Remove duplicate entries on the basis of
|
||||||
|
* their id string. Use CCompletionProposalComparator for sorting.
|
||||||
|
*/
|
||||||
|
public class DefaultProposalFilter implements IProposalFilter {
|
||||||
|
|
||||||
|
public ICCompletionProposal[] filterProposals(
|
||||||
|
ICCompletionProposal[] proposals) {
|
||||||
|
|
||||||
|
CCompletionProposalComparator propsComp = new CCompletionProposalComparator();
|
||||||
|
propsComp.setOrderAlphabetically(true);
|
||||||
|
Arrays.sort(proposals, propsComp);
|
||||||
|
|
||||||
|
// remove duplicates but leave the ones with return types
|
||||||
|
|
||||||
|
int last = 0;
|
||||||
|
int removed = 0;
|
||||||
|
for (int i = 1; i < proposals.length; ++i) {
|
||||||
|
if (propsComp.compare(proposals[last], proposals[i]) == 0) {
|
||||||
|
// We want to leave the one that has the return string if any
|
||||||
|
boolean lastReturn = proposals[last].getIdString() != proposals[last]
|
||||||
|
.getDisplayString();
|
||||||
|
boolean iReturn = proposals[i].getIdString() != proposals[i]
|
||||||
|
.getDisplayString();
|
||||||
|
|
||||||
|
if (!lastReturn && iReturn)
|
||||||
|
// flip i down to last
|
||||||
|
proposals[last] = proposals[i];
|
||||||
|
|
||||||
|
// Remove the duplicate
|
||||||
|
proposals[i] = null;
|
||||||
|
++removed;
|
||||||
|
} else
|
||||||
|
// update last
|
||||||
|
last = i;
|
||||||
|
}
|
||||||
|
if (removed > 0) {
|
||||||
|
// Strip out the null entries
|
||||||
|
ICCompletionProposal[] newArray = new ICCompletionProposal[proposals.length
|
||||||
|
- removed];
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < proposals.length; ++i)
|
||||||
|
if (proposals[i] != null)
|
||||||
|
newArray[j++] = proposals[i];
|
||||||
|
proposals = newArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proposals;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.eclipse.cdt.ui.text.contentassist;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.text.ICCompletionProposal;
|
||||||
|
|
||||||
|
|
||||||
|
public interface IProposalFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a list of ICCompletionProposals <br>
|
||||||
|
* - Change the order of entries <br>
|
||||||
|
* - Remove undesired (duplicate) entries <br>
|
||||||
|
* - Supplement existing entries with additional information
|
||||||
|
* @param proposals The List of proposals
|
||||||
|
* @return The filtered list of proposals as array
|
||||||
|
*/
|
||||||
|
ICCompletionProposal[] filterProposals(ICCompletionProposal[] proposals) ;
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue