Ejemplo n.º 1
0
        internal FileItem(CommentTaskProvider provider, string fileName)
        {
            // Note: The caller should check FileUtility.IsValidPath(fileName) before invoking this constructor.
            this.provider                   = provider;
            this.FileName                   = fileName;
            this.hierarchyItems             = EmptySet;
            this.lastModifiedTimeScannedUtc = MinDateTimeUtc;

            try
            {
                this.fileInfo = new FileInfo(fileName);
                this.scanInfo = ScanInfo.Get(this);
            }
            catch (Exception ex)
            {
                // We might not have access to the file, or the fileName parameter might contain a non-file name.
                // The latter condition should be very rare now since the caller is using FileUtility.IsValidPath.
                // An invalid file name should only get through to here if it's valid per Windows standard naming
                // rules but invalid on the target file system (e.g., if it's on a Unix system or on a CD).
                if (!IsAccessException(ex) && !(ex is NotSupportedException || ex is ArgumentException))
                {
                    throw;
                }

                // Make sure this FileItem is unscannable so nothing will try to use its null this.fileInfo member.
                this.scanInfo = ScanInfo.Unscannable;
            }
        }
Ejemplo n.º 2
0
 internal CommentTask(CommentTaskProvider provider, TaskPriority priority, string project, string fileName, int line, string comment)
 {
     this.provider = provider;
     this.Priority = priority;
     this.Project  = project;
     this.FilePath = fileName;
     this.Line     = line;
     this.Comment  = comment;
 }
        public FileItemManager(CommentTaskProvider provider, FileMonitor monitor, Options options)
        {
            this.provider = provider;
            this.monitor  = monitor;

            this.options          = options;
            this.options.Applied += this.Options_Applied;
            this.RefreshExcludePatterns();
        }
Ejemplo n.º 4
0
        private void TasksControl_Loaded(object sender, RoutedEventArgs e)
        {
            // The Loaded event will be raised again whenever the tool window tab is changed,
            // so we must make sure this event handler isn't called again.
            this.Loaded -= this.TasksControl_Loaded;

            if (this.isLoading)
            {
                MainPackage package = this.Package;
                if (package == null)
                {
                    throw new InvalidOperationException("The tasks control can't be loaded without its associated package.");
                }

                Options options = package.Options;
                if (options == null)
                {
                    throw new InvalidOperationException("The tasks control can't be loaded without its associated options.");
                }

                CommentTaskProvider provider = package.TaskProvider;
                if (provider != null)
                {
                    provider.TasksChanged += this.TaskProvider_TasksChanged;
                }

                this.initiallyEnabled = options.EnableCommentScans;
                this.UpdateWarning(options);

                options.Applied += (s, a) =>
                {
                    if (this.IsLoaded)
                    {
                        this.UpdateWarning((Options)s);
                    }
                };

                this.resetSort.IsEnabled = false;
                string statusXml = options.TasksStatusXml;
                if (!string.IsNullOrEmpty(statusXml))
                {
                    SortDescriptionCollection sorting = this.tasks.Items.SortDescriptions;
                    XElement status = XElement.Parse(statusXml);
                    foreach (XElement sortBy in status.Elements("SortBy"))
                    {
                        SortDescription sort = new SortDescription(
                            sortBy.GetAttributeValue("PropertyName"),
                            sortBy.GetAttributeValue("Direction", ListSortDirection.Ascending));
                        sorting.Add(sort);
                    }
                }

                this.isLoading = false;
            }
        }
        public DocumentMonitor(CommentTaskProvider provider)
        {
            this.provider = provider;

            this.docTable             = new RunningDocumentTable(this.provider.ServiceProvider);
            this.docTable4            = (IVsRunningDocumentTable4)this.provider.ServiceProvider.GetService(typeof(SVsRunningDocumentTable));
            this.docTableAdviseCookie = this.docTable.Advise(this);

            // Creating these components without going through MEF is documented in MSDN under
            // "Using Visual Studio Editor Services in a Non-MEF Component" in the article "Adapting
            // Legacy Code to the New Editor" https://msdn.microsoft.com/en-us/library/dd885359.aspx.
            this.componentModel  = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel));
            this.adapterFactory  = this.componentModel.GetService <IVsEditorAdaptersFactoryService>();
            this.documentFactory = this.componentModel.GetService <ITextDocumentFactoryService>();

            this.documentFactory.TextDocumentCreated  += this.DocumentFactory_TextDocumentCreated;
            this.documentFactory.TextDocumentDisposed += this.DocumentFactory_TextDocumentDisposed;
        }
        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;
                }
            }
        }
        public SolutionMonitor(CommentTaskProvider provider)
        {
            this.provider = provider;
            this.solution = (IVsSolution2)this.provider.ServiceProvider.GetService(typeof(SVsSolution));
            uint cookie;
            int  hr = this.solution.AdviseSolutionEvents(this, out cookie);

            ErrorHandler.ThrowOnFailure(hr);
            this.solutionEventsCookie = cookie;

            // Note: I tried using IVsHierarchyItemCollectionProvider (via componentModel.GetService<IVsHierarchyItemCollectionProvider>()),
            // but it had problems.  It only worked for the first solution opened, and it caused the nodes to display in a different order in
            // the VS Solution Explorer!  Using IVsTrackProjectDocumentsEvents2 works better.
            this.projectTracker = (IVsTrackProjectDocuments2)this.provider.ServiceProvider.GetService(typeof(SVsTrackProjectDocuments));
            hr = this.projectTracker.AdviseTrackProjectDocumentsEvents(this, out cookie);
            ErrorHandler.ThrowOnFailure(hr);
            this.projectEventsCookie = cookie;

            this.RequireScan();
        }
        public IReadOnlyDictionary <string, DocumentItem> GetChangedDocuments()
        {
            Dictionary <string, DocumentItem> result = CommentTaskProvider.CloneAndClear(this.changedDocuments);

            return(result);
        }
        public IReadOnlyDictionary <CommentTask, bool> GetChangedTasks()
        {
            Dictionary <CommentTask, bool> result = CommentTaskProvider.CloneAndClear(this.changedTasks);

            return(result);
        }
 private void RequireScan(bool required = true, [CallerMemberName] string caller = null)
 {
     this.isScanRequired = required;
     CommentTaskProvider.Debug("SolutionMonitor.{0} {1} scan.", caller, required ? "enabled" : "disabled");
 }
 public FileMonitor(CommentTaskProvider provider)
 {
     this.provider          = provider;
     this.fileChangeService = (IVsFileChangeEx)this.provider.ServiceProvider.GetService(typeof(SVsFileChangeEx));
 }
