private void AddChangedDocument(string filePath, DocumentItem document)
        {
            // Ignore file paths that are invalid (e.g., RDT_PROJ_MK::{42D00E44-28B8-4CAA-950E-909D5273945D}),
            // relative, or too long.  We only care about documents that have valid full paths.
            if (FileUtility.IsValidPath(filePath, ValidPathOptions.None))
            {
                CommentTaskProvider.Debug(
                    "AddChangedDocument: {0}.  HasDoc: {1}  HasTextDoc: {2}",
                    filePath,
                    document != null,
                    document != null && document.HasTextDocument);

                lock (this.changedDocuments)
                {
                    this.changedDocuments[filePath] = document;
                }
            }
        }
        private void HandleDocumentLockChange(uint docCookie, bool locked)
        {
            // We don't want to call this.docTable.GetDocumentInfo because it forces the document to fully-initialize.
            // It's more efficient to use IVsRunningDocumentTable4 to just get the flags first.
            // http://blogs.msdn.com/b/visualstudio/archive/2013/10/14/asynchronous-solution-load-performance-improvements-in-visual-studio-2013.aspx
            // Note: When debugging this, it's easiest to add a Watch = this.docTable4.GetDocumentMoniker(docCookie)
            uint rawFlags = this.docTable4.GetDocumentFlags(docCookie);
            var  flags1   = (_VSRDTFLAGS)rawFlags;
            var  flags4   = (_VSRDTFLAGS4)rawFlags;

            if (flags4.HasFlag(_VSRDTFLAGS4.RDT_PendingInitialization) &&
                !flags1.HasFlag(_VSRDTFLAGS.RDT_ProjSlnDocument) &&
                !flags1.HasFlag(_VSRDTFLAGS.RDT_VirtualDocument))
            {
                string moniker = this.docTable4.GetDocumentMoniker(docCookie);
                if (!string.IsNullOrEmpty(moniker))
                {
                    DocumentItem document = locked ? new DocumentItem(null) : null;
                    this.AddChangedDocument(moniker, document);
                }
            }
        }
        public void UpdateDocuments(IReadOnlyDictionary <string, DocumentItem> changedDocuments)
        {
            List <FileItem> removeItems = new List <FileItem>();

            foreach (var pair in changedDocuments)
            {
                string       fileName = pair.Key;
                DocumentItem document = pair.Value;

                if (this.files.TryGetValue(fileName, out FileItem file))
                {
                    file.Document = document;
                    if (document != null)
                    {
                        lock (this.changedItems)
                        {
                            this.changedItems.Add(file);
                        }
                    }
                    else if (!file.HasHierarchyReference)
                    {
                        removeItems.Add(file);
                    }
                }
                else if (document != null)
                {
                    file = this.TryAdd(fileName);
                    if (file != null)
                    {
                        file.Document = document;
                    }
                }
            }

            this.Remove(removeItems);
        }
        private void TextBuffer_PostChanged(object sender, EventArgs e)
        {
            ITextDocument document = DocumentItem.GetTextDocument(sender as ITextBuffer);

            this.AddChangedDocument(document);
        }