/******************************************************************************* * Copyright Technophobia Ltd 2012 * * This file is part of the Substeps Eclipse Plugin. * * The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify * it under the terms of the Eclipse Public License v1.0. * * The Substeps Eclipse Plugin 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 * Eclipse Public License for more details. * * You should have received a copy of the Eclipse Public License * along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>. ******************************************************************************/ package com.technophobia.substeps.document.navigation; import static com.technophobia.substeps.FeatureEditorPlugin.instance; import java.util.regex.Pattern; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.handlers.HandlerUtil; import com.technophobia.eclipse.transformer.ProjectToJavaProjectTransformer; import com.technophobia.substeps.FeatureEditorPlugin; import com.technophobia.substeps.editor.FeatureEditor; import com.technophobia.substeps.model.ParentStep; import com.technophobia.substeps.model.StepImplementation; import com.technophobia.substeps.model.Syntax; /** * * @author imoore * */ public class JumpToSubStepDefinitionHandler extends AbstractHandler { private static final ProjectToJavaProjectTransformer PROJECT_TRANSFORMER = new ProjectToJavaProjectTransformer(); /** * {@inheritDoc} */ @Override public Object execute(final ExecutionEvent event) throws ExecutionException { final IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); final IWorkbenchPage page = window.getActivePage(); // TextEditor implements IEditorPart final IEditorPart activeEditor = page.getActiveEditor(); final IEditorInput editorInput = activeEditor.getEditorInput(); final IFile file = (IFile) editorInput.getAdapter(IFile.class); final boolean isFeatureFile = file.getFileExtension().toLowerCase().equals("feature"); final boolean isSubstepsFile = file.getFileExtension().toLowerCase().equals("substeps"); if (isFeatureFile || isSubstepsFile) { final IContainer container = file.getParent(); final IProject project = container.getProject(); final FeatureEditor currentEditor = (FeatureEditor) activeEditor.getAdapter(FeatureEditor.class); final IDocument currentDocument = currentEditor.getCurrentDocument(); final IEditorSite editorSite = activeEditor.getEditorSite(); if (editorSite != null) { final ISelectionProvider selectionProvider = editorSite.getSelectionProvider(); if (selectionProvider != null) { jumpToStepDefinition(page, project, currentDocument, selectionProvider); } } } // Must return null, apparently return null; } private void jumpToStepDefinition(final IWorkbenchPage page, final IProject project, final IDocument currentDocument, final ISelectionProvider selectionProvider) { final int offset = ((ITextSelection) selectionProvider.getSelection()).getOffset(); // Get the line from where we are final String currentLine = getCurrentLine(currentDocument, offset); if (currentLine != null) { instance().info("F3 lookup on line: " + currentLine); // Set the Syntax from SubstepSuggestionProvider final Syntax syntax = FeatureEditorPlugin.instance().syntaxFor(project); // We can be finding definitions written in either a Substeps file // or an annotated method in a Java class, these correspond to a // ParentStep or a StepImplementation in the Syntax respectively. final ParentStep parentStep = findParent(syntax, currentLine); if (parentStep != null) { // Open the user defined Substep file. OpenSubstepsEditor.open(page, PROJECT_TRANSFORMER.from(project), parentStep); } else { final StepImplementation stepImplementation = findStep(syntax, currentLine); if (stepImplementation != null) { OpenJavaEditor.open(PROJECT_TRANSFORMER.from(project), stepImplementation.getMethod()); } } } } private static final ParentStep findParent(final Syntax syntax, final String stepValue) { for (final ParentStep rootSubStep : syntax.getSortedRootSubSteps()) { if (Pattern.matches(rootSubStep.getParent().getPattern(), stepValue)) { return rootSubStep; } } return null; } private static final StepImplementation findStep(final Syntax syntax, final String stepValue) { for (final StepImplementation stepImplementation : syntax.getStepImplementations()) { if (Pattern.matches(stepImplementation.getValue(), stepValue)) { return stepImplementation; } } return null; } /** * @param currentDocument * @param offset * @return */ private String getCurrentLine(final IDocument currentDocument, final int offset) { String rtn = null; int lineNumber; try { lineNumber = currentDocument.getLineOfOffset(offset); final int lineStart = currentDocument.getLineOffset(lineNumber); String line = currentDocument.get(lineStart, currentDocument.getLineLength(lineNumber)); final int commentIdx = line.indexOf("#"); if (commentIdx >= 0) { line = line.substring(0, commentIdx); } rtn = line.trim(); } catch (final BadLocationException e) { FeatureEditorPlugin.instance().error("BadLocationException getting current line @offset: " + offset, e); } return rtn; } }