locked
CodeElements goes to C++ implementations rather than header file RRS feed

  • Question

  • Hello, first and foremost, here are my specs:

    • Add-in for: Visual Studio 2008
    • Target Source evaluations: Managed and Native C++
    • Goals: Evaluate header files and comments in Doxygen format

    Secondly, I am aware of other Add-ins such as "AtomineerUtils" (which is an excellent Add-in), but it has become partially an self-education to learn as well for I looked at this for few days, so I'd still like to inquire if possible.  One thing I have suspicions of is that most of these Add-Ins that alters the C++ header files actually does its own parsing of the header files rather than walk through the EnvDTE.CodeElements...  (I'd imagine this is a better way to go because if the file(s) are not part of the VCProj, using CodeElements would not work.)

    In a nutshell, when the IntelliSense is deleted (.NCB file) and building itself, it won't be able to find the implementations of the function (vsCMElement.vsCMElementFunction) on time so rather than the .CPP file, it will correctly set towards the header file.

    Otherwise, when inspecting CodeElement (of the CodeElements) would point towards the CPP implementations rather than the header file where the function is declared.  Thus when inserting the Doxygen comment (at CodeElement.StartPoint.CreateEditPoint()), it will end up inserting in CPP file rather than header file.

    I'd imagine the initial question would be, what is the correct way (if other than to walk through and find each CodeElement in CodeElements) in Visual Studio 2008 to determine the element type vsCMElementFunction and set the StartPoint for editing, assuming the implementation is on the CPP side and declaration is in header file side and the file exists in the VCProj project file?

    I thank you for your time and responses in advance.

    Sincerely,

    Hideki A. Ikeda


    There are 3 things inevitable in life: death, tax, and software bugs
    Monday, August 2, 2010 10:11 PM

Answers

  • Hello, Ninja

    As what I have mentioned, we could use VCCodeFunction.DocComment property add comment to the function method. After adding the comment, we could use EditPoint to remove the comment in the CPP file. See the following code based on my previous code.

                if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)

                {

                    if (commandName == "AddInVCCodeModel.Connect.AddInVCCodeModel")

                    {

                        VCCodeModel vcCodeModel = (VCCodeModel)_applicationObject.Solution.Projects.Item(1).CodeModel;

                        //Find class CBox.

                        VCCodeElement cBoxElement = (VCCodeElement)vcCodeModel.CodeElements.Item("CBox");

                        //Find volume function.

                        VCCodeElement funcElement = cBoxElement.Children.Item("volume") as VCCodeElement;

                        VCCodeFunction vcCodeFunc = (VCCodeFunction)funcElement;

                        //Add comment to the header file.

                        //vcCodeFunc.DocComment = "A comment for function volume";

                        vcCodeFunc.Comment = "A comment for function volume";

     

                        EditPoint ep = vcCodeFunc.StartPoint.CreateEditPoint();

                        while (true)

                        {

                            ep.LineUp(1);

                            //Check whether the line is a comment

                            if (ep.GetText(ep.LineLength).Trim().StartsWith("//"))

                            {

                                ep.Delete(ep.LineLength);

                                //Delete the new line

                                ep.Delete(1);

                            }

                            else

                                break;

                        }

                        handled = true;

                        return;

                    }

                }

    Note my code have some shortcommings, the while loop will exit once it doesn’t find a line that start with //.

    PS: And I guess this is the only method that could satisfy your needs, as I have researched we could not add comment to the header file if we don’t use VCCodeFunction.Comment or DocComment property.

    If you have anything unclear, feel free to let me know.

    Thanks

    Chao


    Please unmark it if it does not help, and mark it if it helps.
    Monday, August 9, 2010 3:51 AM

