visual-studio-extensionsvsixvspackagempf

How can I obtain the list of files in a project from VSIX(/MPF) code?


I am building a VSIX package to support a custom language in Visual Studio using MPF. I am in a custom designer and I need to find the files referenced in the project to resolve some dependencies. Where can I access this list?


Solution

  • I assume, that you´re using MPF to implement the project system for your custom language service. When doing so, you probably have a project root node which is derived from either ProjectNode or HierarchyNode...

    If so, you could share the root node´s instance with the designer and try to find files by traversing the hierarchy, for instance...

    internal class HierarchyVisitor
    {
        private readonly Func<HierarchyNode, bool> filterCallback;
    
        public HierarchyVisitor(
            Func<HierarchyNode, bool> filter)
        {
            this.filterCallback = filter;
        }
    
        public IEnumerable<HierarchyNode> Visit(
            HierarchyNode node)
        {
            var stack = new Stack<HierarchyNode>();
            stack.Push(node);
            while (stack.Any())
            {
                HierarchyNode next = stack.Pop();
                if (this.filterCallback(next))
                {
                    yield return next;
                }
    
                for (
                    HierarchyNode child = next.FirstChild; 
                    child != null; 
                    child = child.NextSibling)
                {
                    stack.Push(child);
                }
            }
        }
    }
    

    To get a list of all nodes in the hierarchy, you could just do...

    ProjectNode root = ...
    var visitor = new HierarchyVisitor(x => true);
    IEnumerable<HierarchyNode> flatList = visitor.Visit(root);
    

    Or to filter for a certain file type, you could try something like this...

    ProjectNode root = ...
    var visitor = new HierarchyVisitor((HierarchyNode x) => 
        {
            const string XmlFileExtension = ".xml";
            string path = new Uri(x.Url, UriKind.Absolut).LocalPath;
            return string.Compare(
                XmlFileExtension, 
                Path.GetFileExtension(path), 
                StringComparison.InvariantCultureIgnoreCase) == 0;
        });
    
    IEnumerable<HierarchyNode> xmlFiles = visitor.Visit(root);