Пример #1
0
        public override bool TryResolvePotentialProject(string documentFilePath, out ProjectSnapshot projectSnapshot)
        {
            if (documentFilePath == null)
            {
                throw new ArgumentNullException(nameof(documentFilePath));
            }

            _foregroundDispatcher.AssertForegroundThread();

            var normalizedDocumentPath = _filePathNormalizer.Normalize(documentFilePath);
            var projects = _projectSnapshotManagerAccessor.Instance.Projects;

            for (var i = 0; i < projects.Count; i++)
            {
                if (projects[i].FilePath == _miscellaneousHostProject.FilePath)
                {
                    // We don't resolve documents to belonging to the miscellaneous project.
                    continue;
                }

                var projectDirectory = _filePathNormalizer.GetDirectory(projects[i].FilePath);
                if (normalizedDocumentPath.StartsWith(projectDirectory, FilePathComparison.Instance))
                {
                    projectSnapshot = projects[i];
                    return(true);
                }
            }

            projectSnapshot = null;
            return(false);
        }
Пример #2
0
        public void SubjectBuffersConnected(IWpfTextView textView, ConnectionReason reason, Collection <ITextBuffer> subjectBuffers)
        {
            if (textView == null)
            {
                throw new ArgumentException(nameof(textView));
            }

            if (subjectBuffers == null)
            {
                throw new ArgumentNullException(nameof(subjectBuffers));
            }

            _foregroundDispatcher.AssertForegroundThread();

            for (var i = 0; i < subjectBuffers.Count; i++)
            {
                var textBuffer = subjectBuffers[i];
                if (!textBuffer.IsRazorBuffer())
                {
                    continue;
                }

                if (!_editorFactoryService.TryGetDocumentTracker(textBuffer, out var documentTracker) ||
                    !(documentTracker is DefaultVisualStudioDocumentTracker tracker))
                {
                    Debug.Fail("Tracker should always be available given our expectations of the VS workflow.");
                    return;
                }

                tracker.AddTextView(textView);
            }
        }
Пример #3
0
        public override void ProjectUpdated(ProjectSnapshotUpdateContext update)
        {
            if (update == null)
            {
                throw new ArgumentNullException(nameof(update));
            }

            _foregroundDispatcher.AssertForegroundThread();

            if (_projects.TryGetValue(update.WorkspaceProject.FilePath, out var original))
            {
                if (!original.IsInitialized)
                {
                    // If the project has been uninitialized, just ignore the update.
                    return;
                }

                // This is an update to the project's computed values, so everything should be overwritten
                var snapshot = original.WithComputedUpdate(update);
                _projects[update.WorkspaceProject.FilePath] = snapshot;

                if (snapshot.IsDirty)
                {
                    // It's possible that the snapshot can still be dirty if we got a project update while computing state in
                    // the background. We need to trigger the background work to asynchronously compute the effect of the updates.
                    NotifyBackgroundWorker(snapshot.CreateUpdateContext());
                }

                if (!object.Equals(snapshot.ComputedVersion, original.ComputedVersion))
                {
                    NotifyListeners(new ProjectChangeEventArgs(snapshot, ProjectChangeKind.TagHelpersChanged));
                }
            }
        }
        public void Dispose()
        {
            _foregroundDispatcher.AssertForegroundThread();

            _projectSnapshotManager.Changed -= ProjectSnapshotManager_Changed;
            _disposed = true;
        }
Пример #5
0
        public override VisualStudioDocumentTracker GetTracker(ITextView textView)
        {
            if (textView == null)
            {
                throw new ArgumentNullException(nameof(textView));
            }

            _foregroundDispatcher.AssertForegroundThread();

            // While it's definitely possible to have multiple Razor text buffers attached to the same text view, there's
            // no real scenario for it. This method always returns the tracker for the first Razor text buffer, but the
            // other functionality for this class will maintain state correctly for the other buffers.
            var textBuffer = textView.BufferGraph.GetRazorBuffers().FirstOrDefault();

            if (textBuffer == null)
            {
                // No Razor buffer, nothing to track.
                return(null);
            }

            // A little bit of hardening here, to make sure our assumptions are correct.
            DefaultVisualStudioDocumentTracker tracker;

            if (!textBuffer.Properties.TryGetProperty(typeof(VisualStudioDocumentTracker), out tracker))
            {
                Debug.Fail("The document tracker should be initialized");
            }

            Debug.Assert(tracker.TextViewsInternal.Contains(textView));
            return(tracker);
        }
