diff options
6 files changed, 112 insertions, 13 deletions
diff --git a/org.eclipse.jdt.ui/schema/javaCompletionProposalComputer.exsd b/org.eclipse.jdt.ui/schema/javaCompletionProposalComputer.exsd index c25fcf9300..0197988a6e 100644 --- a/org.eclipse.jdt.ui/schema/javaCompletionProposalComputer.exsd +++ b/org.eclipse.jdt.ui/schema/javaCompletionProposalComputer.exsd @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <!-- Schema file written by PDE --> -<schema targetNamespace="org.eclipse.jdt.ui"> +<schema targetNamespace="org.eclipse.jdt.ui" xmlns="http://www.w3.org/2001/XMLSchema"> <annotation> <appInfo> <meta.schema plugin="org.eclipse.jdt.ui" id="javaCompletionProposalComputer" name="Java Completion Proposal Computer"/> @@ -95,6 +95,15 @@ and must have a public 0-argument constructor. </appInfo> </annotation> </attribute> + <attribute name="needsSortingAfterFiltering" type="boolean" use="default" value="false"> + <annotation> + <documentation> + if the attribute is set to "true" it forces the content assist processor to resort the list of proposals every time a new token is entered or removed to the completion prefix. + +@since 3.8 + </documentation> + </annotation> + </attribute> </complexType> </element> diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java index ddccc314b5..0cf61fddbb 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Paul Fullbright <paul.fullbright@oracle.com> - content assist category enablement - http://bugs.eclipse.org/345213 + * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -76,6 +77,15 @@ public final class CompletionProposalCategory { private int fSortOrder= 0xffff - 1; private String fLastError= null; + /** + * Flag indicating whether any completion engine associated with this category requests + * resorting of its proposals after filtering is triggered. Filtering is, e.g., triggered when a + * user continues typing with an open completion window. + * + * @since 3.8 + */ + private boolean fNeedsSortingAfterFiltering; + CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) throws CoreException { fElement= element; fRegistry= registry; @@ -365,8 +375,10 @@ public final class CompletionProposalCategory { List<CompletionProposalComputerDescriptor> descriptors= new ArrayList<CompletionProposalComputerDescriptor>(fRegistry.getProposalComputerDescriptors()); for (Iterator<CompletionProposalComputerDescriptor> it= descriptors.iterator(); it.hasNext();) { CompletionProposalComputerDescriptor desc= it.next(); - if (desc.getCategory() == this) + if (desc.getCategory() == this){ desc.sessionStarted(); + fNeedsSortingAfterFiltering= fNeedsSortingAfterFiltering || desc.isSortingAfterFilteringNeeded(); + } if (fLastError == null) fLastError= desc.getErrorMessage(); } @@ -376,6 +388,7 @@ public final class CompletionProposalCategory { * Notifies the computers in this category of a proposal computation session end. */ public void sessionEnded() { + fNeedsSortingAfterFiltering= false; List<CompletionProposalComputerDescriptor> descriptors= new ArrayList<CompletionProposalComputerDescriptor>(fRegistry.getProposalComputerDescriptors()); for (Iterator<CompletionProposalComputerDescriptor> it= descriptors.iterator(); it.hasNext();) { CompletionProposalComputerDescriptor desc= it.next(); @@ -386,4 +399,14 @@ public final class CompletionProposalCategory { } } + /** + * Returns whether any completion proposal computer associated with this category requires + * proposals to be sorted again after filtering. + * + * @return <code>true</code> if any completion proposal computer in this category requires + * proposals to be sorted. + */ + public boolean isSortingAfterFilteringNeeded() { + return fNeedsSortingAfterFiltering; + } } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java index c9dfe2f9c9..c3f1bea52b 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -61,6 +62,8 @@ final class CompletionProposalComputerDescriptor { 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 needsSortingAfterFiltering attribute. */ + private static final String NEEDS_SORTING_AFTER_FILTERING= "needsSortingAfterFiltering"; //$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. */ @@ -131,6 +134,15 @@ final class CompletionProposalComputerDescriptor { * @since 3.4 */ boolean fTriedLoadingComputer= false; + + /** + * Tells whether this proposal engine provides dynamic content that needs to be sorted after its + * proposal have been filtered. Filtering happens, e.g., when a user continues typing with an + * open completion window. + * + * @since 3.8 + */ + private boolean fNeedsSortingAfterFiltering; /** @@ -174,6 +186,9 @@ final class CompletionProposalComputerDescriptor { String activateAttribute= element.getAttribute(ACTIVATE); fActivate= Boolean.valueOf(activateAttribute).booleanValue(); + String needsSortingAfterFilteringAttribute= element.getAttribute(NEEDS_SORTING_AFTER_FILTERING); + fNeedsSortingAfterFiltering= Boolean.valueOf(needsSortingAfterFilteringAttribute).booleanValue(); + fClass= element.getAttribute(CLASS); checkNotNull(fClass, CLASS); @@ -564,4 +579,13 @@ final class CompletionProposalComputerDescriptor { } } + /** + * Returns the <code>needsSortingAfterFiltering</code> flag of the described extension. + * + * @return the needsSortingAfterFiltering flag of the described extension + * @since 3.8 + */ + public boolean isSortingAfterFilteringNeeded() { + return fNeedsSortingAfterFiltering; + } } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java index aba09ea931..1441339012 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Paul Fullbright <paul.fullbright@oracle.com> - content assist category enablement - http://bugs.eclipse.org/345213 + * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -29,7 +30,9 @@ import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; @@ -63,6 +66,7 @@ import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.text.java.AbstractProposalSorter; import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; import org.eclipse.jdt.internal.ui.JavaPlugin; @@ -277,16 +281,18 @@ public class ContentAssistProcessor implements IContentAssistProcessor { * @return the list of proposals */ private List<ICompletionProposal> collectProposals(ITextViewer viewer, int offset, IProgressMonitor monitor, ContentAssistInvocationContext context) { + boolean needsSortingAfterFiltering= false; List<ICompletionProposal> proposals= new ArrayList<ICompletionProposal>(); List<CompletionProposalCategory> providers= getCategories(); for (Iterator<CompletionProposalCategory> it= providers.iterator(); it.hasNext();) { CompletionProposalCategory cat= it.next(); List<ICompletionProposal> computed= cat.computeCompletionProposals(context, fPartition, new SubProgressMonitor(monitor, 1)); proposals.addAll(computed); + needsSortingAfterFiltering= needsSortingAfterFiltering || (cat.isSortingAfterFilteringNeeded() && !computed.isEmpty()); if (fErrorMessage == null) fErrorMessage= cat.getErrorMessage(); } - + installProposalSorter(needsSortingAfterFiltering); return proposals; } @@ -630,4 +636,35 @@ public class ContentAssistProcessor implements IContentAssistProcessor { return (KeySequence) binding; return null; } + + /** + * Installs the proposal sorter to be used by the content assistant for resorting proposals + * after filtering. Sets the sorter to the system's default sorter if + * <code>needsSortingAfterFiltering</code> is <code>true</code>, <code>null</code> otherwise. + * + * @param needsSortingAfterFiltering the flag indicating whether a sorter should be passed to + * the content assistant + * @since 3.8 + * @see ProposalSorterRegistry#getCurrentSorter() the sorter used if <code>true</code> + */ + private void installProposalSorter(boolean needsSortingAfterFiltering) { + if (!needsSortingAfterFiltering) { + fAssistant.setSorter(null); + return; + } + + AbstractProposalSorter sorter= null; + ProposalSorterHandle currentSorter= ProposalSorterRegistry.getDefault().getCurrentSorter(); + try { + sorter= currentSorter.getSorter(); + } catch (InvalidRegistryObjectException x) { + JavaPlugin.log(currentSorter.createExceptionStatus(x)); + } catch (CoreException x) { + JavaPlugin.log(currentSorter.createExceptionStatus(x)); + } catch (RuntimeException x) { + JavaPlugin.log(currentSorter.createExceptionStatus(x)); + } + fAssistant.setSorter(sorter); + } + } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalSorterHandle.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalSorterHandle.java index fe59e1c8d3..4eb6c3f979 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalSorterHandle.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalSorterHandle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; @@ -133,7 +134,7 @@ public final class ProposalSorterHandle { * @throws InvalidRegistryObjectException if the extension is not valid any longer (e.g. due to * plug-in unloading) */ - private synchronized AbstractProposalSorter getSorter() throws CoreException, InvalidRegistryObjectException { + synchronized AbstractProposalSorter getSorter() throws CoreException, InvalidRegistryObjectException { if (fSorter == null) fSorter= createSorter(); return fSorter; @@ -213,21 +214,21 @@ public final class ProposalSorterHandle { return stats; } - private Status createExceptionStatus(InvalidRegistryObjectException x) { + Status createExceptionStatus(InvalidRegistryObjectException x) { // extension has become invalid - log & disable String disable= createBlameMessage(); String reason= JavaTextMessages.CompletionProposalComputerDescriptor_reason_invalid; return new Status(IStatus.INFO, JavaPlugin.getPluginId(), IStatus.OK, disable + " " + reason, x); //$NON-NLS-1$ } - private Status createExceptionStatus(CoreException x) { + Status createExceptionStatus(CoreException x) { // unable to instantiate the extension - log & disable String disable= createBlameMessage(); String reason= JavaTextMessages.CompletionProposalComputerDescriptor_reason_instantiation; return new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, disable + " " + reason, x); //$NON-NLS-1$ } - private Status createExceptionStatus(RuntimeException x) { + Status createExceptionStatus(RuntimeException x) { // misbehaving extension - log & disable String disable= createBlameMessage(); String reason= JavaTextMessages.CompletionProposalComputerDescriptor_reason_runtime_ex; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java index 2fd7d79d6a..ee5a827a81 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2011 IBM Corporation and others. + * Copyright (c) 2006, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Marcel Bruch <bruch@cs.tu-darmstadt.de> - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 *******************************************************************************/ package org.eclipse.jdt.ui.text.java; @@ -15,6 +16,7 @@ import java.util.Comparator; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposalSorter; /** * Abstract base class for sorters contributed to the @@ -30,7 +32,7 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal; * * @since 3.2 */ -public abstract class AbstractProposalSorter implements Comparator<ICompletionProposal> { +public abstract class AbstractProposalSorter implements Comparator<ICompletionProposal>, ICompletionProposalSorter { /** * Creates a new sorter. Note that subclasses must provide a zero-argument constructor to be @@ -40,7 +42,9 @@ public abstract class AbstractProposalSorter implements Comparator<ICompletionPr } /** - * Called once before sorting. + * Called once before initial sorting starts the first time. Note that if a completion engine + * needs subsequent sorting of its proposals (e.g., after some proposals get filtered due to + * changes in the completion prefix), this method is <i>not</i> called again. * <p> * Clients may override, the default implementation does nothing. * </p> @@ -63,7 +67,8 @@ public abstract class AbstractProposalSorter implements Comparator<ICompletionPr public abstract int compare(ICompletionProposal p1, ICompletionProposal p2); /** - * Called once after sorting. + * Called once after the initial sorting finished. Note that even if a completion engine causes + * a subsequent sorting of its proposals, this method is <i>not</i> called again. * <p> * Clients may override, the default implementation does nothing. * </p> |