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.Task;

            var(workspaceProject, projectSnapshot) = Assert.Single(workspaceStateGenerator.UpdateQueue);
            Assert.Equal(workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
        public async Task ProjectOperations_EndBuild_ProjectWithoutWorkspaceProject_Noops()
        {
            // Arrange
            var expectedPath   = "Path/To/Project.csproj";
            var projectService = CreateProjectService(expectedPath);

            var args            = new BuildEventArgs(monitor: null, success: true);
            var projectSnapshot = new DefaultProjectSnapshot(
                ProjectState.Create(
                    Workspace.Services,
                    new HostProject(expectedPath, RazorConfiguration.Default, "Project")));

            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Returns(Workspace);
            projectManager
            .Setup(p => p.GetLoadedProject(expectedPath))
            .Returns(projectSnapshot);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var trigger = new ProjectBuildChangeTrigger(Dispatcher, projectService, workspaceStateGenerator, projectManager.Object);

            // Act
            await trigger.HandleEndBuildAsync(args);

            // Assert
            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
示例#3
0
        public async Task WorkspaceChanged_DocumentChanged_CSHTML_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 50,
            };

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

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

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

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

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

            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);
        }
示例#4
0
        public async Task SolutionClosing_StopsActiveWork()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart     = new ManualResetEventSlim(initialState: false);
            WorkQueueTestAccessor.NotifyBackgroundWorkStarting = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            workspaceStateGenerator.ClearQueue();
            WorkQueueTestAccessor.NotifyBackgroundWorkStarting.Wait();

            // Act
            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.SolutionClosed();

                // Trigger a project removed event while solution is closing to clear state.
                projectManager.ProjectRemoved(HostProjectOne);
            }, CancellationToken.None).ConfigureAwait(false);

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

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
示例#5
0
        public async Task IsPartialComponentClass_NonComponents_ReturnsFalse()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector   = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var sourceText = SourceText.From(
                $@"
public partial class NonComponent1 {{}}
public class NonComponent2 {{}}
public partial class NonComponent3 {{}}
public class NonComponent4 {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = CSharpSyntaxTree.ParseText(sourceText).GetRoot();
            var solution       = SolutionWithTwoProjects
                                 .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                                 .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // Initialize document
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            // Act
            var result = detector.IsPartialComponentClass(document);

            // Assert
            Assert.False(result);
        }
示例#6
0
        public async Task WorkspaceChanged_ProjectChangeEvents_UpdatesProjectState_AfterDelay(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 1,
                BlockDelayedUpdateWorkEnqueue = new ManualResetEventSlim(initialState: false),
            };

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

            projectManager.ProjectAdded(HostProjectOne);

            var solution = SolutionWithTwoProjects.WithProjectAssemblyName(ProjectNumberOne.Id, "Changed");
            var e        = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

            // 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);
        }
示例#7
0
        public async Task IsPartialComponentClass_InitializedDocument_ReturnsTrue()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector   = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);
            var sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = await CSharpSyntaxTree.ParseText(sourceText).GetRootAsync();

            var solution = SolutionWithTwoProjects
                           .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                           .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // Initialize document
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            // Act
            var result = detector.IsPartialComponentClass(document);

            // Assert
            Assert.True(result);
        }
示例#8
0
        public async Task SolutionClosing_CancelsActiveWork()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Workspace)
            {
                AllowNotifyListeners = true,
            };
            var expectedProjectPath     = SomeProject.FilePath;
            var expectedProjectSnapshot = await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.ProjectAdded(SomeProject);
                projectManager.ProjectAdded(SomeOtherProject);

                return(projectManager.GetLoadedProject(SomeProject.FilePath));
            }, CancellationToken.None);

            var projectService = new Mock <TextBufferProjectService>(MockBehavior.Strict);

            projectService.Setup(p => p.GetProjectPath(It.IsAny <IVsHierarchy>())).Returns(expectedProjectPath);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();

            var trigger = new VsSolutionUpdatesProjectSnapshotChangeTrigger(TestServiceProvider.Instance, projectService.Object, workspaceStateGenerator, Dispatcher, JoinableTaskFactory.Context);

            trigger.Initialize(projectManager);
            trigger.UpdateProjectCfg_Done(Mock.Of <IVsHierarchy>(MockBehavior.Strict), pCfgProj: default, pCfgSln: default, dwAction: default, fSuccess: default, fCancel: default);
        public async Task ProjectOperations_EndBuild_EnqueuesProjectStateUpdate()
        {
            // Arrange
            var expectedProjectPath = SomeProject.FilePath;
            var projectService      = CreateProjectService(expectedProjectPath);

            var args            = new BuildEventArgs(monitor: null, success: true);
            var projectSnapshot = new DefaultProjectSnapshot(ProjectState.Create(Workspace.Services, SomeProject));

            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Returns(Workspace);
            projectManager
            .Setup(p => p.GetLoadedProject(SomeProject.FilePath))
            .Returns(projectSnapshot);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var trigger = new ProjectBuildChangeTrigger(Dispatcher, projectService, workspaceStateGenerator, projectManager.Object);

            // Act
            await trigger.HandleEndBuildAsync(args);

            Thread.Sleep(500);

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

            Assert.Equal(SomeWorkspaceProject, update.workspaceProject);
        }