Пример #6
0
        public override void StartListening()
        {
            _foregroundDispatcher.AssertForegroundThread();

            if (_fileChangeUnadviseTask?.IsCompleted == false)
            {
                // An unadvise operation is still processing, block the foreground thread until it completes.
                _fileChangeUnadviseTask.Join();
            }

            if (_fileChangeAdviseTask != null)
            {
                // Already listening
                return;
            }

            _fileChangeAdviseTask = _joinableTaskFactory.RunAsync(async() =>
            {
                try
                {
                    return(await _fileChangeService.AdviseFileChangeAsync(FilePath, FileChangeFlags, this));
                }
                catch (PathTooLongException)
                {
                    // Don't report PathTooLongExceptions but don't fault either.
                }
                catch (Exception exception)
                {
                    _errorReporter.ReportError(exception);
                }

                return(VSConstants.VSCOOKIE_NIL);
            });
        }
        public void Dispose()
        {
            _dispatcher.AssertForegroundThread();

            _textBuffer.Changed -= TextBuffer_OnChanged;
            _parser.Dispose();
            _idleTimer.Dispose();
        }
        public void Detatch()
        {
            _foregroundDispatcher.AssertForegroundThread();

            DotNetProject.Modified -= DotNetProject_Modified;

            UpdateHostProjectForeground(null);
        }
Пример #9
0
        public override void Subscribe()
        {
            _foregroundDispatcher.AssertForegroundThread();

            UpdateRazorHostProject();

            _project.ProjectCapabilitiesChanged += Project_ProjectCapabilitiesChanged;
            _project.Disposing += Project_Disposing;
        }
        public override void StartListening()
        {
            _foregroundDispatcher.AssertForegroundThread();

            if (_listening)
            {
                return;
            }

            AttachToFileServiceEvents();

            _listening = true;
        }
        // Internal for testing
        internal void Enqueue(DocumentSnapshot document)
        {
            _foregroundDispatcher.AssertForegroundThread();

            lock (_work)
            {
                // We only want to store the last 'seen' version of any given document. That way when we pick one to process
                // it's always the best version to use.
                _work[document.FilePath] = document;

                StartWorker();
            }
        }
        public override void DocumentProcessed(DocumentSnapshot document)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            _foregroundDispatcher.AssertForegroundThread();

            lock (_work)
            {
                _work[document.FilePath] = document;
                StartWorkTimer();
                StartDocumentClosedCheckTimer();
            }
        }
Пример #13
0
        public override bool TryResolveDocument(string documentFilePath, out DocumentSnapshot document)
        {
            _foregroundDispatcher.AssertForegroundThread();

            var normalizedPath = _filePathNormalizer.Normalize(documentFilePath);

            if (!_projectResolver.TryResolvePotentialProject(normalizedPath, out var potentialProject))
            {
                potentialProject = _projectResolver.GetMiscellaneousProject();
            }

            if (!potentialProject.DocumentFilePaths.Contains(normalizedPath, FilePathComparer.Instance))
            {
                var miscProject = _projectResolver.GetMiscellaneousProject();
                if (!miscProject.DocumentFilePaths.Contains(normalizedPath, FilePathComparer.Instance))
                {
                    // Miscellaneous project and other tracked projects do not contain document.
                    document = null;
                    return(false);
                }

                potentialProject = miscProject;
            }

            document = potentialProject.GetDocument(normalizedPath);
            return(true);
        }
Пример #14
0
        public void DocumentRenamed(uint cookie, string fromFilePath, string toFilePath)
        {
            ForegroundDispatcher.AssertForegroundThread();

            // Ignore changes is casing
            if (FilePathComparer.Instance.Equals(fromFilePath, toFilePath))
            {
                return;
            }

            lock (_lock)
            {
                // Treat a rename as a close + reopen.
                //
                // Due to ordering issues, we could see a partial rename. This is why we need to pass the new
                // file path here.
                DocumentClosed(cookie, exceptFilePath: toFilePath);
            }

            // Try to open any existing documents that match the new name.
            if ((_runningDocumentTable.GetDocumentFlags(cookie) & (uint)_VSRDTFLAGS4.RDT_PendingInitialization) == 0)
            {
                DocumentOpened(cookie);
            }
        }
