Package info.cukes.editor.annotation

Source Code of info.cukes.editor.annotation.ScenarioAnnotationSearch

/*
* Copyright (c) 2012 FMR LLC.
* 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:
* FMR LLC - initial implementation
*/
package info.cukes.editor.annotation;

import info.cukes.editor.Activator;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaCore;
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.core.search.SearchRequestor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.osgi.service.log.LogService;

import cucumber.annotation.en.And;
import cucumber.annotation.en.But;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;

public class ScenarioAnnotationSearch implements IResourceChangeListener {
    private IJavaSearchScope scope;
    private Map<String, List<IAnnotation>> matches = new HashMap<String, List<IAnnotation>>();
    private boolean scopeHasChanged = true;

    @SuppressWarnings("serial")
    private static Map<String, Class<? extends Annotation>> supportedAnnotations = new HashMap<String, Class<? extends Annotation>>() {
        {
            put("Given", Given.class);
            put("Then", Then.class);
            put("When", When.class);
            put("But", But.class);
            put("And", And.class);
        }
    };

    public ScenarioAnnotationSearch() {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        workspace.addResourceChangeListener(this);

        updateSearchScope();
    }

    /**
     * Parse the current row, looking for a keyword ("Given", "And", etc.). If found, search all java code for that
     * annotation and return all potential matches.
     */
    public List<IAnnotation> search(ITextViewer viewer, int line) {
        IDocument doc = viewer.getDocument();
        try {
            IRegion lineRegion = doc.getLineInformation(line);

            final int offs = lineRegion.getOffset();
            final int len = lineRegion.getLength();

            String currentLine = viewer.getDocument().get(offs, len);

            String potentialAnnotationName = annotationInString(currentLine);

            if (potentialAnnotationName == null) {
                return Collections.emptyList();
            }

            /*
             * Found that the row begins with a supported annotation. Try to find a match in code.
             */
            if (supportedAnnotations.containsKey(potentialAnnotationName)) {
                SearchPattern pattern = SearchPattern.createPattern(potentialAnnotationName,
                    IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ALL_OCCURRENCES,
                    SearchPattern.R_EXACT_MATCH);

                /*
                 * Keep cached list of matches, unless a resource change has occurred.
                 */
                if (matches.get(potentialAnnotationName) != null) {
                    return matches.get(potentialAnnotationName);
                }

                try {
                    final List<IAnnotation> matchesForAnnotation = new ArrayList<IAnnotation>();
                    SearchRequestor requestor = new SearchRequestor() {
                        @Override
                        public void acceptSearchMatch(SearchMatch match) throws CoreException {
                            if (match.getElement() instanceof IMethod) {
                                IAnnotation[] annotations = ((IMethod) match.getElement()).getAnnotations();
                                for (IAnnotation annotation : annotations) {
                                    if (supportedAnnotations.containsKey(annotation.getElementName())) {
                                        matchesForAnnotation.add(annotation);
                                    }
                                }
                            }
                        }
                    };

                    if (scopeHasChanged) {
                        updateSearchScope();
                    }

                    SearchEngine engine = new SearchEngine();

                    Activator.getLogservice().log(LogService.LOG_ERROR, "Searching for " + potentialAnnotationName);
                    engine.search(pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope,
                        requestor, null);
                    matches.put(potentialAnnotationName, matchesForAnnotation);

                    return matchesForAnnotation;

                } catch (CoreException e) {
                    Activator.getLogservice().log(LogService.LOG_ERROR, e.getMessage());
                }
            }

        } catch (BadLocationException e) {

        }
        return Collections.emptyList();
    }

    protected void updateSearchScope() {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();

        try {
            List<IJavaProject> javaProjects = new ArrayList<IJavaProject>();
            for (IProject project : workspace.getRoot().getProjects()) {
                if (project.isOpen() && project.isNatureEnabled("org.eclipse.jdt.core.javanature")) {
                    javaProjects.add(JavaCore.create(project));
                }
            }

            scope = SearchEngine.createJavaSearchScope(javaProjects.toArray(new IJavaProject[javaProjects.size()]),
                false);

        } catch (CoreException e) {
            Activator.getLogservice().log(LogService.LOG_ERROR, e.getMessage());
        }

        scopeHasChanged = false;
    }

    @Override
    public void resourceChanged(IResourceChangeEvent event) {
        if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
            matches.clear();
            Activator.getLogservice().log(LogService.LOG_ERROR, event.getDelta().toString());

            IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
                public boolean visit(IResourceDelta delta) {
                    if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) {
                        scopeHasChanged = true;
                    }

                    return true;
                }
            };
            try {
                event.getDelta().accept(visitor);
            } catch (CoreException e) {

            }
        }
    }

    public static String annotationInString(String line) {
        String trimmedLine = line.trim();
        int firstSpaceIndex = trimmedLine.indexOf(" ");
        String potentialAnnotationName = null;
        if (firstSpaceIndex != -1) {
            potentialAnnotationName = trimmedLine.substring(0, firstSpaceIndex);
        } else if (trimmedLine.length() > 0) {
            potentialAnnotationName = trimmedLine;
        }

        if (potentialAnnotationName == null) {
            return null;
        }

        if (supportedAnnotations.containsKey(potentialAnnotationName)) {
            return potentialAnnotationName;
        }

        return null;
    }
}
TOP

Related Classes of info.cukes.editor.annotation.ScenarioAnnotationSearch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.