Thursday, August 06, 2009

New CodeRush Plugin: CR_MethodPreview

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.

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)



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()


        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



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



Saif Khan said...

There might be a possibility here for a plugin, no?

Rory said...

Indeed. :) I have asked for a little more info and made an offer :)

Saif Khan said...

you da man!

Mark said...

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!

Rory said...

You're quite welcome. :)