Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 11 files changed
  • 0 commit comments
  • 1 contributor
View
2  docs/releasenotes/net.sf.eclipsefp.haskell_2.3.2.txt
@@ -25,6 +25,8 @@ Features:
- Install all dependencies for one project from right click on project (performs a clean of the project afterwards).
- BuildWrapper and scion-browser should build with GHC 7.6
- If you run a GHCi session in debug mode and launch a function with :trace, :hist output will show as a stack trace in the Debug perspective
+ - Watch action on editor adds the selected text as a debug expression
+ - Inspect action on editor evaluates the expression in current GHCi session (only visible if stopped at a breakpoint in debug GHCi session)
Internal:
- Hopefully performance of some UI operations has been enhanced and the UI should be more responsive in places
View
22 net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BWFacade.java
@@ -1076,17 +1076,23 @@ private void setDerived(){
IFolder fldr=project.getFolder(DIST_FOLDER);
if (fldr.exists()){
if (!fldr.isDerived()){
- try {
- fldr.setDerived(true,new NullProgressMonitor());
- } catch (CoreException ce){
- // log error and leave flag to false, let's hope it'll be better at next run
- BuildWrapperPlugin.logError(BWText.error_derived, ce);
+ if (!project.getWorkspace().isTreeLocked()){
+ try {
+ fldr.setDerived(true,new NullProgressMonitor());
+ needSetDerivedOnDistDir=false; // ok
+ } catch (CoreException ce){
+ // log error and leave flag to false, let's hope it'll be better at next run
+ BuildWrapperPlugin.logError(BWText.error_derived, ce);
+ needSetDerivedOnDistDir=false; // let's not cause errors again
+ }
+ } else {
+ needSetDerivedOnDistDir=true; // tree is locked, le's try again when it's not
}
+ } else {
+ needSetDerivedOnDistDir=false; // folder is already marked
}
- needSetDerivedOnDistDir=false;
-
} else {
- needSetDerivedOnDistDir=true;
+ needSetDerivedOnDistDir=true; // folder doesn't exist, let's try again when it does
}
}
}
View
41 ...ipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/debug/HaskellDebugTarget.java
@@ -1,3 +1,8 @@
+/**
+ * Copyright (c) 2012 by JP Moresmau
+ * This code is made available under the terms of the Eclipse Public License,
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
+ */
package net.sf.eclipsefp.haskell.debug.core.internal.debug;
import java.io.BufferedReader;
@@ -44,6 +49,19 @@
*
*/
public class HaskellDebugTarget extends HaskellDebugElement implements IDebugTarget,IStreamListener {
+ /**
+ * lock
+ */
+ private static Object instanceLock=new Object();
+ /**
+ * number of target currently suspended at a breakpoint
+ */
+ private static int instances=0;
+ /**
+ * system property to write globally if we can handle inspect
+ */
+ private static final String SYSTEM_PROPERTY="haskell.debug"; //$NON-NLS-1$
+
// associated system process (VM)
private final IProcess fProcess;
@@ -64,6 +82,22 @@
private final HaskellThread thread=new HaskellThread( this );
+ /**
+ * manages the number of instances
+ * @param delta the number to move the count by
+ */
+ private static void instances(final int delta){
+ synchronized( instanceLock ) {
+ instances+=delta;
+ if(instances>0){
+ System.setProperty( SYSTEM_PROPERTY, "true" ); //$NON-NLS-1$
+ } else {
+ instances=0;
+ System.clearProperty( SYSTEM_PROPERTY );
+ }
+ }
+ }
+
public HaskellDebugTarget(final ILaunch launch, final IProcess process){
setTarget( this );
this.fLaunch=launch;
@@ -71,6 +105,7 @@ public HaskellDebugTarget(final ILaunch launch, final IProcess process){
this.fProcess.getStreamsProxy().getOutputStreamMonitor().addListener( this );
DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
+ instances(1);
}
@Override
@@ -191,6 +226,7 @@ private synchronized void waitForPrompt(){
@Override
public void terminate() throws DebugException {
if (isSuspended()){
+ instances(-1);
thread.setBreakpoint( null );
thread.setStopLocation( null );
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent( thread, DebugEvent.RESUME )});
@@ -224,7 +260,7 @@ public void resume() throws DebugException {
thread.setStopLocation( null );
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent( thread, DebugEvent.RESUME )});
sendRequest( GHCiSyntax.CONTINUE_COMMAND, false );
-
+ instances(-1);
}
@Override
@@ -327,6 +363,7 @@ public void dispose(){
connected=false;
disposed=true;
DebugPlugin.getDefault().getBreakpointManager().removeBreakpointListener( this );
+
}
@Override
@@ -422,7 +459,7 @@ public void run() {
}
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent( thread, DebugEvent.SUSPEND,hb!=null?DebugEvent.BREAKPOINT:DebugEvent.UNSPECIFIED )});
-
+ instances(1);
} else {
m=GHCiSyntax.BREAKPOINT_NOT.matcher( response.toString() );
View
45 ...lipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/debug/HaskellExpression.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2012 by JP Moresmau
+ * This code is made available under the terms of the Eclipse Public License,
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
+ */
+package net.sf.eclipsefp.haskell.debug.core.internal.debug;
+
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.core.model.IValue;
+
+
+/**
+ * Wrapping a value and an expression text
+ * @author JP Moresmau
+ *
+ */
+public class HaskellExpression extends HaskellDebugElement implements IExpression{
+ private final String expression;
+ private final HaskellValue value;
+
+ public HaskellExpression( final HaskellDebugTarget target,final String expression,final HaskellValue value ) {
+ super( target );
+ this.expression=expression;
+ this.value=value;
+ }
+
+ @Override
+ public String getExpressionText() {
+ return expression;
+ }
+
+ @Override
+ public IValue getValue() {
+ return value;
+ }
+
+ @Override
+ public void dispose() {
+ // NOOP
+
+ }
+
+
+
+}
View
BIN  net.sf.eclipsefp.haskell.ui/icons/etool16/insp_exp.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  net.sf.eclipsefp.haskell.ui/icons/etool16/watch_exp.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
5 net.sf.eclipsefp.haskell.ui/plugin.properties
@@ -120,6 +120,11 @@ openDefinitionCommand_name = &Open Declaration
openDefinitionCommand_desc = Opens an editor on the declaration of the selected element
# NOTE: open declaration is referred to as open definition in the code
+watchExpressionCommand_name=Watch
+watchExpressionCommand_desc=Add the selected code to the watched expressions
+inspectExpressionCommand_name=Inspect
+inspectExpressionCommand_desc=See the current value of the expression
+
searchHoogleAction_label = Search in &Hoogle
searchHoogleAction_tooltip = Search for the select element in Hoogle
searchHoogleCommand_name = Search in &Hoogle
View
78 net.sf.eclipsefp.haskell.ui/plugin.xml
@@ -476,6 +476,16 @@
name="%references_project_label"
id="net.sf.eclipsefp.ui.commands.references.project"/>
<command
+ description="%watchExpressionCommand_desc"
+ categoryId="org.eclipse.debug.ui.category.run"
+ name="%watchExpressionCommand_name"
+ id="net.sf.eclipsefp.ui.commands.run.watchExpression"/>
+ <command
+ description="%inspectExpressionCommand_desc"
+ categoryId="org.eclipse.debug.ui.category.run"
+ name="%inspectExpressionCommand_name"
+ id="net.sf.eclipsefp.ui.commands.run.inspectExpression"/>
+ <command
description="%HaddockDocumentFollowing.description"
categoryId="net.sf.eclipsefp.haskell.ui.category.source"
name="%HaddockDocumentFollowing.name"
@@ -511,6 +521,22 @@
</command>
</menuContribution>
<menuContribution
+ locationURI="menu:org.eclipse.ui.run?after=emptyBreakpointGroup">
+ <command
+ commandId="net.sf.eclipsefp.ui.commands.run.watchExpression"
+ icon="icons/etool16/watch_exp.gif">
+ <visibleWhen checkEnabled="true"/>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="menu:org.eclipse.ui.run?after=emptyBreakpointGroup">
+ <command
+ commandId="net.sf.eclipsefp.ui.commands.run.inspectExpression"
+ icon="icons/etool16/insp_exp.gif">
+ <visibleWhen checkEnabled="true"/>
+ </command>
+ </menuContribution>
+ <menuContribution
locationURI="menu:navigate?after=open.ext">
<command
commandId="net.sf.eclipsefp.ui.commands.navigate.searchHoogle">
@@ -524,6 +550,22 @@
<visibleWhen checkEnabled="true"/>
</command>
</menuContribution>
+ <menuContribution
+ locationURI="popup:#HaskellEditorContext?after=additions">
+ <command
+ commandId="net.sf.eclipsefp.ui.commands.run.watchExpression"
+ icon="icons/etool16/watch_exp.gif">
+ <visibleWhen checkEnabled="true"/>
+ </command>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:#HaskellEditorContext?after=additions">
+ <command
+ commandId="net.sf.eclipsefp.ui.commands.run.inspectExpression"
+ icon="icons/etool16/insp_exp.gif">
+ <visibleWhen checkEnabled="true"/>
+ </command>
+ </menuContribution>
<menuContribution
locationURI="popup:#HaskellEditorContext?after=group.open">
<command
@@ -657,6 +699,7 @@
</reference>
</activeWhen>
</handler>
+ <!-- handler for the references in project action when invoked from the HaskellEditor -->
<handler
class="net.sf.eclipsefp.haskell.ui.handlers.ReferencesProjectHandler"
commandId="net.sf.eclipsefp.ui.commands.references.project">
@@ -666,6 +709,41 @@
</reference>
</activeWhen>
</handler>
+ <!-- handler for the Watch expression action when invoked from the HaskellEditor -->
+ <handler
+ class="net.sf.eclipsefp.haskell.ui.handlers.WatchExpressionHandler"
+ commandId="net.sf.eclipsefp.ui.commands.run.watchExpression">
+ <activeWhen>
+ <and>
+ <reference
+ definitionId="net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellEditor.active">
+ </reference>
+ <with variable="selection">
+ <iterate operator="or">
+ <instanceof value="org.eclipse.jface.text.ITextSelection"/>
+ </iterate>
+ </with>
+ </and>
+ </activeWhen>
+ </handler>
+ <!-- handler for the Inspect expression action when invoked from the HaskellEditor -->
+ <handler
+ class="net.sf.eclipsefp.haskell.ui.handlers.InspectExpressionHandler"
+ commandId="net.sf.eclipsefp.ui.commands.run.inspectExpression">
+ <activeWhen>
+ <and>
+ <reference
+ definitionId="net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellEditor.active">
+ </reference>
+ <with variable="selection">
+ <iterate operator="or">
+ <instanceof value="org.eclipse.jface.text.ITextSelection"/>
+ </iterate>
+ </with>
+ <systemTest property="haskell.debug" value="true"/>
+ </and>
+ </activeWhen>
+ </handler>
</extension>
<extension
point="org.eclipse.core.expressions.definitions">
View
80 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/handlers/InspectExpressionHandler.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2012 by JP Moresmau
+ * This code is made available under the terms of the Eclipse Public License,
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
+ */
+package net.sf.eclipsefp.haskell.ui.handlers;
+
+import net.sf.eclipsefp.haskell.debug.core.internal.debug.HaskellDebugElement;
+import net.sf.eclipsefp.haskell.debug.core.internal.debug.HaskellExpression;
+import net.sf.eclipsefp.haskell.debug.core.internal.debug.HaskellValue;
+import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
+import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellEditor;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.ISuspendResume;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.InspectPopupDialog;
+import org.eclipse.swt.graphics.Point;
+
+
+/**
+ * Inspect the current value of the selected expression
+ * @author JP Moresmau
+ *
+ */
+public class InspectExpressionHandler extends WatchExpressionHandler {
+
+ /* (non-Javadoc)
+ * @see net.sf.eclipsefp.haskell.ui.handlers.WatchExpressionHandler#addExpression(java.lang.String)
+ */
+ @Override
+ protected void addExpression(final HaskellEditor hEditor, final String s ) {
+ IAdaptable context = DebugUITools.getDebugContext();
+ if (context instanceof HaskellDebugElement){
+ final HaskellDebugElement hde=(HaskellDebugElement)context;
+ if ((hde instanceof ISuspendResume && ((ISuspendResume)hde).isSuspended()) || hde.getDebugTarget().isSuspended()){
+ try {
+ final HaskellValue val=hde.getDebugTarget().evaluate( s );
+ hEditor.getEditorSite().getShell().getDisplay().asyncExec( new Runnable(){
+ @Override
+ public void run() {
+ Point p=hEditor.getSelectedPoint();
+ //new InspectDialog(hEditor,s,res).open();
+ new InspectPopupDialog( hEditor.getEditorSite().getShell(), new Point( p.x, p.y+20 ), null, new HaskellExpression( hde.getDebugTarget(), s, val ) ).open();
+ }
+ });
+
+ } catch (DebugException de){
+ HaskellUIPlugin.log( de );
+ }
+
+ }
+ }
+
+ }
+
+// private static class InspectDialog extends PopupDialog{
+// private final String val;
+// /**
+// *
+// */
+// public InspectDialog(final HaskellEditor hEditor,final String exp,final String val) {
+// super(hEditor.getEditorSite().getShell(),PopupDialog.INFOPOPUPRESIZE_SHELLSTYLE,false,false,false,false,false,exp,"");
+// this.val=val;
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jface.dialogs.PopupDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+// */
+// @Override
+// protected Control createDialogArea( final Composite parent ) {
+// Composite composite=(Composite)super.createDialogArea( parent );
+// Label l=new Label(composite,SWT.NONE);
+// l.setLayoutData( new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL) );
+// l.setText( val );
+// composite.layout( true );
+// return composite;
+// }
+// }
+}
View
85 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/handlers/WatchExpressionHandler.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2012 by JP Moresmau
+ * This code is made available under the terms of the Eclipse Public License,
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
+ */
+package net.sf.eclipsefp.haskell.ui.handlers;
+
+import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellEditor;
+import net.sf.eclipsefp.haskell.ui.util.text.WordFinder;
+import net.sf.eclipsefp.haskell.ui.util.text.WordFinder.EditorThing;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IWatchExpression;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+
+/**
+ * Handler for watch expression
+ * @author JP Moresmau
+ *
+ */
+public class WatchExpressionHandler extends AbstractHandler {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+ */
+ @Override
+ public Object execute( final ExecutionEvent event ) {
+ IEditorPart editor = HandlerUtil.getActiveEditor( event );
+
+ if( !( editor instanceof HaskellEditor ) ) {
+ return null;
+ }
+ final HaskellEditor hEditor=(HaskellEditor)editor;
+
+ // cast is safe because we have a guard in plugin.xml
+ final ITextSelection sel=(ITextSelection)HandlerUtil.getActiveMenuSelection( event );
+
+ String s=sel.getText();
+ // find word at location
+ if (s.length()==0){
+ WordFinder.getEditorThing( hEditor,new WordFinder.EditorThingHandler() {
+
+ @Override
+ public void handle( final EditorThing thing ) {
+ if (thing!=null && thing.getThing()!=null){
+ String name = thing.getThing().getName();
+ addExpression(hEditor, name );
+ } else {
+ String s=WordFinder.findWord( hEditor.getDocument(), sel.getOffset() );
+ if (s.length()>0){
+ addExpression(hEditor, s );
+ }
+ }
+ }
+ });
+ } else {
+ addExpression(hEditor, s );
+ }
+
+ return null;
+ }
+
+ protected void addExpression(final HaskellEditor hEditor,final String s){
+ if (s.length()>0){
+ IWatchExpression expression= DebugPlugin.getDefault().getExpressionManager().newWatchExpression(s);
+ DebugPlugin.getDefault().getExpressionManager().addExpression(expression);
+ IAdaptable object = DebugUITools.getDebugContext();
+ IDebugElement context= null;
+ if (object instanceof IDebugElement) {
+ context= (IDebugElement) object;
+ } else if (object instanceof ILaunch) {
+ context= ((ILaunch) object).getDebugTarget();
+ }
+ expression.setExpressionContext(context);
+ }
+ }
+}
View
13 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellEditor.java
@@ -71,6 +71,7 @@
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
@@ -203,7 +204,10 @@ public HaskellEditor() {
// getSourceViewer().revealRange( offset, length );
// }
+
+
public IDocument getDocument() {
+
IDocumentProvider docProvider = getDocumentProvider();
if (docProvider!=null){
return docProvider.getDocument( getEditorInput() );
@@ -288,6 +292,15 @@ public void editorContextMenuAboutToShow( final IMenuManager menu ) {
}
}
+ /**
+ * get the location in display coordinates of the current selection
+ * @return
+ */
+ public Point getSelectedPoint(){
+ Point p2=getSourceViewer().getTextWidget().getLocationAtOffset( getSourceViewer().getTextWidget().getSelectionRange().x );
+ return getSourceViewer().getTextWidget().toDisplay(p2 );
+ }
+
@Override
protected void createActions() {
super.createActions();

No commit comments for this range

Something went wrong with that request. Please try again.