Пример #15
0
        public void DocumentOpened(uint cookie)
        {
            ForegroundDispatcher.AssertForegroundThread();

            lock (_lock)
            {
                // Casts avoid dynamic
                if ((object)_runningDocumentTable.GetDocumentData(cookie) is IVsTextBuffer vsTextBuffer)
                {
                    var filePath = _runningDocumentTable.GetDocumentMoniker(cookie);
                    if (!TryGetMatchingDocuments(filePath, out var documents))
                    {
                        // This isn't a document that we're interesting in.
                        return;
                    }

                    var textBuffer = _editorAdaptersFactory.GetDataBuffer(vsTextBuffer);
                    if (textBuffer == null)
                    {
                        // The text buffer has not been created yet, register to be notified when it is.
                        VsTextBufferDataEventsSink.Subscribe(vsTextBuffer, () => BufferLoaded(vsTextBuffer, filePath));

                        return;
                    }

                    // It's possible that events could be fired out of order and that this is a rename.
                    if (_documentsByCookie.ContainsKey(cookie))
                    {
                        DocumentClosed(cookie, exceptFilePath: filePath);
                    }

                    BufferLoaded(textBuffer, filePath, documents);
                }
            }
        }
        // Internal for testing
        internal void ProjectOperations_EndBuild(object sender, BuildEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            _foregroundDispatcher.AssertForegroundThread();

            if (!args.Success)
            {
                // Build failed
                return;
            }

            var projectItem = args.SolutionItem;

            if (!_projectService.IsSupportedProject(projectItem))
            {
                // We're hooked into all build events, it's possible to get called with an unsupported project item type.
                return;
            }

            var projectPath = _projectService.GetProjectPath(projectItem);

            // Get the corresponding roslyn project by matching the project name and the project path.
            foreach (var projectSnapshot in _projectManager.Projects)
            {
                if (string.Equals(projectPath, projectSnapshot.FilePath, StringComparison.OrdinalIgnoreCase))
                {
                    _projectManager.HostProjectBuildComplete(projectSnapshot.HostProject);
                    break;
                }
            }
        }
Пример #17
0
        public void SubjectBuffersConnected(ITextView textView, ConnectionReason reason, IReadOnlyCollection <ITextBuffer> subjectBuffers)
        {
            if (textView == null)
            {
                throw new ArgumentException(nameof(textView));
            }

            if (subjectBuffers == null)
            {
                throw new ArgumentNullException(nameof(subjectBuffers));
            }

            _foregroundDispatcher.AssertForegroundThread();

            _documentManager.OnTextViewOpened(textView, subjectBuffers);
        }
Пример #18
0
            public int FilesChanged(uint cChanges, string[] rgpszFile, uint[] rggrfChange)
            {
                _foregroundDispatcher.AssertForegroundThread();

                _importDocumentManager.OnFilesChanged(cChanges, rgpszFile, rggrfChange);

                return(VSConstants.S_OK);
            }
        private void OnChanged()
        {
            _foregroundDispatcher.AssertForegroundThread();

            var args = new EditorSettingsChangedEventArgs(Current);

            Changed?.Invoke(this, args);
        }
Пример #20
0
        internal void AddTextView(ITextView textView)
        {
            if (textView == null)
            {
                throw new ArgumentNullException(nameof(textView));
            }

            _foregroundDispatcher.AssertForegroundThread();

            if (!_textViews.Contains(textView))
            {
                _textViews.Add(textView);
            }
        }
Пример #21
0
        public override void Update(EditorSettings updatedSettings)
        {
            if (updatedSettings == null)
            {
                throw new ArgumentNullException(nameof(updatedSettings));
            }

            _foregroundDispatcher.AssertForegroundThread();

            lock (SettingsAccessorLock)
            {
                if (!_settings.Equals(updatedSettings))
                {
                    _settings = updatedSettings;
                    OnChanged();
                }
            }
        }
        // Internal for testing
        internal void OnChanged(object sender, EditorSettingsChangedEventArgs e)
        {
            _foregroundDispatcher.AssertForegroundThread();

            Debug.Assert(_changed != null, nameof(OnChanged) + " should not be invoked when there are no listeners.");

            var args = new EditorSettingsChangedEventArgs(Current);

            _changed?.Invoke(this, args);
        }
        // Internal for testing
        internal void Enqueue(DocumentSnapshot document)
        {
            _foregroundDispatcher.AssertForegroundThread();

            if (!_projectManager.IsDocumentOpen(document.FilePath))
            {
                // We don't parse closed documents
                return;
            }

            lock (_work)
            {
                // We only want to store the last 'seen' version of any given document. That way when we pick one to process
                // it's always the best version to use.
                _work[document.FilePath] = document;

                StartWorker();
            }
        }
