FileCodeModel in the new editor API

Verrouillé FileCodeModel in the new editor API

  • jeudi 9 février 2012 14:33
     
     

    Hi all,

    I have been trying to get similar information to what it is shown in the drop-down bar about the current context position of the user. Lets say the caret is in method A() of class B {} of namespace C.D {} I want to get that information. We couldnt find how to access that information directly.

    We tried using the CodeElementFromPoint method of the FileCodeModel (http://msdn.microsoft.com/en-us/library/envdte.filecodemodel.codeelementfrompoint.aspx) but the ComException thrown when you dont select the proper group to find is very annoying and makes debugging hell (you dont know which are real ComException' and which ones are thrown by that method).

    We tried to reimplement that code using a binary search over the CodeElement but for big files it is still too slow for our purposes (average of 152ms for a 1400 lines file). Is there any way to do that with the new editor API? How about accessing the compiler AST or an intermediate representation of it? 

    Any hint would be useful.

    Regards, 
    Federico

Toutes les réponses

  • mardi 14 février 2012 06:52
    Modérateur
     
     

    Hi Federico,
    Thank you for your question.

    I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay. Appreciate your patience.

    Thank you for your understanding and support.


    Best regards,
    Lucy


    Lucy Liu [MSFT]
    MSDN Community Support | Feedback to us

  • mardi 6 mars 2012 23:28
    Modérateur
     
     Réponse proposée

    Hi Federico,

    Currently, no. we don't expose they underlying AST or other internals. The impementation varies by language. There is some ongoing work destined for a future release that may make this easier for VB.Net and C#. Specifically, the Roslyn project, which is currently in CTP form. This won't ship with the next version of VS (version 11), but most likely in a future version.

    Right now, all we've got is the FileCodeModel. Not sure if getting at the dropdown bar would buy you anything here, as one of the developers I spoke with indicated performance characteristics should be similar, given that the info is ultimately coming from the same place.

    I ran into a lot of issues trying to retreive and access the info in the dropdown bar. It's not really designed for that, and you'd have to reimplement the IVsDropdownBarClient interface, as it's interop signature for GetEntryText doesn't align with the .IDL definition. Consequently, you'll wind up corrupting the heap :-(.

    Specifically, the following will crash under the debugger, because the last param to GetEntryText isn't a string (or a BSTR) but a WCHAR**. You'd essentially have to redefine and marshal that last param yourself.

            private void OnCmdBarButtonClick(CommandBarButton Ctrl, ref bool CancelDefault)
            {
                IVsMonitorSelection vsMonSel = (IVsMonitorSelection)Package.GetGlobalService(typeof(SVsShellMonitorSelection));
                object objFrame;
                int hr = vsMonSel.GetCurrentElementValue((uint)Microsoft.VisualStudio.VSConstants.VSSELELEMID.SEID_DocumentFrame, out objFrame);
                IVsWindowFrame activeDocFrame = (IVsWindowFrame)objFrame;
                IntPtr ppv = IntPtr.Zero;
                Guid guidCodeWindow = typeof(IVsCodeWindow).GUID;
                hr = activeDocFrame.QueryViewInterface(ref guidCodeWindow, out ppv);

                if (ppv != IntPtr.Zero)
                {
                    object objCodeWindow = Marshal.GetObjectForIUnknown(ppv);
                    IVsCodeWindow vsCodeWindow = objCodeWindow as IVsCodeWindow;
                    if (vsCodeWindow != null)
                    {
                        IVsDropdownBarManager ddBarMgr = vsCodeWindow as IVsDropdownBarManager;
                        if (ddBarMgr == null)
                            return;

                        IVsDropdownBar ddBar;
                        IVsDropdownBarClient ddBarClient;
                        hr = ddBarMgr.GetDropdownBar(out ddBar);
                        hr = ddBar.GetClient(out ddBarClient);

                        // HERE THERE BE DRAGONS, GetEntryText in textmgr.idl defines the last param as WCHAR** NOT BSTR, so, this will
                        // cause a corruption in memory. :-(
                        string curObject, curMember;
                        hr = ddBarClient.GetEntryText(0, 0, out curObject);
                        hr = ddBarClient.GetEntryText(1, 0, out curMember);

                        //FrameworkElement elem = ddBar as FrameworkElement;
                    }
                }
            }

    Sincerely,


    Ed Dore