Beispiel #1
0
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            switch (args.Kind)
            {
                case WorkspaceChangeKind.SolutionCleared:
                case WorkspaceChangeKind.SolutionRemoved:
                case WorkspaceChangeKind.SolutionAdded:
                    this.CancelAllParses();
                    break;

                case WorkspaceChangeKind.DocumentRemoved:
                    this.CancelParse(args.DocumentId);
                    break;

                case WorkspaceChangeKind.DocumentChanged:
                    this.ParseIfOpen(args.NewSolution.GetDocument(args.DocumentId));
                    break;

                case WorkspaceChangeKind.ProjectChanged:
                    foreach (var doc in args.NewSolution.GetProject(args.ProjectId).Documents)
                    {
                        this.ParseIfOpen(doc);
                    }

                    break;
            }
        }
            private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
            {
                if (e.Kind == WorkspaceChangeKind.ProjectChanged)
                {
                    var oldProject = e.OldSolution.GetProject(e.ProjectId);
                    var newProject = e.NewSolution.GetProject(e.ProjectId);

                    if (!object.Equals(oldProject.ParseOptions, newProject.ParseOptions))
                    {
                        var workspace = e.NewSolution.Workspace;
                        var documentIds = workspace.GetRelatedDocumentIds(SubjectBuffer.AsTextContainer());

                        if (documentIds.Any(d => d.ProjectId == e.ProjectId))
                        {
                            this.RaiseChanged();
                        }
                    }
                }
            }
Beispiel #3
0
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            switch (args.Kind)
            {
                case WorkspaceChangeKind.SolutionCleared:
                case WorkspaceChangeKind.SolutionAdded:
                case WorkspaceChangeKind.SolutionRemoved:
                    this.CancelBuild(releasePreviousCompilations: true);
                    break;

                case WorkspaceChangeKind.SolutionChanged:
                case WorkspaceChangeKind.ProjectRemoved:
                    this.Rebuild(args.NewSolution);
                    break;

                default:
                    this.Rebuild(args.NewSolution, args.ProjectId);
                    break;
            }
        }
        private void OnWorkspaceChangedLookForAnalyzer(object sender, WorkspaceChangeEventArgs e)
        {
            if (e.Kind == WorkspaceChangeKind.SolutionCleared ||
                e.Kind == WorkspaceChangeKind.SolutionReloaded ||
                e.Kind == WorkspaceChangeKind.SolutionRemoved)
            {
                _workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;
            }
            else if (e.Kind == WorkspaceChangeKind.SolutionAdded)
            {
                _analyzerReference = TryGetAnalyzerReference(e.NewSolution);
                if (_analyzerReference != null)
                {
                    _workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;

                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasItems)));
                }
            }
            else if (e.ProjectId == _projectId)
            {
                if (e.Kind == WorkspaceChangeKind.ProjectRemoved)
                {
                    _workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;
                }
                else if (e.Kind == WorkspaceChangeKind.ProjectAdded ||
                         e.Kind == WorkspaceChangeKind.ProjectChanged)
                {
                    _analyzerReference = TryGetAnalyzerReference(e.NewSolution);
                    if (_analyzerReference != null)
                    {
                        _workspace.WorkspaceChanged -= OnWorkspaceChangedLookForAnalyzer;

                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasItems)));
                    }
                }
            }
        }
Beispiel #5
0
            private void ProcessEvents(WorkspaceChangeEventArgs args, IAsyncToken asyncToken)
            {
                SolutionCrawlerLogger.LogWorkspaceEvent(_logAggregator, (int)args.Kind);

                // TODO: add telemetry that record how much it takes to process an event (max, min, average and etc)
                switch (args.Kind)
                {
                case WorkspaceChangeKind.SolutionAdded:
                case WorkspaceChangeKind.SolutionChanged:
                case WorkspaceChangeKind.SolutionReloaded:
                case WorkspaceChangeKind.SolutionRemoved:
                case WorkspaceChangeKind.SolutionCleared:
                    ProcessSolutionEvent(args, asyncToken);
                    break;

                case WorkspaceChangeKind.ProjectAdded:
                case WorkspaceChangeKind.ProjectChanged:
                case WorkspaceChangeKind.ProjectReloaded:
                case WorkspaceChangeKind.ProjectRemoved:
                    ProcessProjectEvent(args, asyncToken);
                    break;

                case WorkspaceChangeKind.DocumentAdded:
                case WorkspaceChangeKind.DocumentReloaded:
                case WorkspaceChangeKind.DocumentChanged:
                case WorkspaceChangeKind.DocumentRemoved:
                case WorkspaceChangeKind.AdditionalDocumentAdded:
                case WorkspaceChangeKind.AdditionalDocumentRemoved:
                case WorkspaceChangeKind.AdditionalDocumentChanged:
                case WorkspaceChangeKind.AdditionalDocumentReloaded:
                    ProcessDocumentEvent(args, asyncToken);
                    break;

                default:
                    throw ExceptionUtilities.Unreachable;
                }
            }
Beispiel #6
0
            private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
            {
                switch (e.Kind)
                {
                case WorkspaceChangeKind.SolutionAdded:
                case WorkspaceChangeKind.SolutionChanged:
                case WorkspaceChangeKind.SolutionRemoved:
                case WorkspaceChangeKind.SolutionCleared:
                case WorkspaceChangeKind.SolutionReloaded:
                    ClearVersionMap(e.NewSolution.Workspace, e.NewSolution.ProjectIds);
                    break;

                case WorkspaceChangeKind.ProjectAdded:
                case WorkspaceChangeKind.ProjectRemoved:
                case WorkspaceChangeKind.ProjectChanged:
                case WorkspaceChangeKind.ProjectReloaded:
                    ClearVersionMap(e.NewSolution.Workspace, e.ProjectId);
                    break;

                case WorkspaceChangeKind.DocumentRemoved:
                    ClearVersionMap(e.NewSolution.Workspace, e.DocumentId);
                    break;

                case WorkspaceChangeKind.DocumentAdded:
                case WorkspaceChangeKind.DocumentReloaded:
                case WorkspaceChangeKind.DocumentChanged:
                case WorkspaceChangeKind.AdditionalDocumentAdded:
                case WorkspaceChangeKind.AdditionalDocumentRemoved:
                case WorkspaceChangeKind.AdditionalDocumentChanged:
                case WorkspaceChangeKind.AdditionalDocumentReloaded:
                    break;

                default:
                    Contract.Fail("Unknown event");
                    break;
                }
            }