示例#10
0
        public async Task WorkspaceChanged_DocumentChanged_Razor_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            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);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

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

            Assert.Equal(update.WorkspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.ProjectSnapshot.FilePath, HostProjectOne.FilePath);
        }
示例#11
0
        public async Task WorkspaceChanged_ProjectRemovedEvent_QueuesProjectStateRemoval()
        {
            // 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(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
            }, CancellationToken.None).ConfigureAwait(false);

            var solution = SolutionWithTwoProjects.RemoveProject(ProjectNumberOne.Id);
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.ProjectRemoved, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Null(p.WorkspaceProject));
        }
示例#12
0
        public async Task WorkspaceChanged_SolutionEvents_EnqueuesUpdatesForProjectsInSolution(WorkspaceChangeKind kind)
        {
            // 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(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
            }, CancellationToken.None).ConfigureAwait(false);

            var e = new WorkspaceChangeEventArgs(kind, oldSolution: EmptySolution, newSolution: SolutionWithTwoProjects);

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberOne.Id, p.WorkspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.WorkspaceProject.Id));
        }
示例#13
0
        public void IsPartialComponentClass_Uninitialized_ReturnsFalse()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector   = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = CSharpSyntaxTree.ParseText(sourceText).GetRoot();
            var solution       = SolutionWithTwoProjects
                                 .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                                 .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // Act
            var result = detector.IsPartialComponentClass(document);

            // Assert
            Assert.False(result);
        }
示例#14
0
        public void WorkspaceChanged_SolutionEvents_EnqueuesStateClear_EnqueuesSolutionProjectUpdates(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            projectManager.ProjectAdded(HostProjectTwo);
            projectManager.ProjectAdded(HostProjectThree);

            // Initialize with a project. This will get removed.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithOneProject);

            detector.Workspace_WorkspaceChanged(Workspace, e);

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithOneProject, newSolution: SolutionWithTwoProjects);

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberThree.Id, p.workspaceProject.Id),
                p => Assert.Null(p.workspaceProject),
                p => Assert.Equal(ProjectNumberOne.Id, p.workspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.workspaceProject.Id));
        }
示例#15
0
        public async Task WorkspaceChanged_DocumentChanged_PartialComponent_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 sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = CSharpSyntaxTree.ParseText(sourceText).GetRoot();
            var solution       = SolutionWithTwoProjects
                                 .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                                 .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // The change detector only operates when a semantic model / syntax tree is available.
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: solution, newSolution: solution, projectId: ProjectNumberOne.Id, PartialComponentClassDocumentId);

            // 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);
        }
