Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-dev] Re-done patches for bug 104792

Hello folks,

sorry for bugging you with badly working patches. I did the original ones with 
an SVN repository due to IT problems.

Now I a re-did them after figuring out a way to get the original CVS pserver 
access (by working from my home instead of from the office ...) and the patch 
format does look somewhat different. This should account for all the trouble.

For details about the content see 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=104792

Hope you'll like it and - Doug, good luck applying them this time!

Bye 


Norbert Ploett
Index: plugin.xml
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui.tests/plugin.xml,v
retrieving revision 1.37
diff -u -r1.37 plugin.xml
--- plugin.xml	15 Nov 2005 21:30:13 -0000	1.37
+++ plugin.xml	16 Jan 2006 07:53:39 -0000
@@ -121,5 +121,12 @@
             id="org.eclipse.cdt.ui.tests.DOMAST.DOMAST.IncludeStatementFilter">
       </filter>
    </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>
Index: ui/org/eclipse/cdt/ui/tests/text/contentassist/ProposalFilterPreferencesTest.java
===================================================================
RCS file: ui/org/eclipse/cdt/ui/tests/text/contentassist/ProposalFilterPreferencesTest.java
diff -N ui/org/eclipse/cdt/ui/tests/text/contentassist/ProposalFilterPreferencesTest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ui/org/eclipse/cdt/ui/tests/text/contentassist/ProposalFilterPreferencesTest.java	1 Jan 1970 00:00:00 -0000
@@ -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);
+	}
+}
Index: ui/org/eclipse/cdt/ui/tests/text/contentassist/TestProposalFilter.java
===================================================================
RCS file: ui/org/eclipse/cdt/ui/tests/text/contentassist/TestProposalFilter.java
diff -N ui/org/eclipse/cdt/ui/tests/text/contentassist/TestProposalFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ui/org/eclipse/cdt/ui/tests/text/contentassist/TestProposalFilter.java	1 Jan 1970 00:00:00 -0000
@@ -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 ;
+	}
+
+}
Index: src/org/eclipse/cdt/internal/ui/preferences/AbstractPreferencePage.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AbstractPreferencePage.java,v
retrieving revision 1.5
diff -u -r1.5 AbstractPreferencePage.java
--- src/org/eclipse/cdt/internal/ui/preferences/AbstractPreferencePage.java	23 Jun 2005 16:01:24 -0000	1.5
+++ src/org/eclipse/cdt/internal/ui/preferences/AbstractPreferencePage.java	16 Jan 2006 08:02:56 -0000
@@ -33,6 +33,7 @@
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Group;
@@ -63,6 +64,16 @@
 			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();
 	private SelectionListener fCheckBoxListener = new SelectionListener() {
@@ -157,6 +168,24 @@
 		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) {
 		PixelConverter pixelConverter= new PixelConverter(composite);
 		Label filler= new Label(composite, SWT.LEFT );
@@ -292,11 +321,22 @@
 			String key = (String) fTextFields.get(t);
 			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)
 	 */
 	public void init(IWorkbench workbench) {
Index: src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties,v
retrieving revision 1.39
diff -u -r1.39 PreferencesMessages.properties
--- src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties	23 Jun 2005 16:02:26 -0000	1.39
+++ src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties	16 Jan 2006 08:02:56 -0000
@@ -85,6 +85,7 @@
 CEditorPreferencePage.ContentAssistPage.autoActivationEnableDot=Enable "." as trigger
 CEditorPreferencePage.ContentAssistPage.autoActivationEnableArrow=Enable "->" as trigger
 CEditorPreferencePage.ContentAssistPage.autoActivationDelay=dela&y (ms)
+CEditorPreferencePage.ContentAssistPage.proposalFilterSelect=Completion Proposal Filter:
 CEditorPreferencePage.ContentAssistPage.completionProposalBackgroundColor=&Background for completion proposals:
 CEditorPreferencePage.ContentAssistPage.completionProposalForegroundColor=&Foreground for completion proposals:
 CEditorPreferencePage.ContentAssistPage.parameterBackgroundColor=Bac&kground for method parameters:
@@ -260,3 +261,4 @@
 
 #Indexer
 IndexerPrefs.description=Sets default Indexer Options for new Projects
+ProposalFilterPreferencesUtil.defaultFilterName=<Default Filter>
Index: src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java,v
retrieving revision 1.7
diff -u -r1.7 CodeAssistPreferencePage.java
--- src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java	23 Jun 2005 16:01:24 -0000	1.7
+++ src/org/eclipse/cdt/internal/ui/preferences/CodeAssistPreferencePage.java	16 Jan 2006 08:02:56 -0000
@@ -58,6 +58,7 @@
 		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));
 
         OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
 		overlayKeys.toArray(keys);