Beispiel #7
0
        public async void OnWorkspaceChangedAsync(object sender, WorkspaceChangeEventArgs args)
        {
            Document oldDocument = (from d in _project.Documents where StringComparers.Paths.Equals(d.FilePath, _oldFilePath) select d).FirstOrDefault();

            if (oldDocument == null)
            {
                return;
            }

            if (args.Kind == WorkspaceChangeKind.DocumentAdded && args.ProjectId == _project.Id)
            {
                Project  project       = (from p in args.NewSolution.Projects where p.Id.Equals(_project.Id) select p).FirstOrDefault();
                Document addedDocument = (from d in project?.Documents where d.Id.Equals(args.DocumentId) select d).FirstOrDefault();

                if (addedDocument != null && StringComparers.Paths.Equals(addedDocument.FilePath, _newFilePath))
                {
                    _docAdded = true;
                }
            }

            if (args.Kind == WorkspaceChangeKind.DocumentRemoved && args.ProjectId == _project.Id && args.DocumentId == oldDocument.Id)
            {
                _docRemoved = true;
            }

            if (args.Kind == WorkspaceChangeKind.DocumentChanged && args.ProjectId == _project.Id)
            {
                _docChanged = true;
            }

            if (_docAdded && _docRemoved && _docChanged)
            {
                _workspace.WorkspaceChanged -= OnWorkspaceChangedAsync;
                Project myNewProject = _workspace.CurrentSolution.Projects.Where(p => StringComparers.Paths.Equals(p.FilePath, _project.FilePath)).FirstOrDefault();
                await RenameAsync(myNewProject);
            }
        }
Beispiel #8
0
            private void ProcessDocumentEvent(WorkspaceChangeEventArgs e, string eventName)
            {
                switch (e.Kind)
                {
                case WorkspaceChangeKind.DocumentAdded:
                    Contract.ThrowIfNull(e.DocumentId);
                    EnqueueEvent(e.NewSolution, e.DocumentId, InvocationReasons.DocumentAdded, eventName);
                    break;

                case WorkspaceChangeKind.DocumentRemoved:
                    Contract.ThrowIfNull(e.DocumentId);
                    EnqueueEvent(e.OldSolution, e.DocumentId, InvocationReasons.DocumentRemoved, eventName);
                    break;

                case WorkspaceChangeKind.DocumentReloaded:
                case WorkspaceChangeKind.DocumentChanged:
                    Contract.ThrowIfNull(e.DocumentId);
                    EnqueueEvent(e.OldSolution, e.NewSolution, e.DocumentId, eventName);
                    break;

                case WorkspaceChangeKind.AdditionalDocumentAdded:
                case WorkspaceChangeKind.AdditionalDocumentRemoved:
                case WorkspaceChangeKind.AdditionalDocumentChanged:
                case WorkspaceChangeKind.AdditionalDocumentReloaded:
                case WorkspaceChangeKind.AnalyzerConfigDocumentAdded:
                case WorkspaceChangeKind.AnalyzerConfigDocumentRemoved:
                case WorkspaceChangeKind.AnalyzerConfigDocumentChanged:
                case WorkspaceChangeKind.AnalyzerConfigDocumentReloaded:
                    // If an additional file or .editorconfig has changed we need to reanalyze the entire project.
                    Contract.ThrowIfNull(e.ProjectId);
                    EnqueueEvent(e.NewSolution, e.ProjectId, InvocationReasons.AdditionalDocumentChanged, eventName);
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(e.Kind);
                }
            }
Beispiel #9
0
        public virtual void Update(
            Optional <Drawing> drawing          = default(Optional <Drawing>),
            Optional <Plane> drawingPlane       = default(Optional <Plane>),
            Optional <ViewPort> activeViewPort  = default(Optional <ViewPort>),
            Optional <IViewControl> viewControl = default(Optional <IViewControl>),
            bool isDirty = true)
        {
            var e = new WorkspaceChangeEventArgs(
                drawing.HasValue,
                drawingPlane.HasValue,
                activeViewPort.HasValue,
                viewControl.HasValue,
                this.IsDirty != isDirty);

            OnWorkspaceChanging(e);
            if (drawing.HasValue)
            {
                this.Drawing = drawing.Value;
            }
            if (drawingPlane.HasValue)
            {
                this.DrawingPlane = drawingPlane.Value;
            }
            if (activeViewPort.HasValue)
            {
                this.ActiveViewPort = activeViewPort.Value;
            }
            if (viewControl.HasValue)
            {
                this.ViewControl = viewControl.Value;
            }
            this.IsDirty = isDirty;
            OnWorkspaceChanged(e);

            var selectedEntityIds = SelectedEntities.Select(ent => ent.Id).ToList();
        }
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            // We're getting an event for a workspace we already disconnected from
            if (args.NewSolution.Workspace != _workspace)
            {
                return;
            }

            // If the displayed project is being renamed, retrigger the update
            if (args.Kind == WorkspaceChangeKind.ProjectChanged && args.ProjectId != null)
            {
                var oldProject = args.OldSolution.GetProject(args.ProjectId);
                var newProject = args.NewSolution.GetProject(args.ProjectId);

                if (oldProject.Name != newProject.Name)
                {
                    var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());

                    if (currentContextDocumentId != null && currentContextDocumentId.ProjectId == args.ProjectId)
                    {
                        StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                    }
                }
            }

            if (args.Kind == WorkspaceChangeKind.DocumentChanged &&
                args.OldSolution == args.NewSolution)
            {
                var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());
                if (currentContextDocumentId != null && currentContextDocumentId == args.DocumentId)
                {
                    // The context has changed, so update everything.
                    StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                }
            }
        }
Beispiel #11
0
            private void ProcessProjectEvent(WorkspaceChangeEventArgs e, string eventName)
            {
                switch (e.Kind)
                {
                case WorkspaceChangeKind.ProjectAdded:
                    Contract.ThrowIfNull(e.ProjectId);
                    EnqueueEvent(e.NewSolution, e.ProjectId, InvocationReasons.DocumentAdded, eventName);
                    break;

                case WorkspaceChangeKind.ProjectRemoved:
                    Contract.ThrowIfNull(e.ProjectId);
                    EnqueueEvent(e.OldSolution, e.ProjectId, InvocationReasons.DocumentRemoved, eventName);
                    break;

                case WorkspaceChangeKind.ProjectChanged:
                case WorkspaceChangeKind.ProjectReloaded:
                    Contract.ThrowIfNull(e.ProjectId);
                    EnqueueEvent(e.OldSolution, e.NewSolution, e.ProjectId, eventName);
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(e.Kind);
                }
            }