示例#16
0
        public async Task WorkspaceChanged_DocumentChanged_PartialComponent_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            workspaceStateGenerator.ClearQueue();

            var sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = await CSharpSyntaxTree.ParseText(sourceText).GetRootAsync();

            var solution = SolutionWithTwoProjects
                           .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                           .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // The change detector only operates when a semantic model / syntax tree is available.
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: solution, newSolution: solution, projectId: ProjectNumberOne.Id, PartialComponentClassDocumentId);

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

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

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();

            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

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

            Assert.Equal(update.WorkspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.ProjectSnapshot.FilePath, HostProjectOne.FilePath);
        }
        public void UpdateProjectCfg_Done_KnownProject_EnqueuesProjectStateUpdate()
        {
            // Arrange
            var expectedProjectPath = SomeProject.FilePath;

            uint cookie;
            var  buildManager = new Mock <IVsSolutionBuildManager>(MockBehavior.Strict);

            buildManager
            .Setup(b => b.AdviseUpdateSolutionEvents(It.IsAny <VsSolutionUpdatesProjectSnapshotChangeTrigger>(), out cookie))
            .Returns(VSConstants.S_OK);

            var services = new Mock <IServiceProvider>(MockBehavior.Strict);

            services.Setup(s => s.GetService(It.Is <Type>(f => f == typeof(SVsSolutionBuildManager)))).Returns(buildManager.Object);

            var projectService = new Mock <TextBufferProjectService>(MockBehavior.Strict);

            projectService.Setup(p => p.GetProjectPath(It.IsAny <IVsHierarchy>())).Returns(expectedProjectPath);

            var projectSnapshots = new[]
            {
                new DefaultProjectSnapshot(ProjectState.Create(Workspace.Services, SomeProject)),
                new DefaultProjectSnapshot(ProjectState.Create(Workspace.Services, SomeOtherProject)),
            };

            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Returns(Workspace);
            projectManager
            .Setup(p => p.GetLoadedProject(expectedProjectPath))
            .Returns(projectSnapshots[0]);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();

            var trigger = new VsSolutionUpdatesProjectSnapshotChangeTrigger(services.Object, projectService.Object, workspaceStateGenerator);

            trigger.Initialize(projectManager.Object);

            // Act
            trigger.UpdateProjectCfg_Done(Mock.Of <IVsHierarchy>(MockBehavior.Strict), Mock.Of <IVsCfg>(MockBehavior.Strict), Mock.Of <IVsCfg>(MockBehavior.Strict), 0, 0, 0);

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

            Assert.Equal(update.workspaceProject.Id, SomeWorkspaceProject.Id);
            Assert.Same(update.projectSnapshot, projectSnapshots[0]);
        }
示例#18
0
        public async Task WorkspaceChanged_ProjectEvents_EnqueuesUpdatesForDependentProjects(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue)
            {
                NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false),
            };

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);

            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.ProjectAdded(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
                projectManager.ProjectAdded(HostProjectThree);
            }, CancellationToken.None).ConfigureAwait(false);

            // Initialize with a project. This will get removed.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithOneProject);

            detector.Workspace_WorkspaceChanged(Workspace, e);
            detector.NotifyWorkspaceChangedEventComplete.Wait();
            detector.NotifyWorkspaceChangedEventComplete.Reset();

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithOneProject, newSolution: SolutionWithDependentProject);

            var solution = SolutionWithDependentProject.WithProjectAssemblyName(ProjectNumberThree.Id, "Changed");

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithDependentProject, newSolution: solution, projectId: ProjectNumberThree.Id);

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

            // Assert
            Assert.Equal(3, WorkQueueTestAccessor.Work.Count);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberOne.FilePath);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberTwo.FilePath);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberThree.FilePath);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();
            Assert.Empty(WorkQueueTestAccessor.Work);
        }
