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); }
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); } }
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; }
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); }
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); }
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(); } }
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); }
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); } }
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; } } }
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); }
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); }
internal void AddTextView(ITextView textView) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } _foregroundDispatcher.AssertForegroundThread(); if (!_textViews.Contains(textView)) { _textViews.Add(textView); } }
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(); } }
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(); } } }
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); }
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); } }
private void OnContextChanged(ProjectSnapshot project, ContextChangeKind kind) { _foregroundDispatcher.AssertForegroundThread(); _project = project; var handler = ContextChanged; if (handler != null) { handler(this, new ContextChangeEventArgs(kind)); } }
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); }
public sealed override bool TryGetDocument(DocumentKey key, out EditorDocument document) { _foregroundDispatcher.AssertForegroundThread(); lock (_lock) { return(_documents.TryGetValue(key, out document)); } }