Beispiel #12
0
        public async Task WorkspaceChanged_DocumentChanged_Razor_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 1,
                BlockDelayedUpdateWorkEnqueue = new ManualResetEventSlim(initialState: false),
            };

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            workspaceStateGenerator.ClearQueue();

            var solution = SolutionWithTwoProjects.WithDocumentText(RazorDocumentId, SourceText.From("Hello World"));
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id, RazorDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            detector.BlockDelayedUpdateWorkEnqueue.Set();

            await detector._deferredUpdates.Single().Value;

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
Beispiel #13
0
        public async Task WorkspaceChanged_ProjectAddedEvent_AddsProject()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue)
            {
                NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false),
            };
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectThree), CancellationToken.None).ConfigureAwait(false);

            var solution = SolutionWithOneProject;
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.ProjectAdded, oldSolution: EmptySolution, newSolution: solution, projectId: ProjectNumberThree.Id);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);
            detector.NotifyWorkspaceChangedEventComplete.Wait();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberThree.Id, p.WorkspaceProject.Id));
        }
            private void OnWorkspaceChanged(object?sender, WorkspaceChangeEventArgs e)
            {
                if (e.Kind == WorkspaceChangeKind.ProjectChanged)
                {
                    RoslynDebug.AssertNotNull(e.ProjectId);
                    var oldProject = e.OldSolution.GetRequiredProject(e.ProjectId);
                    var newProject = e.NewSolution.GetRequiredProject(e.ProjectId);

                    if (!object.Equals(oldProject.ParseOptions, newProject.ParseOptions))
                    {
                        var workspace  = e.NewSolution.Workspace;
                        var documentId = workspace.GetDocumentIdInCurrentContext(SubjectBuffer.AsTextContainer());
                        if (documentId != null)
                        {
                            var relatedDocumentIds = e.NewSolution.GetRelatedDocumentIds(documentId);

                            if (relatedDocumentIds.Any(d => d.ProjectId == e.ProjectId))
                            {
                                RaiseChanged();
                            }
                        }
                    }
                }
            }
            // We override Workspace_WorkspaceChanged in order to enforce calls to this to be on the foreground thread.
            // OmniSharp currently has an issue where they update the Solution on multiple different threads resulting
            // in change events dispatching through the Workspace on multiple different threads. This normalizes
            // that abnormality.
#pragma warning disable VSTHRD100 // Avoid async void methods
            internal override async void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
#pragma warning restore VSTHRD100 // Avoid async void methods
            {
                if (_foregroundDispatcher.IsForegroundThread)
                {
                    base.Workspace_WorkspaceChanged(sender, args);
                    return;
                }
                await Task.Factory.StartNew(
                    () =>
                {
                    try
                    {
                        base.Workspace_WorkspaceChanged(sender, args);
                    }
                    catch (Exception ex)
                    {
                        Debug.Fail("Unexpected error when handling a workspace changed event: " + ex);
                    }
                },
                    CancellationToken.None,
                    TaskCreationOptions.None,
                    _foregroundDispatcher.ForegroundScheduler);
            }
Beispiel #16
0
        public async System.Threading.Tasks.Task WorkspaceChangedAsync(object sender, WorkspaceChangeEventArgs e)
        {
            var profiler = MiniProfiler.StartNew(nameof(WorkspaceChangedAsync));

            profiler.Storage = new NLogStorage(LogManager.GetLogger("profiler"));
            var workspace = sender as VisualStudioWorkspace;

            switch (e.Kind)
            {
            case WorkspaceChangeKind.SolutionAdded:
                try
                {
                    using (profiler.Step(WorkspaceChangeKind.SolutionAdded.ToString()))
                    {
                        await _indexingQueue.EnqueueMultipleAsync(workspace.CurrentSolution.Projects);
                    }
                }
                catch (Exception ex)
                {
                    LogManager.GetLogger("error").Error(ex, "WorkspaceChangeKind.SolutionAdded");
                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                    OutputWindowLogger.WriteLn($"Exception occured during adding solution: {ex.Message}");
                }
                break;

            case WorkspaceChangeKind.SolutionChanged:
                break;

            case WorkspaceChangeKind.SolutionRemoved:
                break;

            case WorkspaceChangeKind.SolutionCleared:
                break;

            case WorkspaceChangeKind.SolutionReloaded:
                break;

            case WorkspaceChangeKind.ProjectAdded:
                try
                {
                    using (profiler.Step(WorkspaceChangeKind.SolutionAdded.ToString()))
                    {
                        await _indexingQueue.EnqueueMultipleAsync(workspace.CurrentSolution.Projects);
                    }
                }
                catch (Exception ex)
                {
                    LogManager.GetLogger("error").Error(ex, "WorkspaceChangeKind.ProjectAdded");
                    OutputWindowLogger.WriteLn($"Exception occured during adding projects: {ex.Message}");
                }
                break;

            case WorkspaceChangeKind.ProjectRemoved:
                break;

            case WorkspaceChangeKind.ProjectChanged:
                break;

            case WorkspaceChangeKind.ProjectReloaded:
                break;

            case WorkspaceChangeKind.DocumentAdded:
                var documentAddedChanges = e.NewSolution.GetChanges(e.OldSolution);
                var addedDocuments       = documentAddedChanges.GetProjectChanges()
                                           .SelectMany(x => x.GetAddedDocuments())
                                           .Select(x => workspace.CurrentSolution.GetDocument(x));
                await DocumentsAddedActionAsync(addedDocuments);

                break;

            case WorkspaceChangeKind.DocumentRemoved:
                var documentRemovedChanges = e.NewSolution.GetChanges(e.OldSolution);
                var removedDocuments       = documentRemovedChanges.GetProjectChanges()
                                             .SelectMany(x => x.GetRemovedDocuments());
                await DocumentRemovedActionAsync(removedDocuments);

                break;

            case WorkspaceChangeKind.DocumentReloaded:
                break;

            case WorkspaceChangeKind.DocumentChanged:
                break;

            case WorkspaceChangeKind.AdditionalDocumentAdded:
                break;

            case WorkspaceChangeKind.AdditionalDocumentRemoved:
                break;

            case WorkspaceChangeKind.AdditionalDocumentReloaded:
                break;

            case WorkspaceChangeKind.AdditionalDocumentChanged:
                break;

            default:
                break;
            }
            await profiler.StopAsync();
        }
