com.redhat.ceylon.eclipse.code.quickfix.CeylonQuickFixController.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.ceylon.eclipse.code.quickfix.CeylonQuickFixController.java

Source

package com.redhat.ceylon.eclipse.code.quickfix;

/*******************************************************************************
 * Copyright (c) 2000, 2010 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
 *******************************************************************************/

import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectTypeChecker;
import static com.redhat.ceylon.eclipse.util.AnnotationUtils.getAnnotationModel;
import static com.redhat.ceylon.eclipse.util.AnnotationUtils.getAnnotationsForLine;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
import org.eclipse.jface.text.quickassist.QuickAssistAssistant;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.SimpleMarkerAnnotation;

import com.redhat.ceylon.compiler.typechecker.TypeChecker;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.eclipse.code.editor.CeylonAnnotation;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.util.MarkerUtils;

public class CeylonQuickFixController extends QuickAssistAssistant implements IQuickAssistProcessor {

    private CeylonQuickFixAssistant assistant;
    private CeylonEditor editor; //may only be used for quick assists!!!
    private IFile file;
    private Tree.CompilationUnit model;

    public CeylonQuickFixController(CeylonEditor editor) {
        assistant = new CeylonQuickFixAssistant();
        this.editor = editor;

        if (editor.getEditorInput() instanceof FileEditorInput) {
            FileEditorInput input = (FileEditorInput) editor.getEditorInput();
            if (input != null) {
                file = input.getFile();
            }
        }

        setQuickAssistProcessor(this);
    }

    public CeylonQuickFixController(IMarker marker) {
        assistant = new CeylonQuickFixAssistant();
        IFileEditorInput input = MarkerUtils.getInput(marker);
        if (input != null) {
            file = input.getFile();
            IProject project = file.getProject();
            IJavaProject javaProject = JavaCore.create(project);
            TypeChecker tc = getProjectTypeChecker(project);
            if (tc != null) {
                try {
                    for (IPackageFragmentRoot pfr : javaProject.getPackageFragmentRoots()) {
                        if (pfr.getPath().isPrefixOf(file.getFullPath())) {
                            IPath relPath = file.getFullPath().makeRelativeTo(pfr.getPath());
                            model = tc.getPhasedUnitFromRelativePath(relPath.toString()).getCompilationUnit();
                        }
                    }
                } catch (JavaModelException e) {
                    e.printStackTrace();
                }
            }
        }
        setQuickAssistProcessor(this);
    }

    Tree.CompilationUnit getRootNode() {
        if (editor != null) {
            return editor.getParseController().getRootNode();
        } else if (model != null) {
            //TODO: this is really slow ... get the tree from CeylonBuilder
            return (Tree.CompilationUnit) model;
        } else {
            return null;
        }
    }

    public String getErrorMessage() {
        return null;
    }

    @Override
    public boolean canFix(Annotation annotation) {
        return assistant.canFix(annotation);
    }

    @Override
    public boolean canAssist(IQuickAssistInvocationContext quickAssistContext) {
        return assistant.canAssist(quickAssistContext);
    }

    public boolean canFix(IMarker marker) throws CoreException {
        for (String type : assistant.getSupportedMarkerTypes()) {
            if (marker.getType().equals(type)) {
                MarkerAnnotation ma = new MarkerAnnotation(marker);
                return assistant.canFix(ma);
            }
        }
        return false;
    }

    public void collectProposals(IQuickAssistInvocationContext context, IAnnotationModel model,
            Collection<Annotation> annotations, boolean addQuickFixes, boolean addQuickAssists,
            Collection<ICompletionProposal> proposals) {
        ArrayList<ProblemLocation> problems = new ArrayList<ProblemLocation>();
        // collect problem locations and corrections from marker annotations
        for (Annotation curr : annotations) {
            if (curr instanceof CeylonAnnotation) {
                ProblemLocation problemLocation = getProblemLocation((CeylonAnnotation) curr, model);
                if (problemLocation != null) {
                    problems.add(problemLocation);
                }
            }
        }
        if (problems.isEmpty() && addQuickFixes) {
            for (Annotation curr : annotations) {
                if (curr instanceof SimpleMarkerAnnotation) {
                    collectMarkerProposals((SimpleMarkerAnnotation) curr, proposals);
                }
            }
        }

        ProblemLocation[] problemLocations = (ProblemLocation[]) problems
                .toArray(new ProblemLocation[problems.size()]);
        if (addQuickFixes) {
            collectCorrections(context, problemLocations, proposals);
        }
        if (addQuickAssists) {
            collectAssists(context, problemLocations, proposals);
        }
    }

    private static ProblemLocation getProblemLocation(CeylonAnnotation annotation, IAnnotationModel model) {
        int problemId = annotation.getId();
        if (problemId != -1) {
            Position pos = model.getPosition((Annotation) annotation);
            if (pos != null) {
                return new ProblemLocation(pos.getOffset(), pos.getLength(), annotation); // java problems all handled by the quick assist processors
            }
        }
        return null;
    }

    public void collectAssists(IQuickAssistInvocationContext context, ProblemLocation[] locations,
            Collection<ICompletionProposal> proposals) {
        //if (locations.length==0) {
        ((CeylonQuickFixAssistant) assistant).addProposals(context, editor, proposals);
        //}
    }

    private static void collectMarkerProposals(SimpleMarkerAnnotation annotation,
            Collection<ICompletionProposal> proposals) {
        IMarker marker = annotation.getMarker();
        IMarkerResolution[] res = IDE.getMarkerHelpRegistry().getResolutions(marker);
        if (res.length > 0) {
            for (int i = 0; i < res.length; i++) {
                proposals.add(new CeylonMarkerResolutionProposal(res[i], marker));
            }
        }
    }

    public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext quickAssistContext) {
        ArrayList<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
        ISourceViewer viewer = quickAssistContext.getSourceViewer();
        collectProposals(quickAssistContext, getAnnotationModel(viewer),
                getAnnotationsForLine(viewer, getLine(quickAssistContext, viewer)), true, true, proposals);
        return proposals.toArray(new ICompletionProposal[proposals.size()]);
    }

    private int getLine(IQuickAssistInvocationContext quickAssistContext, ISourceViewer viewer) {
        try {
            return viewer.getDocument().getLineOfOffset(quickAssistContext.getOffset());
        } catch (BadLocationException e) {
            e.printStackTrace();
            return 0;
        }
    }

    public void collectCorrections(IQuickAssistInvocationContext quickAssistContext, ProblemLocation[] locations,
            Collection<ICompletionProposal> proposals) {
        if (locations != null && locations.length > 0) {
            Tree.CompilationUnit rootNode = getRootNode();
            HashSet<Integer> handledProblems = new HashSet<Integer>(locations.length);
            for (int i = 0; i < locations.length; i++) {
                ProblemLocation curr = locations[i];
                Integer id = new Integer(curr.getProblemId());
                if (handledProblems.add(id)) {
                    assistant.addProposals(quickAssistContext, curr, file, rootNode, proposals);
                }
            }
        }
    }

}