1
1
// DebugValueTooltipProvider.cs
4
// Lluis Sanchez Gual <lluis@novell.com>
3
// Authors: Lluis Sanchez Gual <lluis@novell.com>
4
// Jeffrey Stedfast <jeff@xamarin.com>
6
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
7
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
8
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
10
// of this software and associated documentation files (the "Software"), to deal
29
30
using System.Collections.Generic;
30
32
using Mono.TextEditor;
31
using MonoDevelop.Ide.Gui;
33
using MonoDevelop.Components;
32
34
using Mono.Debugging.Client;
33
35
using TextEditor = Mono.TextEditor.TextEditor;
34
using MonoDevelop.Ide.CodeCompletion;
35
36
using MonoDevelop.Debugger;
37
38
using ICSharpCode.NRefactory.TypeSystem;
40
41
namespace MonoDevelop.SourceEditor
42
public class DebugValueTooltipProvider: ITooltipProvider, IDisposable
43
public class DebugValueTooltipProvider: TooltipProvider, IDisposable
44
45
Dictionary<string,ObjectValue> cachedValues = new Dictionary<string,ObjectValue> ();
46
DebugValueWindow tooltip;
46
public DebugValueTooltipProvider()
48
DebuggingService.CurrentFrameChanged += HandleCurrentFrameChanged;
51
void HandleCurrentFrameChanged (object sender, EventArgs e)
48
public DebugValueTooltipProvider ()
50
DebuggingService.CurrentFrameChanged += CurrentFrameChanged;
51
DebuggingService.DebugSessionStarted += DebugSessionStarted;
54
void DebugSessionStarted (object sender, EventArgs e)
56
DebuggingService.DebuggerSession.TargetExited += TargetProcessExited;
59
void CurrentFrameChanged (object sender, EventArgs e)
53
61
// Clear the cached values every time the current frame changes
54
62
cachedValues.Clear ();
57
#region ITooltipProvider implementation
68
void TargetProcessExited (object sender, EventArgs e)
74
#region ITooltipProvider implementation
76
static int IndexOfLastWhiteSpace (string text)
78
int index = text.Length - 1;
81
if (char.IsWhiteSpace (text[index]))
59
public TooltipItem GetItem (Mono.TextEditor.TextEditor editor, int offset)
89
public override TooltipItem GetItem (TextEditor editor, int offset)
61
91
if (offset >= editor.Document.TextLength)
77
107
startOffset = ed.SelectionRange.Offset;
78
108
length = ed.SelectionRange.Length;
80
ICSharpCode.NRefactory.TypeSystem.DomRegion expressionRegion;
110
DomRegion expressionRegion;
81
111
ResolveResult res = ed.GetLanguageItem (offset, out expressionRegion);
83
113
if (res == null || res.IsError || res.GetType () == typeof (ResolveResult))
88
118
if (expressionRegion.IsEmpty)
91
121
if (res is NamespaceResolveResult ||
92
122
res is ConversionResolveResult ||
93
123
res is ForEachResolveResult ||
94
124
res is TypeIsResolveResult ||
95
125
res is TypeOfResolveResult ||
96
res is TypeResolveResult ||
97
126
res is ErrorResolveResult)
107
136
if (res is LocalResolveResult) {
108
137
var lr = (LocalResolveResult) res;
110
// Capture only the local variable portion of the expression...
111
expression = lr.Variable.Name;
139
// Use the start and end offsets of the variable region so that we get the "@" in variable names like "@class"
140
start = new DocumentLocation (lr.Variable.Region.BeginLine, lr.Variable.Region.BeginColumn);
141
end = new DocumentLocation (lr.Variable.Region.EndLine, lr.Variable.Region.EndColumn);
142
startOffset = editor.Document.LocationToOffset (start);
143
endOffset = editor.Document.LocationToOffset (end);
145
expression = ed.GetTextBetween (startOffset, endOffset).Trim ();
147
// Note: When the LocalResolveResult is a parameter, the Variable.Region includes the type
148
if (lr.IsParameter) {
149
int index = IndexOfLastWhiteSpace (expression);
151
expression = expression.Substring (index + 1);
112
154
length = expression.Length;
114
// Calculate start offset based on the end offset because we don't want to include the type information.
115
startOffset = endOffset - length;
116
155
} else if (res is InvocationResolveResult) {
117
156
var ir = (InvocationResolveResult) res;
167
211
if (!cachedValues.TryGetValue (expression, out val)) {
168
val = frame.GetExpressionValue (expression, false);
212
val = frame.GetExpressionValue (expression, true);
169
213
cachedValues [expression] = val;
196
240
return char.IsLetterOrDigit (c) || c == '_';
199
public Gtk.Window CreateTooltipWindow (Mono.TextEditor.TextEditor editor, int offset, Gdk.ModifierType modifierState, TooltipItem item)
201
return new DebugValueWindow (editor, offset, DebuggingService.CurrentFrame, (ObjectValue) item.Item, null);
204
public void GetRequiredPosition (Mono.TextEditor.TextEditor editor, Gtk.Window tipWindow, out int requiredWidth, out double xalign)
207
requiredWidth = tipWindow.SizeRequest ().Width;
210
public bool IsInteractive (Mono.TextEditor.TextEditor editor, Gtk.Window tipWindow)
243
public override Gtk.Window ShowTooltipWindow (TextEditor editor, int offset, Gdk.ModifierType modifierState, int mouseX, int mouseY, TooltipItem item)
245
var location = editor.OffsetToLocation (item.ItemSegment.Offset);
246
var point = editor.LocationToPoint (location);
247
int lineHeight = (int) editor.LineHeight;
250
// find the top of the line that the mouse is hovering over
251
while (y + lineHeight < mouseY)
254
var caret = new Gdk.Rectangle (mouseX, y, 1, lineHeight);
255
tooltip = new DebugValueWindow (editor, offset, DebuggingService.CurrentFrame, (ObjectValue) item.Item, null);
256
tooltip.ShowPopup (editor, caret, PopupPosition.TopLeft);
261
public override bool IsInteractive (TextEditor editor, Gtk.Window tipWindow)
263
return DebuggingService.IsDebugging;
217
268
#region IDisposable implementation
218
269
public void Dispose ()
220
DebuggingService.CurrentFrameChanged -= HandleCurrentFrameChanged;
271
DebuggingService.CurrentFrameChanged -= CurrentFrameChanged;
272
DebuggingService.DebugSessionStarted -= DebugSessionStarted;