Beispiel #17
0
 private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
 {
     if (args.Kind != WorkspaceChangeKind.DocumentChanged)
     {
         if (!_dismissed)
         {
             this.Cancel();
         }
     }
 }
 private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs eventArgs)
 => _workQueue.AddWork(true);
 private void OnWorkspaceChanged(object?sender, WorkspaceChangeEventArgs eventArgs)
 => _asyncDelay.RequeueWork();
Beispiel #20
0
        // Internal for testing, virtual for temporary VSCode workaround
        internal virtual void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
        {
            Project project;

            switch (e.Kind)
            {
            case WorkspaceChangeKind.ProjectAdded:
            {
                project = e.NewSolution.GetProject(e.ProjectId);

                Debug.Assert(project != null);

                if (TryGetProjectSnapshot(project.FilePath, out var projectSnapshot))
                {
                    _workspaceStateGenerator.Update(project, projectSnapshot, CancellationToken.None);
                }
                break;
            }

            case WorkspaceChangeKind.ProjectChanged:
            case WorkspaceChangeKind.ProjectReloaded:
            {
                project = e.NewSolution.GetProject(e.ProjectId);

                if (TryGetProjectSnapshot(project?.FilePath, out var _))
                {
                    EnqueueUpdate(e.ProjectId);
                }
                break;
            }

            case WorkspaceChangeKind.ProjectRemoved:
            {
                project = e.OldSolution.GetProject(e.ProjectId);
                Debug.Assert(project != null);

                if (TryGetProjectSnapshot(project?.FilePath, out var projectSnapshot))
                {
                    _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot, CancellationToken.None);
                }

                break;
            }

            case WorkspaceChangeKind.DocumentChanged:
            case WorkspaceChangeKind.DocumentReloaded:
            {
                // This is the case when a component declaration file changes on disk. We have an MSBuild
                // generator configured by the SDK that will poke these files on disk when a component
                // is saved, or loses focus in the editor.
                project = e.OldSolution.GetProject(e.ProjectId);
                var document = project.GetDocument(e.DocumentId);

                if (document.FilePath == null)
                {
                    return;
                }

                // Using EndsWith because Path.GetExtension will ignore everything before .cs
                // Using Ordinal because the SDK generates these filenames.
                // Stll have .cshtml.g.cs and .razor.g.cs for Razor.VSCode scenarios.
                if (document.FilePath.EndsWith(".cshtml.g.cs", StringComparison.Ordinal) ||
                    document.FilePath.EndsWith(".razor.g.cs", StringComparison.Ordinal) ||
                    document.FilePath.EndsWith(".razor", StringComparison.Ordinal) ||

                    // VSCode's background C# document
                    document.FilePath.EndsWith("__bg__virtual.cs", StringComparison.Ordinal))
                {
                    EnqueueUpdate(e.ProjectId);
                    return;
                }

                // We now know we're not operating directly on a Razor file. However, it's possible the user is operating on a partial class that is associated with a Razor file.

                if (IsPartialComponentClass(document))
                {
                    EnqueueUpdate(e.ProjectId);
                }

                break;
            }

            case WorkspaceChangeKind.SolutionAdded:
            case WorkspaceChangeKind.SolutionChanged:
            case WorkspaceChangeKind.SolutionCleared:
            case WorkspaceChangeKind.SolutionReloaded:
            case WorkspaceChangeKind.SolutionRemoved:

                if (e.OldSolution != null)
                {
                    foreach (var p in e.OldSolution.Projects)
                    {
                        if (TryGetProjectSnapshot(p?.FilePath, out var projectSnapshot))
                        {
                            _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot, CancellationToken.None);
                        }
                    }
                }

                InitializeSolution(e.NewSolution);
                break;
            }
        }
Beispiel #21
0
 private void WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     OnPropertyChangedDirect(string.Empty);
 }
Beispiel #22
0
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
        {
            switch (e.Kind)
            {
            case WorkspaceChangeKind.SolutionAdded:
                _infoBarShownForCurrentSolution = false;
                return;

            // Check if a new analyzer config document was added
            case WorkspaceChangeKind.AnalyzerConfigDocumentAdded:
                break;

            default:
                return;
            }

            // Bail out if we have a null DTE instance or we have already shown the info bar for current solution.
            if (_dte == null ||
                _infoBarShownForCurrentSolution)
            {
                return;
            }

            // Check if added analyzer config document is at the root of the current solution.
            var analyzerConfigDocumentFilePath = e.NewSolution.GetAnalyzerConfigDocument(e.DocumentId)?.FilePath;
            var analyzerConfigDirectory        = PathUtilities.GetDirectoryName(analyzerConfigDocumentFilePath);
            var solutionDirectory = PathUtilities.GetDirectoryName(e.NewSolution.FilePath);

            if (analyzerConfigDocumentFilePath == null ||
                analyzerConfigDirectory == null ||
                analyzerConfigDirectory != solutionDirectory)
            {
                return;
            }

            // Check if user has explicitly disabled the suggestion to add newly added analyzer config document as solution item.
            if (_workspace.Options.GetOption(NeverShowAgain))
            {
                return;
            }

            // Kick off a task to show info bar to make it a solution item.
            Task.Run(async() =>
            {
                await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();

                var solution = (Solution2)_dte.Solution;
                if (VisualStudioAddSolutionItemService.TryGetExistingSolutionItemsFolder(solution, analyzerConfigDocumentFilePath, out _, out var hasExistingSolutionItem) &&
                    hasExistingSolutionItem)
                {
                    return;
                }

                if (!_infoBarShownForCurrentSolution)
                {
                    _infoBarShownForCurrentSolution = true;
                    var infoBarService = _workspace.Services.GetRequiredService <IInfoBarService>();
                    infoBarService.ShowInfoBarInGlobalView(
                        ServicesVSResources.A_new_editorconfig_file_was_detected_at_the_root_of_your_solution_Would_you_like_to_make_it_a_solution_item,
                        GetInfoBarUIItems().ToArray());
                }
            });

            return;

            // Local functions
            IEnumerable <InfoBarUI> GetInfoBarUIItems()
            {
                // Yes - add editorconfig solution item.
                yield return(new InfoBarUI(
                                 title: ServicesVSResources.Yes,
                                 kind: InfoBarUI.UIKind.Button,
                                 action: AddEditorconfigSolutionItem,
                                 closeAfterAction: true));

                // No - do not add editorconfig solution item.
                yield return(new InfoBarUI(
                                 title: ServicesVSResources.No,
                                 kind: InfoBarUI.UIKind.Button,
                                 action: () => { },
                                 closeAfterAction: true));

                // Don't show the InfoBar again link
                yield return(new InfoBarUI(title: ServicesVSResources.Never_show_this_again,
                                           kind: InfoBarUI.UIKind.Button,
                                           action: () => _workspace.Options = _workspace.Options.WithChangedOption(NeverShowAgain, true),
                                           closeAfterAction: true));
            }

            void AddEditorconfigSolutionItem()
            {
                var addSolutionItemService = _workspace.Services.GetRequiredService <IAddSolutionItemService>();

                addSolutionItemService.AddSolutionItemAsync(analyzerConfigDocumentFilePath, CancellationToken.None).Wait();
            }
        }
