views:

194

answers:

3

Is it possible to do a macro that copies a definition of a function to a declaration(, and maybe also the opposite)? For instance

Foo::Foo(int aParameter, int bParameter){
    //
}

int Foo::someMethod(char aCharacter) const {
    return 0;  
}

from the .cpp file would be:

class Foo {
    Foo(int aParameter, int bParameter);

    int someMethod(char aCharacter) const;
};

in the .cpp file.

Also:

if there are anyone with knowledge of good tutorials or documentation that aims at Visual Studio .Net (and maybe also covers the above problem) I would probably accept that as an answer as well

+1  A: 

No, this is next-to-impossible to get 100% reliable. You have to write a C++ language parser to be able to accurately lift the class name out of the declaration and deal with complexities like default argument values and missing argument names. Writing a C++ parser is hard in any language but you'll especially find VBA lacking.

Check out Visual Assist. Their website is down right now (uh-oh), can't give you an accurate link.

Hans Passant
I don't think it's impossible.. just very time consuming.. I think that what I would need to do is manipulate the tabs (open documents or active project) in Visual studio, the active document, reading one line at a time (or maybe selected text?), string parsing, add text to a document at a specific location.. and there we go. Any pointers on any of those topics?
Default
+1 though, I found http://www.sharewareconnection.com/visual-assist-x.htm with the description: *Define Autotext/Code Templates ahead of time and accept them just as easily.*. But I would like to give it a try in macro
Default
Resharper (http://www.jetbrains.com/resharper/) also has this functionality. Although, I guess both Visual Assist X and Resharper has the language parsers...
Default
see Create Implementation in Visual Assist - http://www.wholetomato.com/products/features/createImplementation.asp
sean e
A: 

It's not beautiful or fast, but it does work.
Used the record macro function and browsed the object browser to get the calls and then patched it together.
My visual basic knowledge is limited, so any feedback to the code would be very helpful. For instance, I get a huge slowdown when trying to locate the class <name> { row. Any tips to speed this up?

Imports EnvDTE

Public Module Module1
    Function getFileName(ByRef str As String) As String
        If (str = "main.cpp") Then
            Return ""
        Else
            Dim pos As Integer
            pos = InStr(str, ".cpp")
            If (pos = 0) Then
                ' not a .cpp file.'
                Return ""
            Else
                Dim header As String
                header = Left(str, pos - 1)
                Return header
            End If
        End If
        Return ""
    End Function

    Function getParts(ByRef str As String, ByRef returnvalue As String, ByRef classname As String, ByRef identifier As String, ByRef arguments As String) As String
        ' common function looks like:'
        '   <return_value> <classname>::<identifier>([arguments])[{]'
        '                 ^divider    ^colonposition            ^parenthesisEnd'
        '                  ^classnamepos            ^parenthesisStart'
        ''
        ' exceptions: ctor and dtor'
        '   <classname>::[~]<classname>([arguments])[{]'

        Dim colonposition As Integer
        Dim classnameposition As Integer
        Dim divider As Integer
        Dim divider2 As Integer
        Dim parenthesisStart As Integer
        Dim parenthesisEnd As Integer

        colonposition = InStr(str, "::")
        parenthesisStart = InStr(str, "(")
        parenthesisEnd = InStr(str, ")")
        If (colonposition = 0 Or parenthesisStart = 0 Or parenthesisEnd = 0) Then
            Return "Not a function line" ' no colons or parenthesis found? maybe not a function line'
        End If

        divider = InStr(str, " ")

        ' do we have a ctor/dtor?'
        If (divider > colonposition Or divider = 0) Then

            Return "constructor or destructor"
        End If
        ' this might be a function'
        While True
            divider2 = InStr(divider + 1, str, " ")
            If (divider2 > colonposition) Then
                Exit While
            End If
            divider = divider2
        End While
        ' now we have the full return value in 0 -> divider-1'
        returnvalue = Left(str, divider - 1)
        ' and the classname as well'
        classname = Left(Right(str, str.Length - divider), colonposition - divider - 1)
        'indentifier is right after the :: and before the parenthesis'
        identifier = Left(Right(str, str.Length - colonposition - 1), parenthesisStart - colonposition - 2)
        ' and not to mention the arguments between the parenthesis'
        arguments = Left(Right(str, str.Length - parenthesisStart), parenthesisEnd - parenthesisStart - 1)


        Return "Success"
    End Function

    Sub getDefinition()
        Dim sourcefile As String
        Dim filename As String
        Dim header As String
        Dim returnvalue As String
        Dim classname As String
        Dim identifier As String
        Dim arguments As String

        Dim str As String
        Dim line As String
        Dim pos As Integer


        sourcefile = DTE.ActiveDocument.Name
        ' get the filename for the current file (without the extension)'
        filename = getFileName(sourcefile)
        If (filename.Length = 0) Then
            MsgBox("Im not in a .cpp file", , "GetDefinition")
            Return
        End If

        ' get the current line'
        DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
        DTE.ActiveDocument.Selection.EndOfLine(True)
        line = DTE.ActiveDocument.Selection.Text()
        ' now interpret the line'
        str = getParts(line, returnvalue, classname, identifier, arguments)
        If (Not str = "Success") Then
            MsgBox(str, , "GetDefinition")
            Exit Sub
        End If
        ' the str should be put into the header file as of:'
        ' class <classname>[:<base>][{]'
        ' [{]'
        '     <--- somewhere here'
        ' }'

        ' attach the header ending'
        header = filename + ".h"
        ' activate the header file'
        DTE.Windows.Item(header).Activate()
        DTE.ActiveDocument.Selection.StartOfDocument()


        While (True)
            DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
            DTE.ActiveDocument.Selection.EndOfLine(True)
            line = DTE.ActiveDocument.Selection.Text()
            pos = InStr(line, classname)
            If (Not pos = 0) Then
                Exit While
            End If
            DTE.ActiveDocument.Selection.LineDown(False, 1)
        End While
        ' found the class definition'
        While (True)
            pos = InStr(line, "{")
            If (Not pos = 0) Then
                Exit While
            End If
            DTE.ActiveDocument.Selection.LineDown(False, 1)
        End While
        DTE.ActiveDocument.Selection.EndOfLine(False)
        DTE.ActiveDocument.Selection.NewLine()

        DTE.ActiveDocument.Selection.Text = returnvalue & " " & identifier & "(" & arguments & ");"


    End Sub
End Module
Default
A: 

So, I found the Automation and Extensibility for Visual Studio, which covers the stuff I am trying to do, with a little help from the object browser and record macro function.

I guess I should be able to solve it from here.

Default