Ejemplo n.º 12
0
        public bool Refresh(RefreshAction action, out IDictionary <CommentTask, bool> itemChanges)
        {
            bool isScannable = action != RefreshAction.Remove && this.scanInfo.IsScannable;

            if (isScannable)
            {
                this.fileInfo.Refresh();
                isScannable = this.fileInfo.Exists;
            }

            bool result = false;

            itemChanges = null;

            if (!isScannable)
            {
                if (this.tasks != null)
                {
                    itemChanges = this.tasks.ToDictionary(t => t, t => false);
                    this.tasks  = null;
                }

                // Reset to min time so if the file shows up again we'll re-scan it.
                this.lastModifiedTimeScannedUtc = MinDateTimeUtc;
                result = true;
            }
            else
            {
                bool forceRefresh = action == RefreshAction.Always || !this.AreTaskProjectsCurrent;

                // Make sure that the file has been modified since we last scanned it.
                // Note: lastModifiedUtc can go backward to before lastModifiedTimeScannedUtc
                // due to Undo, so we have to check != instead of just >.
                DateTime lastModifiedUtc = this.Document != null && this.Document.HasTextDocument
                                        ? this.Document.LastModifiedUtc.Value : this.fileInfo.LastWriteTimeUtc;
                if (forceRefresh || lastModifiedUtc != this.lastModifiedTimeScannedUtc)
                {
                    // Make sure that it's been at least N seconds since the file was last modified.
                    // If someone is making a long sequence of continual edits, then there's no point
                    // in wasting scanning overhead while they're actively changing the file.
                    DateTime latestAllowedTimeUtc = DateTime.UtcNow - this.provider.ScanDelay;
                    if (forceRefresh || latestAllowedTimeUtc >= lastModifiedUtc)
                    {
                        itemChanges = this.Refresh();
                        result      = true;
                        this.lastModifiedTimeScannedUtc = lastModifiedUtc;
                    }
                }
                else
                {
                    // We should only get into this branch of the Refresh method if we got a new file, a document change event,
                    // or a file change event.  It's possible to get a "document change" event when a document within the solution
                    // is first opened even though we've already scanned it (from the solution reference).  When that happens the
                    // lastModifiedUtc should equal the lastModifiedTimeScannedUtc, so we'll just return true since the file scan
                    // results should already be up-to-date.
                    result = lastModifiedUtc == this.lastModifiedTimeScannedUtc;
                    Debug.Assert(result, "The file's modified time should have changed or been the same as the last modified scanned time.");
                }
            }

            CommentTaskProvider.Debug("FileItem.Refresh: {0}, Result={1}  ItemChanges={2}", this.FileName, result, itemChanges != null);
            return(result);
        }