@@ -135,7 +136,10 @@
 //		label= PreferencesMessages.getString("CEditorPreferencePage.ContentAssistPage.parameterForegroundColor");
 //		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);
 
@@ -168,6 +172,8 @@
 		PreferenceConverter.setDefault(store, ContentAssistPreference.PARAMETERS_FOREGROUND, new RGB(0, 0, 0));
 		store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false);
 		store.setDefault(ContentAssistPreference.ADD_INCLUDE, true);
+		store.setDefault(ContentAssistPreference.PROPOSALS_FILTER, ProposalFilterPreferencesUtil.getProposalFilternamesAsString());  // $NON_NLS 1$
 
 	}
+	
 }
Index: src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java,v
retrieving revision 1.12
diff -u -r1.12 ContentAssistPreference.java
--- src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java	22 Jul 2005 14:55:55 -0000	1.12
+++ src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistPreference.java	16 Jan 2006 08:02:57 -0000
@@ -63,7 +63,9 @@
 	public final static String CURRENT_FILE_SEARCH_SCOPE= "content_assist_current_file_search_scope";	 //$NON-NLS-1$
 	/** Preference key for completion search scope */
 	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) {
 		RGB rgb= PreferenceConverter.getColor(store, key);
 		return manager.getColor(rgb);
Index: src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java,v
retrieving revision 1.27
diff -u -r1.27 CCompletionProcessor2.java
--- src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java	18 Oct 2005 14:55:33 -0000	1.27
+++ src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java	16 Jan 2006 08:02:57 -0000
@@ -22,17 +22,21 @@
 import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
 import org.eclipse.cdt.core.model.IWorkingCopy;
 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.util.ExternalEditorInput;
 import org.eclipse.cdt.ui.CUIPlugin;
 import org.eclipse.cdt.ui.text.ICCompletionProposal;
 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.IProject;
 import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
 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.jface.text.BadLocationException;
@@ -128,48 +132,12 @@
 				}
 			}
 
-			ICCompletionProposal[] propsArray = null;
+			IProposalFilter filter = getCompletionFilter();
+			ICCompletionProposal[] proposalsInput = (ICCompletionProposal[]) proposals.toArray(new ICCompletionProposal[proposals.size()]) ;
 			
-			if (!proposals.isEmpty()) {
-				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;
-				}
-			}
+			ICCompletionProposal[] proposalsFiltered = filter.filterProposals(proposalsInput);
 			
-			return propsArray;
+			return proposalsFiltered;
 			
 		} catch (UnsupportedDialectException e) {
 			errorMessage = CUIMessages.getString(dialectError);
@@ -179,6 +147,32 @@
 		
 		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) {
         try {
Index: plugin.xml
===================================================================
RCS file: /cvsroot/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/plugin.xml,v
retrieving revision 1.179
diff -u -r1.179 plugin.xml
--- plugin.xml	21 Dec 2005 21:01:29 -0000	1.179
+++ plugin.xml	16 Jan 2006 08:02:55 -0000
@@ -17,6 +17,7 @@
    <extension-point id="textHovers" name="%textHoversName"/>
    <extension-point id="IndexerPage" name="Indexer Page" schema="schema/IndexerPage.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
          point="org.eclipse.core.runtime.adapters">
Index: src/org/eclipse/cdt/internal/ui/preferences/ProposalFilterPreferencesUtil.java
===================================================================
RCS file: src/org/eclipse/cdt/internal/ui/preferences/ProposalFilterPreferencesUtil.java
diff -N src/org/eclipse/cdt/internal/ui/preferences/ProposalFilterPreferencesUtil.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/internal/ui/preferences/ProposalFilterPreferencesUtil.java	1 Jan 1970 00:00:00 -0000
@@ -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;
+	}
+
+}
Index: src/org/eclipse/cdt/ui/text/contentassist/IProposalFilter.java
===================================================================
RCS file: src/org/eclipse/cdt/ui/text/contentassist/IProposalFilter.java
diff -N src/org/eclipse/cdt/ui/text/contentassist/IProposalFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/ui/text/contentassist/IProposalFilter.java	1 Jan 1970 00:00:00 -0000
@@ -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) ;
+
+}
Index: src/org/eclipse/cdt/internal/ui/text/contentassist/DefaultProposalFilter.java
===================================================================
RCS file: src/org/eclipse/cdt/internal/ui/text/contentassist/DefaultProposalFilter.java
diff -N src/org/eclipse/cdt/internal/ui/text/contentassist/DefaultProposalFilter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/internal/ui/text/contentassist/DefaultProposalFilter.java	1 Jan 1970 00:00:00 -0000
@@ -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;
+	}
+
+}
Index: schema/ProposalFilter.exsd
===================================================================
RCS file: schema/ProposalFilter.exsd
diff -N schema/ProposalFilter.exsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ schema/ProposalFilter.exsd	1 Jan 1970 00:00:00 -0000
@@ -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>

Back to the top