Beispiel #23
0
            private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
            {
                // guard us from cancellation
                try
                {
                    ProcessEvents(args, _listener.BeginAsyncOperation("OnWorkspaceChanged"));
                }
                catch (OperationCanceledException oce)
                {
                    if (NotOurShutdownToken(oce))
                    {
                        throw;
                    }

                    // it is our cancellation, ignore
                }
                catch (AggregateException ae)
                {
                    ae = ae.Flatten();

                    // If we had a mix of exceptions, don't eat it
                    if (ae.InnerExceptions.Any(e => !(e is OperationCanceledException)) ||
                        ae.InnerExceptions.Cast<OperationCanceledException>().Any(NotOurShutdownToken))
                    {
                        // We had a cancellation with a different token, so don't eat it
                        throw;
                    }

                    // it is our cancellation, ignore
                }
            }
Beispiel #24
0
        private void OnWorkspaceChangedLookForOptionsChanges(object sender, WorkspaceChangeEventArgs e)
        {
            if (e.Kind == WorkspaceChangeKind.SolutionCleared ||
                e.Kind == WorkspaceChangeKind.SolutionReloaded ||
                e.Kind == WorkspaceChangeKind.SolutionRemoved)
            {
                Workspace.WorkspaceChanged -= OnWorkspaceChangedLookForOptionsChanges;
            }
            else if (e.ProjectId == ProjectId)
            {
                if (e.Kind == WorkspaceChangeKind.ProjectRemoved)
                {
                    Workspace.WorkspaceChanged -= OnWorkspaceChangedLookForOptionsChanges;
                }
                else if (e.Kind == WorkspaceChangeKind.ProjectChanged)
                {
                    OnProjectConfigurationChanged();
                }
                else if (e.DocumentId != null)
                {
                    switch (e.Kind)
                    {
                    case WorkspaceChangeKind.AnalyzerConfigDocumentAdded:
                    case WorkspaceChangeKind.AnalyzerConfigDocumentChanged:
                    case WorkspaceChangeKind.AnalyzerConfigDocumentReloaded:
                    case WorkspaceChangeKind.AnalyzerConfigDocumentRemoved:
                        OnProjectConfigurationChanged();
                        break;
                    }
                }
            }

            return;

            // Local functions.
            void OnProjectConfigurationChanged()
            {
                var project = e.NewSolution.GetRequiredProject(ProjectId);
                var newGeneralDiagnosticOption   = project.CompilationOptions !.GeneralDiagnosticOption;
                var newSpecificDiagnosticOptions = project.CompilationOptions !.SpecificDiagnosticOptions;
                var newAnalyzerConfigOptions     = project.GetAnalyzerConfigOptions();

                if (newGeneralDiagnosticOption != _generalDiagnosticOption ||
                    !object.ReferenceEquals(newSpecificDiagnosticOptions, _specificDiagnosticOptions) ||
                    !object.ReferenceEquals(newAnalyzerConfigOptions?.TreeOptions, _analyzerConfigOptions?.TreeOptions) ||
                    !object.ReferenceEquals(newAnalyzerConfigOptions?.AnalyzerOptions, _analyzerConfigOptions?.AnalyzerOptions))
                {
                    _generalDiagnosticOption   = newGeneralDiagnosticOption;
                    _specificDiagnosticOptions = newSpecificDiagnosticOptions;
                    _analyzerConfigOptions     = newAnalyzerConfigOptions;

                    Contract.ThrowIfNull(_items, "We only subscribe to events after we create the items, so this should not be null.");

                    foreach (var item in _items.OfType <DiagnosticItem>())
                    {
                        var effectiveSeverity = item.Descriptor.GetEffectiveSeverity(project.CompilationOptions, newAnalyzerConfigOptions);
                        item.UpdateEffectiveSeverity(effectiveSeverity);
                    }
                }
            }
        }
