blob: 861e6925915f42a5c10770facf59634c4e59e74d [file] [log] [blame]
/*******************************************************************************
* 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.jdt.internal.ui.text.java;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext;
import org.eclipse.ui.IEditorPart;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.text.java.CompletionProposalComparator;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.internal.ui.JavaUIMessages;
/**
* Java completion processor.
*/
public class JavaCompletionProcessor extends ContentAssistProcessor {
private final static String VISIBILITY= JavaCore.CODEASSIST_VISIBILITY_CHECK;
private final static String ENABLED= "enabled"; //$NON-NLS-1$
private final static String DISABLED= "disabled"; //$NON-NLS-1$
private static final Set KEYWORDS;
private IContextInformationValidator fValidator;
private int fNumberOfComputedResults= 0;
private final CompletionProposalComparator fAlphaComparator;
private final CompletionProposalComparator fComparator;
protected final IEditorPart fEditor;
public JavaCompletionProcessor(IEditorPart editor, String partition) {
super(partition);
fEditor= editor;
fAlphaComparator= new CompletionProposalComparator();
fAlphaComparator.setOrderAlphabetically(true);
fComparator= new CompletionProposalComparator();
}
/**
* Tells this processor to restrict its proposal to those element
* visible in the actual invocation context.
*
* @param restrict <code>true</code> if proposals should be restricted
*/
public void restrictProposalsToVisibility(boolean restrict) {
Hashtable options= JavaCore.getOptions();
Object value= options.get(VISIBILITY);
if (value instanceof String) {
String newValue= restrict ? ENABLED : DISABLED;
if ( !newValue.equals(value)) {
options.put(VISIBILITY, newValue);
JavaCore.setOptions(options);
}
}
}
/**
* Tells this processor to order the proposals alphabetically.
*
* @param order <code>true</code> if proposals should be ordered.
*/
public void orderProposalsAlphabetically(boolean order) {
fComparator.setOrderAlphabetically(order);
}
/**
* Tells this processor to restrict is proposals to those
* starting with matching cases.
*
* @param restrict <code>true</code> if proposals should be restricted
*/
public void restrictProposalsToMatchingCases(boolean restrict) {
// not yet supported
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
*/
public String getErrorMessage() {
if (fNumberOfComputedResults == 0)
return JavaUIMessages.JavaEditor_codeassist_noCompletions;
return null;
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
if (fValidator == null)
fValidator= new JavaParameterListValidator();
return fValidator;
}
/*
* @see org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor#filterAndSort(java.util.List, org.eclipse.core.runtime.IProgressMonitor)
*/
protected List filterAndSortProposals(List proposals, IProgressMonitor monitor, TextContentAssistInvocationContext context) {
filter(proposals, context);
Collections.sort(proposals, fComparator);
fNumberOfComputedResults= proposals.size();
return proposals;
}
private void filter(List proposals, TextContentAssistInvocationContext context) {
/*
* TODO filtering is hard if the subjects come from multiple,
* often unknown sources. This method implements some heuristics
* that seem to work well.
*/
/*
* Duplicate filter:
* Goal: remove hippie proposals for stuff that already have java proposals
* Implementation:
* - sort alphanumerically, sorting hippies on top
* - remove any non-IJavaCompletionProposals that happen to have
* the same prefix completion text as another proposal.
*/
Collections.sort(proposals, fAlphaComparator);
IDocument document= context.getDocument();
int offset= context.getInvocationOffset();
ICompletionProposalExtension3 last= null;
for (ListIterator it= proposals.listIterator(proposals.size()); it.hasPrevious();) {
ICompletionProposal proposal= (ICompletionProposal) it.previous();
ICompletionProposalExtension3 current= null;
if (proposal instanceof ICompletionProposalExtension3) {
current= (ICompletionProposalExtension3) proposal;
if (last != null) {
String lastCompletion= getPrefixCompletionText(document, offset, last);
String curCompletion= getPrefixCompletionText(document, offset, current);
if (lastCompletion.equals(curCompletion) && !(current instanceof IJavaCompletionProposal))
it.remove();
}
}
last= current;
}
/*
* Keyword filter:
* Goal: remove any proposal that is equal to a
* Java keyword but is not a IJavaCompletionProposal
* Implementation:
* - remove all proposals that hava keyword display string
*/
for (Iterator iter= proposals.iterator(); iter.hasNext();) {
ICompletionProposal proposal= (ICompletionProposal) iter.next();
if (!(proposal instanceof IJavaCompletionProposal)) {
if (isKeyword(proposal.getDisplayString()))
iter.remove();
}
}
}
private String getPrefixCompletionText(IDocument document, int offset, ICompletionProposalExtension3 last) {
CharSequence prefixCompletionText= last.getPrefixCompletionText(document, offset);
return prefixCompletionText == null ? ((ICompletionProposal) last).getDisplayString() : prefixCompletionText.toString();
}
static {
Set keywords= new HashSet(42);
keywords.add("abstract"); //$NON-NLS-1$
keywords.add("assert"); //$NON-NLS-1$
keywords.add("break"); //$NON-NLS-1$
keywords.add("case"); //$NON-NLS-1$
keywords.add("catch"); //$NON-NLS-1$
keywords.add("class"); //$NON-NLS-1$
keywords.add("continue"); //$NON-NLS-1$
keywords.add("default"); //$NON-NLS-1$
keywords.add("do"); //$NON-NLS-1$
keywords.add("else"); //$NON-NLS-1$
keywords.add("elseif"); //$NON-NLS-1$
keywords.add("extends"); //$NON-NLS-1$
keywords.add("final"); //$NON-NLS-1$
keywords.add("finally"); //$NON-NLS-1$
keywords.add("for"); //$NON-NLS-1$
keywords.add("if"); //$NON-NLS-1$
keywords.add("implements"); //$NON-NLS-1$
keywords.add("import"); //$NON-NLS-1$
keywords.add("instanceof"); //$NON-NLS-1$
keywords.add("interface"); //$NON-NLS-1$
keywords.add("native"); //$NON-NLS-1$
keywords.add("new"); //$NON-NLS-1$
keywords.add("package"); //$NON-NLS-1$
keywords.add("private"); //$NON-NLS-1$
keywords.add("protected"); //$NON-NLS-1$
keywords.add("public"); //$NON-NLS-1$
keywords.add("return"); //$NON-NLS-1$
keywords.add("static"); //$NON-NLS-1$
keywords.add("strictfp"); //$NON-NLS-1$
keywords.add("super"); //$NON-NLS-1$
keywords.add("switch"); //$NON-NLS-1$
keywords.add("synchronized"); //$NON-NLS-1$
keywords.add("this"); //$NON-NLS-1$
keywords.add("throw"); //$NON-NLS-1$
keywords.add("throws"); //$NON-NLS-1$
keywords.add("transient"); //$NON-NLS-1$
keywords.add("try"); //$NON-NLS-1$
keywords.add("volatile"); //$NON-NLS-1$
keywords.add("while"); //$NON-NLS-1$
keywords.add("true"); //$NON-NLS-1$
keywords.add("false"); //$NON-NLS-1$
keywords.add("null"); //$NON-NLS-1$
KEYWORDS= Collections.unmodifiableSet(keywords);
}
private boolean isKeyword(String name) {
return KEYWORDS.contains(name);
}
/*
* @see org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor#filterAndSortContextInformation(java.util.List, org.eclipse.core.runtime.IProgressMonitor)
*/
protected List filterAndSortContextInformation(List contexts, IProgressMonitor monitor) {
fNumberOfComputedResults= contexts.size();
return super.filterAndSortContextInformation(contexts, monitor);
}
/*
* @see org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
*/
protected TextContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
return new JavaContentAssistInvocationContext(viewer, offset, fEditor);
}
}