/**
* Copyright (C) 2005 - 2012 Eric Van Dewoestine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.eclim.plugin.jdt.command.complete;
import java.util.ArrayList;
import java.util.List;
import org.eclim.command.Error;
import org.eclim.plugin.jdt.command.include.ImportUtils;
import org.eclim.plugin.jdt.command.search.SearchRequestor;
import org.eclim.util.file.FileOffsets;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.ui.JavaPlugin;
/**
* Extension to eclipse CompletionProposalCollector that saves reference to
* original CompletionProposals.
*
* @author Eric Van Dewoestine
*/
public class CompletionProposalCollector
extends org.eclipse.jdt.ui.text.java.CompletionProposalCollector
{
private ArrayList<CompletionProposal> proposals =
new ArrayList<CompletionProposal>();
private ArrayList<String> imports;
private Error error;
public CompletionProposalCollector (ICompilationUnit cu)
{
super(cu);
}
public void accept(CompletionProposal proposal)
{
try {
if (isFiltered(proposal)){
return;
}
if (proposal.getKind() != CompletionProposal.POTENTIAL_METHOD_DECLARATION) {
switch (proposal.getKind()) {
case CompletionProposal.KEYWORD:
case CompletionProposal.PACKAGE_REF:
case CompletionProposal.TYPE_REF:
case CompletionProposal.FIELD_REF:
case CompletionProposal.METHOD_REF:
case CompletionProposal.METHOD_NAME_REFERENCE:
case CompletionProposal.METHOD_DECLARATION:
case CompletionProposal.ANONYMOUS_CLASS_DECLARATION:
case CompletionProposal.LABEL_REF:
case CompletionProposal.LOCAL_VARIABLE_REF:
case CompletionProposal.VARIABLE_DECLARATION:
case CompletionProposal.ANNOTATION_ATTRIBUTE_REF:
case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
proposals.add(proposal);
super.accept(proposal);
break;
default:
// do nothing
}
}
} catch (IllegalArgumentException e) {
// all signature processing method may throw IAEs
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=84657
// don't abort, but log and show all the valid proposals
JavaPlugin.log(
new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK,
"Exception when processing proposal for: " +
String.valueOf(proposal.getCompletion()), e));
}
}
public CompletionProposal getProposal(int index)
{
return (CompletionProposal)proposals.get(index);
}
public void completionFailure(IProblem problem)
{
ICompilationUnit src = getCompilationUnit();
IJavaProject javaProject = src.getJavaProject();
IProject project = javaProject.getProject();
// undefined type or attempting to complete static members of an unimported
// type
if (problem.getID() == IProblem.UndefinedType ||
problem.getID() == IProblem.UnresolvedVariable)
{
try{
SearchPattern pattern =
SearchPattern.createPattern(problem.getArguments()[0],
IJavaSearchConstants.TYPE,
IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
IJavaSearchScope scope =
SearchEngine.createJavaSearchScope(new IJavaElement[]{javaProject});
SearchRequestor requestor = new SearchRequestor();
SearchEngine engine = new SearchEngine();
SearchParticipant[] participants =
new SearchParticipant[]{SearchEngine.getDefaultSearchParticipant()};
engine.search(pattern, participants, scope, requestor, null);
if (requestor.getMatches().size() > 0){
imports = new ArrayList<String>();
for (SearchMatch match : requestor.getMatches()){
if(match.getAccuracy() != SearchMatch.A_ACCURATE){
continue;
}
IJavaElement element = (IJavaElement)match.getElement();
String name = null;
switch(element.getElementType()){
case IJavaElement.TYPE:
IType type = (IType)element;
if(Flags.isPublic(type.getFlags())){
name = type.getFullyQualifiedName();
}
break;
case IJavaElement.METHOD:
case IJavaElement.FIELD:
name = ((IType)element.getParent()).getFullyQualifiedName() +
'.' + element.getElementName();
break;
}
if (name != null){
name = name.replace('$', '.');
if (!ImportUtils.isImportExcluded(project, name)){
imports.add(name);
}
}
}
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
IResource resource = src.getResource();
String relativeName = resource.getProjectRelativePath().toString();
if (new String(problem.getOriginatingFileName()).endsWith(relativeName)){
String filename = resource.getLocation().toString();
// ignore the problem if a temp file is being used and the problem is that
// the type needs to be defined in its own file.
if (problem.getID() == IProblem.PublicClassMustMatchFileName &&
filename.indexOf("__eclim_temp_") != -1)
{
return;
}
FileOffsets offsets = FileOffsets.compile(filename);
int[] lineColumn = offsets.offsetToLineColumn(problem.getSourceStart());
error = new Error(
problem.getMessage(),
filename.replace("__eclim_temp_", ""),
lineColumn[0],
lineColumn[1],
problem.isWarning());
}
}
public List<String> getImports()
{
return imports;
}
public Error getError()
{
return error;
}
}