Beispiel #25
0
 public static bool IsActiveDocumentCleared(this WorkspaceChangeEventArgs changeEventArgs, Document?oldDocument) =>
 changeEventArgs.CheckIfNull(nameof(changeEventArgs)).Kind switch
 {
Beispiel #26
0
 async void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     await CheckForSemanticChange();
 }
 private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     switch (e.Kind)
     {
         case WorkspaceChangeKind.SolutionAdded:
         case WorkspaceChangeKind.SolutionChanged:
         case WorkspaceChangeKind.SolutionRemoved:
         case WorkspaceChangeKind.SolutionCleared:
         case WorkspaceChangeKind.SolutionReloaded:
             ClearVersionMap(e.NewSolution.Workspace, e.NewSolution.ProjectIds);
             break;
         case WorkspaceChangeKind.ProjectAdded:
         case WorkspaceChangeKind.ProjectRemoved:
         case WorkspaceChangeKind.ProjectChanged:
         case WorkspaceChangeKind.ProjectReloaded:
             ClearVersionMap(e.NewSolution.Workspace, e.ProjectId);
             break;
         case WorkspaceChangeKind.DocumentRemoved:
             ClearVersionMap(e.NewSolution.Workspace, e.DocumentId);
             break;
         case WorkspaceChangeKind.DocumentAdded:
         case WorkspaceChangeKind.DocumentReloaded:
         case WorkspaceChangeKind.DocumentChanged:
         case WorkspaceChangeKind.AdditionalDocumentAdded:
         case WorkspaceChangeKind.AdditionalDocumentRemoved:
         case WorkspaceChangeKind.AdditionalDocumentChanged:
         case WorkspaceChangeKind.AdditionalDocumentReloaded:
             break;
         default:
             Contract.Fail("Unknown event");
             break;
     }
 }
            async void Ws_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
            {
                var ws = (Microsoft.CodeAnalysis.Workspace)sender;
                var currentSolution = ws.CurrentSolution;

                if (currentSolution == null)
                {
                    return;
                }
                try {
                    switch (e.Kind)
                    {
                    case WorkspaceChangeKind.ProjectAdded:
                        var project1 = currentSolution.GetProject(e.ProjectId);
                        if (project1 != null)
                        {
                            SearchAsync(documentInfos, project1, default(CancellationToken));
                        }
                        break;

                    case WorkspaceChangeKind.ProjectRemoved:
                        var project = currentSolution.GetProject(e.ProjectId);
                        if (project != null)
                        {
                            foreach (var docId in project.DocumentIds)
                            {
                                RemoveDocument(documentInfos, docId);
                            }
                        }
                        break;

                    case WorkspaceChangeKind.DocumentAdded:
                        var document = currentSolution.GetDocument(e.DocumentId);
                        if (document != null)
                        {
                            await UpdateDocument(documentInfos, document, default(CancellationToken));
                        }
                        break;

                    case WorkspaceChangeKind.DocumentRemoved:
                        RemoveDocument(documentInfos, e.DocumentId);
                        break;

                    case WorkspaceChangeKind.DocumentChanged:
                        var doc = currentSolution.GetDocument(e.DocumentId);
                        if (doc != null)
                        {
                            CancellationTokenSource tcs;
                            lock (documentChangedCts) {
                                CancellationTokenSource oldTcs;
                                if (documentChangedCts.TryGetValue(e.DocumentId, out oldTcs))
                                {
                                    oldTcs.Cancel();
                                }
                                tcs = new CancellationTokenSource();
                                documentChangedCts [e.DocumentId] = tcs;
                            }
                            try {
                                //Delaying parsing of new content for 1 second shouldn't be noticable by user
                                //since he would have to edit file and instantlly go to search for newly written member...
                                await Task.Delay(1000, tcs.Token).ConfigureAwait(false);

                                await Task.Run(delegate {
                                    return(UpdateDocument(documentInfos, doc, tcs.Token));
                                }, tcs.Token).ConfigureAwait(false);
                            } finally {
                                lock (documentChangedCts) {
                                    //cts might be replaced by newer call cts
                                    CancellationTokenSource existingCts;
                                    if (documentChangedCts.TryGetValue(e.DocumentId, out existingCts) && tcs == existingCts)
                                    {
                                        documentChangedCts.Remove(e.DocumentId);
                                    }
                                }
                            }
                        }
                        break;
                    }
                } catch (AggregateException ae) {
                    ae.Flatten().Handle(ex => ex is OperationCanceledException);
                } catch (OperationCanceledException) {
                } catch (Exception ex) {
                    LoggingService.LogError("Error while updating navigation symbol cache.", ex);
                }
            }
Beispiel #29
0
 private void WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     ignoreLayerChange = true;
     Layers            = workspace.Drawing.GetLayers().OrderBy(l => l.Name).Select(l => new ReadOnlyLayerViewModel(l));
     ignoreLayerChange = false;
 }
Beispiel #30
0
 // We override Workspace_WorkspaceChanged in order to enforce calls to this to be on the project snapshot manager's
 // thread. OmniSharp currently has an issue where they update the Solution on multiple different threads resulting
 // in change events dispatching through the Workspace on multiple different threads. This normalizes
 // that abnormality.
 internal override void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
 {
     _ = Workspace_WorkspaceChangedAsync(sender, args, CancellationToken.None);
 }
Beispiel #31
0
 private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     Debug.Assert(View == null);
     StartRefresh();
 }
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            // We're getting an event for a workspace we already disconnected from
            if (args.NewSolution.Workspace != _workspace)
            {
                return;
            }

            // If the displayed project is being renamed, retrigger the update
            if (args.Kind == WorkspaceChangeKind.ProjectChanged && args.ProjectId != null)
            {
                var oldProject = args.OldSolution.GetProject(args.ProjectId);
                var newProject = args.NewSolution.GetProject(args.ProjectId);

                if (oldProject.Name != newProject.Name)
                {
                    var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());

                    if (currentContextDocumentId != null && currentContextDocumentId.ProjectId == args.ProjectId)
                    {
                        StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                    }
                }
            }

            if (args.Kind == WorkspaceChangeKind.DocumentChanged &&
                args.OldSolution == args.NewSolution)
            {
                var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());
                if (currentContextDocumentId != null && currentContextDocumentId == args.DocumentId)
                {
                    // The context has changed, so update everything.
                    StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                }
            }
        }
        // Here we're specifically listening for cases when a user opens a Razor document and an active C# content gets created.
        internal void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            lock (_workspaceChangedLock)
            {
                switch (args.Kind)
                {
                case WorkspaceChangeKind.DocumentAdded:
                {
                    // We could technically listen for DocumentAdded here but just because a document gets added doesn't mean it has content included.
                    // Therefore we need to wait for content to populated for Razor files so we don't preemptively remove the corresponding background
                    // C# before the active C# content has been populated.

                    var project  = args.NewSolution.GetProject(args.ProjectId);
                    var document = project.GetDocument(args.DocumentId);

                    if (document.FilePath == null)
                    {
                        break;
                    }

                    if (document.FilePath.EndsWith(ActiveVirtualDocumentSuffix, StringComparison.Ordinal) && !document.FilePath.EndsWith(BackgroundVirtualDocumentSuffix, StringComparison.Ordinal))
                    {
                        // Document from editor got opened, clear out any background documents of the same type

                        var razorDocumentFilePath      = GetRazorDocumentFilePath(document);
                        var backgroundDocumentFilePath = GetBackgroundVirtualDocumentFilePath(razorDocumentFilePath);
                        var backgroundDocument         = GetRoslynDocument(project, backgroundDocumentFilePath);
                        if (backgroundDocument != null)
                        {
                            _workspace.RemoveDocument(backgroundDocument.Id);
                        }
                    }
                    break;
                }

                case WorkspaceChangeKind.DocumentRemoved:
                {
                    var project  = args.OldSolution.GetProject(args.ProjectId);
                    var document = project.GetDocument(args.DocumentId);

                    if (document.FilePath == null)
                    {
                        break;
                    }

                    if (document.FilePath.EndsWith(ActiveVirtualDocumentSuffix, StringComparison.Ordinal) && !document.FilePath.EndsWith(BackgroundVirtualDocumentSuffix, StringComparison.Ordinal))
                    {
                        var razorDocumentFilePath = GetRazorDocumentFilePath(document);

                        if (File.Exists(razorDocumentFilePath))
                        {
                            // Razor document closed because the backing C# virtual document went away
                            var backgroundDocumentFilePath = GetBackgroundVirtualDocumentFilePath(razorDocumentFilePath);
                            var newName             = Path.GetFileName(backgroundDocumentFilePath);
                            var delegatedTextLoader = new DelegatedTextLoader(document);
                            var movedDocumentInfo   = DocumentInfo.Create(args.DocumentId, newName, loader: delegatedTextLoader, filePath: backgroundDocumentFilePath);
                            _workspace.AddDocument(movedDocumentInfo);
                        }
                    }
                }
                break;
                }
            }
        }
            private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
            {
                // We're getting an event for a workspace we already disconnected from
                if (args.NewSolution.Workspace != _workspace)
                {
                    // we are async so we are getting events from previous workspace we were associated with
                    // just ignore them
                    return;
                }

                switch (args.Kind)
                {
                    case WorkspaceChangeKind.ProjectChanged:
                        {
                            var documentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());
                            if (documentId == null || documentId.ProjectId != args.ProjectId)
                            {
                                break;
                            }

                            var oldProject = args.OldSolution.GetProject(args.ProjectId);
                            var newProject = args.NewSolution.GetProject(args.ProjectId);

                            // make sure in case of parse config change, we re-colorize whole document. not just edited section.
                            var configChanged = !object.Equals(oldProject.ParseOptions, newProject.ParseOptions);
                            EnqueueParseSnapshotTask(newProject.GetDocument(documentId));
                            break;
                        }

                    case WorkspaceChangeKind.DocumentChanged:
                        {
                            ParseIfThisDocument(args.OldSolution, args.NewSolution, args.DocumentId);
                            break;
                        }
                }

                // put a request to update last parsed document.
                // this will make us to enqueue a request per workspace change event per a opened file.
                // if this show up as perf cost, we might need to revisit this design. currently we do this so that our Roslyn Language Service API
                // maintain its consistency.
                var newSolution = args.NewSolution;
                _workQueue.EnqueueBackgroundTask(c => UpdateLastParsedDocumentAsync(newSolution, c), "UpdateLastParsedDocument", CancellationToken.None);
            }
