The other night I saw a tweet by Neal Culiner (@NCSoftware) regarding a plugin he’d like to see developed.
Shortly there was a response was a tweet by Matthew MacSuga (@csharpbydesign). He mentioned that he’s asked for something like this a while back.
What they’re after, is a way to preview the code of a method, without having to visit that method.
I feel a little guilty because I remember Matthew mentioning this a while back. I think I started a debate at the time on "what should trigger the functionality” and we (well probably I) got bogged down in the details. Sorry Matthew :(
This time I just thought .. “Sod This” - (Wasting time that is, not talking to Matthew and Neal) - “Let’s just get something out there, and we’ll see where it leads afterward”.
So after a quick vote on the name of said plugin (Where Neal suggested the name and we all agreed :D) I was off to build a new plugin.
Where to start?
So I created a basic plugin and dropped an action in place. (For details please see a previous post)
From here I needed 2 things:
- A function to determine which method to preview.
- A function to actually do the preview.
There are some complexities in the original brief that I didn’t feel comfortable with initially.
- “Select method based on method call under cursor”.
- I have elected to use caret position in this first version.
- “Hold a key down to see Preview”
- I have elected to use a toggleable action in this first version.
- I have elected to use a toggleable action in this first version.
Which Method?
So the first thing to do is to work out which method to display a preview for.
Some Terminology:
Given the sample…
Public Sub Method1()
Call Method2()
End Sub
- “Method2” is known as the MethodReferenceExpression
- “Call Method2()” is the MethodCall.
I would like this plugin to function from either of these 2 locations, so I need to return the declaration of the method to which either refers.
-------------------------------------------------------------
Private Function GetMethod(ByVal Element As LanguageElement) As Method
Dim Method As Method = Nothing
Select Case Element.ElementType
Case LanguageElementType.MethodCall
Method = TryCast(Element, MethodCall).GetDeclaration
Case LanguageElementType.MethodReferenceExpression
Method = TryCast(Element, MethodReferenceExpression).GetDeclaration
End Select
Return Method
End Function
-------------------------------------------------------------
To this method, I can pass CodeRush.Source.GetNodeAt(CodeRush.Caret.SourcePoint)
Later I can replace this with something which passes the element under the cursor, and I won’t have to change much at all.
Next we need to determine the code behind the Method in question.
-------------------------------------------------------------
Dim TheCode as String = CodeRush.CodeMod.GenerateCode(Method)
-------------------------------------------------------------
And now we have the code we’d like to render in our preview window. So lets crack on and create the preview itself.
The Preview Window
Building a preview window is easy… (Isn’t everything with the DXCore? :P)
The following function accepts the code and a location for the preview and builds the preview accordingly. It also places the preview on screen.
(The code to hide the preview has been omitted here but is even simpler.)
-------------------------------------------------------------
Private mPreviewWindow As CodePreviewWindow
Private Sub ShowCodePreview(ByVal Code As String, ByVal insertionPoint As SourcePoint)
mPreviewWindow = New CodePreviewWindow(CodeRush.Documents.ActiveTextView, insertionPoint)
mPreviewWindow.AddCode(Code)
mPreviewWindow.ShowPreview()
End Sub
-------------------------------------------------------------
And so things come together in the main ToggleMethodPreview_Execute() as…
-------------------------------------------------------------
Private mShowingPreview As Boolean = False
Private Sub ToggleMethodPreview_Execute(ByVal ea As DevExpress.CodeRush.Core.ExecuteEventArgs) Handles ToggleMethodPreview.Execute
If mShowingPreview Then
Call HideCodePreview()
Else
Dim Method As Method = GetMethod(CodeRush.Source.GetNodeAt(CodeRush.Caret.SourcePoint))
If Not Method Is Nothing Then
Call ShowMethodPreview(Method, CodeRush.Caret.SourcePoint)
mShowingPreview = True
End If
End If
End Sub
-------------------------------------------------------------
Summary
That’s pretty much all there is to it.
To use this plugin, simply bind a key to the “ToggleMethodPreview” action and activate it when your caret is in a suitable location.
For this plugin I wrote all of 42 lines of code including signatures.
Proof once again, as if you needed it, that the DXCore makes plugin writing ridiculously easy.
So now we have a first draft of “CR_MethodPreview”… go play… see what you think… And we’ll see where it goes from there.
-------------------------------------------------------------
For more DevExpress news, check out their Facebook page
-------------------------------------------------------------
5 comments:
There might be a possibility here for a plugin, no?
http://stackoverflow.com/questions/1273085/attribute-to-add-to-an-interface-for-the-default-concrete-class
Indeed. :) I have asked for a little more info and made an offer :)
you da man!
Visual Studio has the "Code Definition Window" for this for in C#. I've be wanting the same thing for VB. And this plug-in does it. Thanks!
You're quite welcome. :)
Post a Comment