org.eclim.plugin.jdt.command.complete.CompletionProposalCollector.java Source code

Java tutorial

Introduction

Here is the source code for org.eclim.plugin.jdt.command.complete.CompletionProposalCollector.java

Source

/**
 * 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;
    }
}