Beispiel #35
0
 private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
 {
     EnqueueUpdate();
 }
Beispiel #36
0
            private void ProcessEvents(WorkspaceChangeEventArgs args, IAsyncToken asyncToken)
            {
                SolutionCrawlerLogger.LogWorkspaceEvent(_logAggregator, (int)args.Kind);

                // TODO: add telemetry that record how much it takes to process an event (max, min, average and etc)
                switch (args.Kind)
                {
                    case WorkspaceChangeKind.SolutionAdded:
                    case WorkspaceChangeKind.SolutionChanged:
                    case WorkspaceChangeKind.SolutionReloaded:
                    case WorkspaceChangeKind.SolutionRemoved:
                    case WorkspaceChangeKind.SolutionCleared:
                        ProcessSolutionEvent(args, asyncToken);
                        break;
                    case WorkspaceChangeKind.ProjectAdded:
                    case WorkspaceChangeKind.ProjectChanged:
                    case WorkspaceChangeKind.ProjectReloaded:
                    case WorkspaceChangeKind.ProjectRemoved:
                        ProcessProjectEvent(args, asyncToken);
                        break;
                    case WorkspaceChangeKind.DocumentAdded:
                    case WorkspaceChangeKind.DocumentReloaded:
                    case WorkspaceChangeKind.DocumentChanged:
                    case WorkspaceChangeKind.DocumentRemoved:
                    case WorkspaceChangeKind.AdditionalDocumentAdded:
                    case WorkspaceChangeKind.AdditionalDocumentRemoved:
                    case WorkspaceChangeKind.AdditionalDocumentChanged:
                    case WorkspaceChangeKind.AdditionalDocumentReloaded:
                        ProcessDocumentEvent(args, asyncToken);
                        break;
                    default:
                        throw ExceptionUtilities.Unreachable;
                }
            }