All replies

  • Hi, Hideki

    We could add comment to header file directly using VCCodeModel. Here is a good sample in MSDN http://msdn.microsoft.com/en-us/library/ms228770.aspx.

    And I have written a sample for you about this.

    I use a C++ class named CBox for example

            public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)

            {

                handled = false;

                if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)

                {

                    if(commandName == "AddInVCCodeModel.Connect.AddInVCCodeModel")

                    {

                        VCCodeModel vcCodeModel = (VCCodeModel)_applicationObject.Solution.Projects.Item(1).CodeModel;

                        //Find class CBox.

                        VCCodeElement cBoxElement = (VCCodeElement)vcCodeModel.CodeElements.Item("CBox");

                        //Find volume function.

                        VCCodeElement funcElement = cBoxElement.Children.Item("volume") as VCCodeElement;

                        VCCodeFunction vcCodeFunc = (VCCodeFunction)funcElement;

                        //Add comment to the header file.

                        vcCodeFunc.DocComment = "A comment for function volume";

                        handled = true;

                        return;

                    }

                }

            }

    This is the class CBox.

    The header file Box.h.

    #pragma once

     

    class CBox

    {

    public:

        CBox(int length, int width, int height);

        ~CBox(void);

        /// Doc comment

        int volume();

        bool operator>(const int volume);

    private:

        int length;

        int width;

        int height;

    };

    The source file CBox.cpp.

    #include "StdAfx.h"

    #include "Box.h"

     

    CBox::CBox(int length, int width, int height)

    {

        this->height = height;

        this->length = length>width?length:length;

        this->width = length>width?width:length;

    }

     

    CBox::~CBox(void)

    {

    }

    /// Doc comment

    int CBox::volume()

    {

        return this->height * this->length * this->width;

    }

     

    bool CBox::operator >(const int volume)

    {

        return this->volume()>volume;

    }

    If you have anything unclear, feel free to let me know.

    Thanks

    Chao


    Please unmark it if it does not help, and mark it if it helps.
    Wednesday, August 4, 2010 7:40 AM
  • [Edit] I had to mark as Unanswered because this method is only working because it's using VCCodeFunction.DocComment Property (similar to CodeElement.Document property) which is what's doing the trick to insert to the header file.  If you look at the example, you will also notice that CBox::volume() function in the implementation (cpp file) is getting commented as well.  Whether I use VCCodeModel or FileCodeModel2, if I used this approach, I too can comment on both CPP and header file.  I do not think this is the solution/answer although it does get me one step closer to my goals (it now comments to the header file because rather than using EditPoint by using either Comment or DocComment, it will insert/alter/update the comment at the header point).

    Thanks, marked as Answer because it sort of did what I was looking for (I've added your test code to mine and it did as expected).  

    Although when I walk through with FileCodeModel2 and dynamically casted CodeElements as VCCodeElements, it still went towards the CPP implementations rather than header file, it probably is something I'm doing/did wrong...  I should probably not use ActiveDocument.ProjectItem and start using your example method instead so that I can access it via VCCodeModel.

    Thank you very much for your response and help.

    Sincerely,

    Hideki A. Ikeda


    There are 3 things inevitable in life: death, tax, and software bugs
    Thursday, August 5, 2010 12:16 AM
  • Hello, Again

    One thing we should aware is that FileCodeModel and CodeModel are for C#, VB.net, It is not proper to use them in VC++ project, and we have to use VCCodeModel to parse VC++ code element, VCCodeModel is designed specific to VC++ language.

    Adding the comment to both header and source file; is it the right behavior you want?

    For the VCCodeModel is designed to add the comment to both header and source file, if you want to add comment to header file only, please use VCCodeFunction.StartPoint Property to create the editPoint, then to remove the comment, this will take effect on the source file only.

    Thanks

    Chao


    Please unmark it if it does not help, and mark it if it helps.
    Friday, August 6, 2010 3:27 AM
  • Thanks, I'll make sure to use VCCodeModel (which I am in most areas where I can).  Although I may be going off on the tangent from the question raised on this topic, if I cannot use FileCodeModel2, what are the alternatives to call FileCodeModel2.Synchronize() to sync the IntelliSense (I'm guessing it is to sync IntelliSense, many/most of the the documentation are so vague)?  Without the call to Synchronize(), I sometimes get an exception (throws) when extracting a StartPoint so that I can have my EditPoint.

    [Edit] I just realized VCCodeModel.Synchronize() member function exist (derived from CodeModel2), so that answers its question...

    As for your inquiry, I only want the comments on the header as mentioned as my "Goals", and if I used your sample code and used VCCodeFunction.StartPoint (to create my EditoPoint), it will only comment on the cpp side (which takes me back to why I posted this question).

    So replace the line where it's assigning to DocComment Property with the following:

     

    TextPoint	textPoint = null;
    try
    {
     textPoint = vcCodeFunc.StartPoint;	// this may throw an exception if it cannot find it as VCCodeElement (you need to Synchronize() first)
    }
    catch (Exception ex)
    {
     System.Windows.Forms.MessageBox.Show("Exception: " + ex.Message);
    }
    if (textPoint != null)
    {
     EditPoint epStart = textPoint.CreateEditPoint();
     epStart.StartOfLine();
     String myComment = "// This is my comment\n";
     epStart.Insert(myComment);
    }
    

     

    The above code will insert to CPP implementation side, not to the header file side...

    Sincerely,

    Hideki A. Ikeda


    There are 3 things inevitable in life: death, tax, and software bugs
    Friday, August 6, 2010 4:55 PM
  • Hello, Ninja

    As what I have mentioned, we could use VCCodeFunction.DocComment property add comment to the function method. After adding the comment, we could use EditPoint to remove the comment in the CPP file. See the following code based on my previous code.

                if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)

                {

                    if (commandName == "AddInVCCodeModel.Connect.AddInVCCodeModel")

                    {

                        VCCodeModel vcCodeModel = (VCCodeModel)_applicationObject.Solution.Projects.Item(1).CodeModel;

                        //Find class CBox.

                        VCCodeElement cBoxElement = (VCCodeElement)vcCodeModel.CodeElements.Item("CBox");

                        //Find volume function.

                        VCCodeElement funcElement = cBoxElement.Children.Item("volume") as VCCodeElement;

                        VCCodeFunction vcCodeFunc = (VCCodeFunction)funcElement;

                        //Add comment to the header file.

                        //vcCodeFunc.DocComment = "A comment for function volume";

                        vcCodeFunc.Comment = "A comment for function volume";

     

                        EditPoint ep = vcCodeFunc.StartPoint.CreateEditPoint();

                        while (true)

                        {

                            ep.LineUp(1);

                            //Check whether the line is a comment

                            if (ep.GetText(ep.LineLength).Trim().StartsWith("//"))

                            {

                                ep.Delete(ep.LineLength);

                                //Delete the new line

                                ep.Delete(1);

                            }

                            else

                                break;

                        }

                        handled = true;

                        return;

                    }

                }

    Note my code have some shortcommings, the while loop will exit once it doesn’t find a line that start with //.

    PS: And I guess this is the only method that could satisfy your needs, as I have researched we could not add comment to the header file if we don’t use VCCodeFunction.Comment or DocComment property.

    If you have anything unclear, feel free to let me know.

    Thanks

    Chao


    Please unmark it if it does not help, and mark it if it helps.
    Monday, August 9, 2010 3:51 AM
  • Chao,

    Thanks, I'll mark this as an answer since you've mentioned that "...if we don't use VCCodeFunction.Comment...", which means to me that there are no alternatives to get this right (or at least the way I'd imagined the right way would have been).

    I'm also guessing the side effects of the answered code method would have issues with inline code which the implementations resides inside the header class declarations.  But that is solvable, I just wanted to know if I was guessing on how CodeModel and CodeElement worked because it wasn't working the way I would have expected.

    Once again, thank you very much for all the time and effort you've invested on this issues.  I am quite pleased and very satisfied with your support and responses.

    Sincerely,

    Hideki A. Ikeda


    There are 3 things inevitable in life: death, tax, and software bugs
    Monday, August 9, 2010 3:42 PM