Пример #24
0
        public override void OnTextViewOpened(ITextView textView, IEnumerable <ITextBuffer> subjectBuffers)
        {
            if (textView == null)
            {
                throw new ArgumentNullException(nameof(textView));
            }

            if (subjectBuffers == null)
            {
                throw new ArgumentNullException(nameof(subjectBuffers));
            }

            _foregroundDispatcher.AssertForegroundThread();

            foreach (var textBuffer in subjectBuffers)
            {
                if (!textBuffer.IsRazorBuffer())
                {
                    continue;
                }

                if (!IsSupportedProject(textBuffer))
                {
                    return;
                }

                if (!_editorFactoryService.TryGetDocumentTracker(textBuffer, out var documentTracker) ||
                    !(documentTracker is DefaultVisualStudioDocumentTracker tracker))
                {
                    Debug.Fail("Tracker should always be available given our expectations of the VS workflow.");
                    return;
                }

                tracker.AddTextView(textView);

                if (documentTracker.TextViews.Count == 1)
                {
                    tracker.Subscribe();
                }
            }
        }
Пример #25
0
        public void BufferLoaded(ITextBuffer textBuffer, string filePath, EditorDocument[] documents)
        {
            ForegroundDispatcher.AssertForegroundThread();

            lock (_lock)
            {
                for (var i = 0; i < documents.Length; i++)
                {
                    DocumentOpened(filePath, textBuffer);
                }
            }
        }
        public override BraceSmartIndenter Create(VisualStudioDocumentTracker documentTracker)
        {
            if (documentTracker == null)
            {
                throw new ArgumentNullException(nameof(documentTracker));
            }

            _dispatcher.AssertForegroundThread();

            var braceSmartIndenter = new BraceSmartIndenter(_dispatcher, documentTracker, _editorOperationsFactory);

            return(braceSmartIndenter);
        }
Пример #27
0
        public override void StartListening()
        {
            _foregroundDispatcher.AssertForegroundThread();

            try
            {
                if (_fileChangeCookie == VSConstants.VSCOOKIE_NIL)
                {
                    var hr = _fileChangeService.AdviseFileChange(
                        FilePath,
                        FileChangeFlags,
                        this,
                        out _fileChangeCookie);

                    Marshal.ThrowExceptionForHR(hr);
                }
            }
            catch (Exception exception)
            {
                _errorReporter.ReportError(exception);
            }
        }
Пример #28
0
        private void OnContextChanged(ProjectSnapshot project, ContextChangeKind kind)
        {
            _foregroundDispatcher.AssertForegroundThread();

            _project = project;

            var handler = ContextChanged;

            if (handler != null)
            {
                handler(this, new ContextChangeEventArgs(kind));
            }
        }
Пример #29
0
        public override void Publish(string filePath, SourceText sourceText, long hostDocumentVersion)
        {
            if (filePath is null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            if (sourceText is null)
            {
                throw new ArgumentNullException(nameof(sourceText));
            }

            _foregroundDispatcher.AssertForegroundThread();

            if (!_publishedSourceText.TryGetValue(filePath, out var previouslyPublishedText))
            {
                previouslyPublishedText = EmptySourceText;
            }

            IReadOnlyList <TextChange> textChanges = Array.Empty <TextChange>();

            if (!sourceText.ContentEquals(previouslyPublishedText))
            {
                textChanges = sourceText.GetTextChanges(previouslyPublishedText);
            }

            _publishedSourceText[filePath] = sourceText;

            var request = new UpdateCSharpBufferRequest()
            {
                HostDocumentFilePath = filePath,
                Changes             = textChanges,
                HostDocumentVersion = hostDocumentVersion,
            };

            _server.Value.Client.SendRequest("updateCSharpBuffer", request);
        }
Пример #30
0
        public sealed override bool TryGetDocument(DocumentKey key, out EditorDocument document)
        {
            _foregroundDispatcher.AssertForegroundThread();

            lock (_lock)
            {
                return(_documents.TryGetValue(key, out document));
            }
        }