示例#19
0
        public void ProjectOperations_EndBuild_BuildFailed_Noops()
        {
            // Arrange
            var args           = new BuildEventArgs(monitor: null, success: false);
            var projectService = new Mock <TextBufferProjectService>();

            projectService.Setup(p => p.IsSupportedProject(null)).Throws <InvalidOperationException>();
            var projectManager = new Mock <ProjectSnapshotManagerBase>();

            projectManager.SetupGet(p => p.Workspace).Throws <InvalidOperationException>();
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var trigger = new ProjectBuildChangeTrigger(Dispatcher, projectService.Object, workspaceStateGenerator, projectManager.Object);

            // Act
            trigger.ProjectOperations_EndBuild(null, args);

            // Assert
            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
        public async Task ProjectOperations_EndBuild_UnsupportedProject_Noops()
        {
            // Arrange
            var args           = new BuildEventArgs(monitor: null, success: true);
            var projectService = new Mock <TextBufferProjectService>(MockBehavior.Strict);

            projectService.Setup(p => p.IsSupportedProject(null)).Returns(false);
            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Throws <InvalidOperationException>();
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var trigger = new ProjectBuildChangeTrigger(Dispatcher, projectService.Object, workspaceStateGenerator, projectManager.Object);

            // Act
            await trigger.HandleEndBuildAsync(args);

            // Assert
            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
示例#21
0
        public void WorkspaceChanged_ProjectAddedEvent_AddsProject()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectThree);

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

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberThree.Id, p.workspaceProject.Id));
        }
        public void UpdateProjectCfg_Done_WithoutWorkspaceProject_DoesNotEnqueueUpdate()
        {
            // Arrange
            uint cookie;
            var  buildManager = new Mock <IVsSolutionBuildManager>(MockBehavior.Strict);

            buildManager
            .Setup(b => b.AdviseUpdateSolutionEvents(It.IsAny <VsSolutionUpdatesProjectSnapshotChangeTrigger>(), out cookie))
            .Returns(VSConstants.S_OK);

            var services = new Mock <IServiceProvider>(MockBehavior.Strict);

            services.Setup(s => s.GetService(It.Is <Type>(f => f == typeof(SVsSolutionBuildManager)))).Returns(buildManager.Object);
            var projectSnapshot = new DefaultProjectSnapshot(
                ProjectState.Create(
                    Workspace.Services,
                    new HostProject("/Some/Unknown/Path.csproj", RazorConfiguration.Default, "Path")));
            var expectedProjectPath = projectSnapshot.FilePath;

            var projectService = new Mock <TextBufferProjectService>(MockBehavior.Strict);

            projectService.Setup(p => p.GetProjectPath(It.IsAny <IVsHierarchy>())).Returns(expectedProjectPath);

            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Returns(Workspace);
            projectManager
            .Setup(p => p.GetLoadedProject(expectedProjectPath))
            .Returns(projectSnapshot);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();

            var trigger = new VsSolutionUpdatesProjectSnapshotChangeTrigger(services.Object, projectService.Object, workspaceStateGenerator);

            trigger.Initialize(projectManager.Object);

            // Act
            trigger.UpdateProjectCfg_Done(Mock.Of <IVsHierarchy>(MockBehavior.Strict), Mock.Of <IVsCfg>(MockBehavior.Strict), Mock.Of <IVsCfg>(MockBehavior.Strict), 0, 0, 0);

            // Assert
            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
示例#23
0
        public void WorkspaceChanged_SolutionEvents_EnqueuesUpdatesForProjectsInSolution(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            projectManager.ProjectAdded(HostProjectTwo);

            var e = new WorkspaceChangeEventArgs(kind, oldSolution: EmptySolution, newSolution: SolutionWithTwoProjects);

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberOne.Id, p.workspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.workspaceProject.Id));
        }
示例#24
0
        public void WorkspaceChanged_ProjectRemovedEvent_QueuesProjectStateRemoval()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            projectManager.ProjectAdded(HostProjectTwo);

            var solution = SolutionWithTwoProjects.RemoveProject(ProjectNumberOne.Id);
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.ProjectRemoved, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

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

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Null(p.workspaceProject));
        }
        public async Task ProjectOperations_EndBuild_UntrackedProject_NoopsAsync()
        {
            // Arrange
            var projectService = CreateProjectService(SomeProject.FilePath);

            var args = new BuildEventArgs(monitor: null, success: true);

            var projectManager = new Mock <ProjectSnapshotManagerBase>(MockBehavior.Strict);

            projectManager.SetupGet(p => p.Workspace).Returns(Workspace);
            projectManager
            .Setup(p => p.GetLoadedProject(SomeProject.FilePath))
            .Returns <ProjectSnapshot>(null);
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var trigger = new ProjectBuildChangeTrigger(Dispatcher, projectService, workspaceStateGenerator, projectManager.Object);

            // Act
            await trigger.HandleEndBuildAsync(args);

            // Assert
            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
示例#26
0
        public async Task IsPartialComponentClass_NonClass_ReturnsFalse()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var sourceText     = SourceText.From(string.Empty);
            var syntaxTreeRoot = CSharpSyntaxTree.ParseText(sourceText).GetRoot();
            var solution       = SolutionWithTwoProjects
                                 .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                                 .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // Initialize document
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            // Act
            var result = detector.IsPartialComponentClass(document);

            // Assert
            Assert.False(result);
        }