Search code examples
c#visual-studiovisual-studio-2012vsix

Access other files in VS Language Service (Visual Studio Extensibility)


I'm writing custom language service as described in https://msdn.microsoft.com/en-us/library/bb166533.aspx

Now I'm writing code for AuthoringScope (https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.package.authoringscope.aspx) My problem is in GetDeclarations method.

I have access to text of current file via ParseRequest.Text property. It allows me to list all methods and variables in my file but how can I access other files content? I need to get access to other file content for building AST tree of this file but I don't know how can I do this.


Solution

  • Personally I find the MPF "helper" classes (like AuthoringScope) to be a bit restrictive, and implement everything manually (which, I admit, does take more time, but is a lot more flexible in the end).

    In any case, it sounds like your language (like most!) has dependencies between files at the semantic parsing level. This means you'll either have to:

    a) reparse a lot of text all the time, which is likely too slow in large projects
    or b) maintain a global aggregate parse of a project's files, and update it dynamically when the files (or the project's properties) change

    b) is obviously a lot harder, but is almost certainly the best way to do it. A general outline would be to discover all projects after a solution is opened via EnvDTE, parse them all (discover all files in each project, again via EnvDTE), and store everything in some sort of indexable data structure so that you can do fast queries against it (for semantic syntax highlighting, go to definition, etc.). Then you need to listen for changes everywhere and reparse appropriately -- you'll need to check for solution open/close (IVsSolutionEvents), projects being added/removed/renamed/unloaded/loaded (IVsSolutionEvents/IVsSolutionEvents4), files being added/removed/renamed (IVsHierarchyEvents), files being edited (IVsTextViewCreationListener + ITextBuffer.Changed), and project configurations changing (IVsUpdateSolutionEvents, IVsHierarchyEvents).

    Whether you choose a) or b), you still need to be able to check if a file is opened in the editor (potentially with unsaved changes) or not. You can check if a file is already open in the Running Document Table (but don't forget to normalize the path first using Path.GetFullPath()) via the IVsRunningDocumentTable service, which will return an IntPtr to the document data, which can be coaxed into yielding an ITextBuffer for the file, which contains the text (and entire buffer history!) of the file. Of course, if it's not open you'll have to read it from disk.