Beispiel #37
0
            private void ProcessEvent(WorkspaceChangeEventArgs args, string eventName)
            {
                SolutionCrawlerLogger.LogWorkspaceEvent(_logAggregator, (int)args.Kind);

                // TODO: add telemetry that record how much it takes to process an event (max, min, average and etc)
                switch (args.Kind)
                {
                case WorkspaceChangeKind.SolutionAdded:
                    EnqueueFullSolutionEvent(args.NewSolution, InvocationReasons.DocumentAdded, eventName);
                    break;

                case WorkspaceChangeKind.SolutionChanged:
                case WorkspaceChangeKind.SolutionReloaded:
                    EnqueueSolutionChangedEvent(args.OldSolution, args.NewSolution, eventName);
                    break;

                case WorkspaceChangeKind.SolutionRemoved:
                    EnqueueFullSolutionEvent(args.OldSolution, InvocationReasons.SolutionRemoved, eventName);
                    break;

                case WorkspaceChangeKind.SolutionCleared:
                    EnqueueFullSolutionEvent(args.OldSolution, InvocationReasons.DocumentRemoved, eventName);
                    break;

                case WorkspaceChangeKind.ProjectAdded:
                    Contract.ThrowIfNull(args.ProjectId);
                    EnqueueFullProjectEvent(args.NewSolution, args.ProjectId, InvocationReasons.DocumentAdded, eventName);
                    break;

                case WorkspaceChangeKind.ProjectChanged:
                case WorkspaceChangeKind.ProjectReloaded:
                    Contract.ThrowIfNull(args.ProjectId);
                    EnqueueProjectChangedEvent(args.OldSolution, args.NewSolution, args.ProjectId, eventName);
                    break;

                case WorkspaceChangeKind.ProjectRemoved:
                    Contract.ThrowIfNull(args.ProjectId);
                    EnqueueFullProjectEvent(args.OldSolution, args.ProjectId, InvocationReasons.DocumentRemoved, eventName);
                    break;

                case WorkspaceChangeKind.DocumentAdded:
                    Contract.ThrowIfNull(args.DocumentId);
                    EnqueueFullDocumentEvent(args.NewSolution, args.DocumentId, InvocationReasons.DocumentAdded, eventName);
                    break;

                case WorkspaceChangeKind.DocumentReloaded:
                case WorkspaceChangeKind.DocumentChanged:
                    Contract.ThrowIfNull(args.DocumentId);
                    EnqueueDocumentChangedEvent(args.OldSolution, args.NewSolution, args.DocumentId, eventName);
                    break;

                case WorkspaceChangeKind.DocumentRemoved:
                    Contract.ThrowIfNull(args.DocumentId);
                    EnqueueFullDocumentEvent(args.OldSolution, args.DocumentId, InvocationReasons.DocumentRemoved, eventName);
                    break;

                case WorkspaceChangeKind.AdditionalDocumentAdded:
                case WorkspaceChangeKind.AdditionalDocumentRemoved:
                case WorkspaceChangeKind.AdditionalDocumentChanged:
                case WorkspaceChangeKind.AdditionalDocumentReloaded:
                case WorkspaceChangeKind.AnalyzerConfigDocumentAdded:
                case WorkspaceChangeKind.AnalyzerConfigDocumentRemoved:
                case WorkspaceChangeKind.AnalyzerConfigDocumentChanged:
                case WorkspaceChangeKind.AnalyzerConfigDocumentReloaded:
                    // If an additional file or .editorconfig has changed we need to reanalyze the entire project.
                    Contract.ThrowIfNull(args.ProjectId);
                    EnqueueFullProjectEvent(args.NewSolution, args.ProjectId, InvocationReasons.AdditionalDocumentChanged, eventName);
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(args.Kind);
                }
            }
        // Internal for testing, virtual for temporary VSCode workaround
        internal virtual void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e)
        {
            Project project;

            switch (e.Kind)
            {
            case WorkspaceChangeKind.ProjectAdded:
            {
                project = e.NewSolution.GetProject(e.ProjectId);

                Debug.Assert(project != null);

                if (TryGetProjectSnapshot(project.FilePath, out var projectSnapshot))
                {
                    _workspaceStateGenerator.Update(project, projectSnapshot);
                }
                break;
            }

            case WorkspaceChangeKind.ProjectChanged:
            case WorkspaceChangeKind.ProjectReloaded:
            {
                project = e.NewSolution.GetProject(e.ProjectId);

                if (TryGetProjectSnapshot(project?.FilePath, out var _))
                {
                    EnqueueUpdate(e.ProjectId);
                }
                break;
            }

            case WorkspaceChangeKind.ProjectRemoved:
            {
                project = e.OldSolution.GetProject(e.ProjectId);
                Debug.Assert(project != null);

                if (TryGetProjectSnapshot(project?.FilePath, out var projectSnapshot))
                {
                    _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot);
                }

                break;
            }

            case WorkspaceChangeKind.DocumentChanged:
            case WorkspaceChangeKind.DocumentReloaded:
            {
                // This is the case when a component declaration file changes on disk. We have an MSBuild
                // generator configured by the SDK that will poke these files on disk when a component
                // is saved, or loses focus in the editor.
                project = e.OldSolution.GetProject(e.ProjectId);
                var document = project.GetDocument(e.DocumentId);

                if (document.FilePath == null)
                {
                    break;
                }

                // Using EndsWith because Path.GetExtension will ignore everything before .cs
                // Using Ordinal because the SDK generates these filenames.
                if (document.FilePath.EndsWith(".cshtml.g.cs", StringComparison.Ordinal) || document.FilePath.EndsWith(".razor.g.cs", StringComparison.Ordinal))
                {
                    EnqueueUpdate(e.ProjectId);
                }

                break;
            }

            case WorkspaceChangeKind.SolutionAdded:
            case WorkspaceChangeKind.SolutionChanged:
            case WorkspaceChangeKind.SolutionCleared:
            case WorkspaceChangeKind.SolutionReloaded:
            case WorkspaceChangeKind.SolutionRemoved:

                if (e.OldSolution != null)
                {
                    foreach (var p in e.OldSolution.Projects)
                    {
                        if (TryGetProjectSnapshot(p?.FilePath, out var projectSnapshot))
                        {
                            _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot);
                        }
                    }
                }

                InitializeSolution(e.NewSolution);
                break;
            }
        }
Beispiel #39
0
            private void ProcessDocumentEvent(WorkspaceChangeEventArgs e, IAsyncToken asyncToken)
            {
                switch (e.Kind)
                {
                    case WorkspaceChangeKind.DocumentAdded:
                        EnqueueEvent(e.NewSolution, e.DocumentId, InvocationReasons.DocumentAdded, asyncToken);
                        break;
                    case WorkspaceChangeKind.DocumentRemoved:
                        EnqueueEvent(e.OldSolution, e.DocumentId, InvocationReasons.DocumentRemoved, asyncToken);
                        break;
                    case WorkspaceChangeKind.DocumentReloaded:
                    case WorkspaceChangeKind.DocumentChanged:
                        EnqueueEvent(e.OldSolution, e.NewSolution, e.DocumentId, asyncToken);
                        break;

                    case WorkspaceChangeKind.AdditionalDocumentAdded:
                    case WorkspaceChangeKind.AdditionalDocumentRemoved:
                    case WorkspaceChangeKind.AdditionalDocumentChanged:
                    case WorkspaceChangeKind.AdditionalDocumentReloaded:
                        // If an additional file has changed we need to reanalyze the entire project.
                        EnqueueEvent(e.NewSolution, e.ProjectId, InvocationReasons.AdditionalDocumentChanged, asyncToken);
                        break;

                    default:
                        throw ExceptionUtilities.Unreachable;
                }
            }
Beispiel #40
0
 protected virtual void SolutionOrProjectChanged(WorkspaceChangeEventArgs e)
 {
     // do nothing in base implementation
 }
Beispiel #41
0
 private void ProcessSolutionEvent(WorkspaceChangeEventArgs e, IAsyncToken asyncToken)
 {
     switch (e.Kind)
     {
         case WorkspaceChangeKind.SolutionAdded:
             OnSolutionAdded(e.NewSolution);
             EnqueueEvent(e.NewSolution, InvocationReasons.DocumentAdded, asyncToken);
             break;
         case WorkspaceChangeKind.SolutionRemoved:
             EnqueueEvent(e.OldSolution, InvocationReasons.SolutionRemoved, asyncToken);
             break;
         case WorkspaceChangeKind.SolutionCleared:
             EnqueueEvent(e.OldSolution, InvocationReasons.DocumentRemoved, asyncToken);
             break;
         case WorkspaceChangeKind.SolutionChanged:
         case WorkspaceChangeKind.SolutionReloaded:
             EnqueueEvent(e.OldSolution, e.NewSolution, asyncToken);
             break;
         default:
             throw ExceptionUtilities.Unreachable;
     }
 }