/**
* Aptana Studio
* Copyright (c) 2005-2012 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ruby.debug.ui;
import java.io.File;
import java.net.URI;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.ITextEditor;
import com.aptana.core.logging.IdeLog;
import com.aptana.core.util.StringUtil;
import com.aptana.editor.erb.IERBConstants;
import com.aptana.ruby.core.IRubyConstants;
import com.aptana.ruby.debug.core.IRubyLineBreakpoint;
import com.aptana.ruby.debug.core.RubyDebugModel;
import com.aptana.ruby.debug.core.launching.IRubyLaunchConfigurationConstants;
/**
* Adapter to create breakpoints in Ruby files.
*/
public class RubyLineBreakpointAdapter implements IToggleBreakpointsTarget
{
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException
{
IFileStore store = getFileStore(part);
if (store == null)
{
return;
}
URI uri = store.toURI();
IResource resource = null;
IPath fileName = null;
if ("file".equals(uri.getScheme())) //$NON-NLS-1$
{
File file = new File(uri);
fileName = Path.fromOSString(file.getAbsolutePath());
resource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(fileName);
}
if (resource == null)
{
// External file. Stick the marker on the workspace root
resource = ResourcesPlugin.getWorkspace().getRoot();
}
else
{
fileName = resource.getProjectRelativePath();
}
if (IdeLog.isTraceEnabled(RubyDebugUIPlugin.getDefault(), null))
{
IdeLog.logTrace(RubyDebugUIPlugin.getDefault(), MessageFormat.format(
"Toggling breakpoint for URI: {0}, filename: {1}. Marker being set on resource: {2}", //$NON-NLS-1$
uri.toString(), fileName, resource.getLocation().toOSString()));
}
ITextSelection textSelection = (ITextSelection) selection;
int lineNumber = textSelection.getStartLine();
IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager()
.getBreakpoints(IRubyLaunchConfigurationConstants.ID_RUBY_DEBUG_MODEL);
// Search for matching breakpoint. If we find one with same file, same line then we remove it and return.
for (int i = 0; i < breakpoints.length; i++)
{
IBreakpoint breakpoint = breakpoints[i];
if (!(breakpoint instanceof IRubyLineBreakpoint))
{
continue;
}
IRubyLineBreakpoint rubyLineBreakpoint = (IRubyLineBreakpoint) breakpoint;
if (rubyLineBreakpoint.getFilePath().equals(fileName))
{
if (rubyLineBreakpoint.getLineNumber() == (lineNumber + 1))
{
// remove
breakpoint.delete(); // TODO Disable, don't remove?
return;
}
}
}
// create line breakpoint (doc line numbers start at 0)
RubyDebugModel.createLineBreakpoint(resource, fileName, StringUtil.EMPTY, ++lineNumber, true, null);
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection)
{
return getFileStore(part) != null;
}
/**
* Returns an IFileStore pointing at the contents of the editor, only if the file appears to have a ruby, ambiguous
* ruby, or HTML/ERB content type.
*
* @param part
* @return
*/
public IFileStore getFileStore(IWorkbenchPart part)
{
if (!(part instanceof ITextEditor))
return null;
try
{
ITextEditor editorPart = (ITextEditor) part;
IEditorInput editorInput = editorPart.getEditorInput();
IFileStore store = null;
if (editorInput instanceof IURIEditorInput)
{
IURIEditorInput uriInput = (IURIEditorInput) editorInput;
store = EFS.getStore(uriInput.getURI());
}
else if (editorInput instanceof IStorageEditorInput)
{
IStorageEditorInput storageInput = (IStorageEditorInput) editorInput;
IPath path = storageInput.getStorage().getFullPath();
if (path != null)
{
File file = path.toFile();
if (!file.exists())
{
// path might be relative to workspace root
IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
IPath location = iFile.getLocation();
if (location == null)
{
return null;
}
file = location.toFile();
}
store = EFS.getStore(file.toURI());
}
}
if (store == null)
{
return null;
}
for (String contentType : getValidContentTypes())
{
if (isAssociatedWith(store.getName(), contentType))
{
return store;
}
}
}
catch (CoreException e)
{
IdeLog.logError(RubyDebugUIPlugin.getDefault(), e);
}
return null;
}
protected Set<String> getValidContentTypes()
{
Set<String> set = new HashSet<String>();
set.add(IRubyConstants.CONTENT_TYPE_RUBY);
set.add(IRubyConstants.CONTENT_TYPE_RUBY_AMBIGUOUS);
set.add(IERBConstants.CONTENT_TYPE_HTML_ERB);
return set;
}
private boolean isAssociatedWith(String fileName, String contentTypeId)
{
IContentType targetType = Platform.getContentTypeManager().getContentType(contentTypeId);
return targetType.isAssociatedWith(fileName);
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException
{
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection)
{
return false;
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException
{
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection)
{
return false;
}
}