public void ProjectSnapshotHandleProxy_RoundTripsProperly()
        {
            // Arrange
            var tagHelpers = new[]
            {
                TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build(),
                TagHelperDescriptorBuilder.Create("TestTagHelper2", "TestAssembly2").Build(),
            };
            var projectWorkspaceState = new ProjectWorkspaceState(tagHelpers);
            var expectedConfiguration = RazorConfiguration.Default;
            var expectedRootNamespace = "project";
            var handle = new ProjectSnapshotHandleProxy(new Uri("vsls://some/path/project.csproj"), RazorConfiguration.Default, expectedRootNamespace, projectWorkspaceState);
            var converterCollection = new JsonConverterCollection();

            converterCollection.RegisterRazorLiveShareConverters();
            var converters       = converterCollection.ToArray();
            var serializedHandle = JsonConvert.SerializeObject(handle, converters);

            // Act
            var deserializedHandle = JsonConvert.DeserializeObject <ProjectSnapshotHandleProxy>(serializedHandle, converters);

            // Assert
            Assert.Equal("vsls://some/path/project.csproj", deserializedHandle.FilePath.ToString());
            Assert.Equal(projectWorkspaceState, deserializedHandle.ProjectWorkspaceState);
            Assert.Equal(expectedConfiguration.ConfigurationName, deserializedHandle.Configuration.ConfigurationName);
            Assert.Equal(expectedConfiguration.Extensions.Count, deserializedHandle.Configuration.Extensions.Count);
            Assert.Equal(expectedConfiguration.LanguageVersion, deserializedHandle.Configuration.LanguageVersion);
            Assert.Equal(expectedRootNamespace, deserializedHandle.RootNamespace);
        }
Esempio n. 2
0
        public async Task ProjectAdded_PublishesToCorrectFilePathAsync()
        {
            // Arrange
            var serializationSuccessful       = false;
            var expectedConfigurationFilePath = "/path/to/obj/bin/Debug/project.razor.json";

            var publisher = new TestDefaultRazorProjectChangePublisher(
                ProjectConfigurationFilePathStore,
                _razorLogger,
                onSerializeToFile: (snapshot, configurationFilePath) =>
            {
                Assert.Equal(expectedConfigurationFilePath, configurationFilePath);
                serializationSuccessful = true;
            })
            {
                _active = true,
            };

            publisher.Initialize(ProjectSnapshotManager);
            var projectFilePath = "/path/to/project.csproj";
            var hostProject     = new HostProject(projectFilePath, RazorConfiguration.Default, "TestRootNamespace");

            ProjectConfigurationFilePathStore.Set(hostProject.FilePath, expectedConfigurationFilePath);
            var projectWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), CodeAnalysis.CSharp.LanguageVersion.Default);

            // Act
            await RunOnDispatcherThreadAsync(() =>
            {
                ProjectSnapshotManager.ProjectAdded(hostProject);
                ProjectSnapshotManager.ProjectWorkspaceStateChanged(projectFilePath, projectWorkspaceState);
            }).ConfigureAwait(false);

            // Assert
            Assert.True(serializationSuccessful);
        }
        public DefaultProjectWorkspaceStateGeneratorTest()
        {
            var tagHelperResolver = new TestTagHelperResolver();

            tagHelperResolver.TagHelpers.Add(TagHelperDescriptorBuilder.Create("ResolvableTagHelper", "TestAssembly").Build());
            ResolvableTagHelpers = tagHelperResolver.TagHelpers;
            var languageServices = new List <ILanguageService>()
            {
                tagHelperResolver
            };
            var testServices = TestServices.Create(languageServices);

            Workspace = TestWorkspace.Create(testServices);
            var projectId = ProjectId.CreateNewId("Test");
            var solution  = Workspace.CurrentSolution.AddProject(ProjectInfo.Create(
                                                                     projectId,
                                                                     VersionStamp.Default,
                                                                     "Test",
                                                                     "Test",
                                                                     LanguageNames.CSharp,
                                                                     TestProjectData.SomeProject.FilePath));

            WorkspaceProject = solution.GetProject(projectId);
            ProjectSnapshot  = new DefaultProjectSnapshot(ProjectState.Create(Workspace.Services, TestProjectData.SomeProject));
            ProjectWorkspaceStateWithTagHelpers = new ProjectWorkspaceState(new[]
            {
                TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build(),
            });
        }
Esempio n. 4
0
        public async Task ProjectAdded_DoesNotFireWhenNotReadyAsync()
        {
            // Arrange
            var serializationSuccessful       = false;
            var expectedConfigurationFilePath = @"C:\path\to\obj\bin\Debug\project.razor.json";

            var publisher = new TestProjectRazorJsonPublisher(
                ProjectConfigurationFilePathStore,
                onSerializeToFile: (snapshot, configurationFilePath) =>
            {
                Assert.Equal(expectedConfigurationFilePath, configurationFilePath);
                serializationSuccessful = true;
            },
                shouldSerialize: false)
            {
                _active = true,
            };

            publisher.Initialize(ProjectSnapshotManager);
            var projectFilePath = @"C:\path\to\project.csproj";
            var hostProject     = new HostProject(projectFilePath, RazorConfiguration.Default, "TestRootNamespace");

            ProjectConfigurationFilePathStore.Set(hostProject.FilePath, expectedConfigurationFilePath);
            var projectWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), CodeAnalysis.CSharp.LanguageVersion.Default);

            // Act
            await RunOnDispatcherThreadAsync(() =>
            {
                ProjectSnapshotManager.ProjectAdded(hostProject);
                ProjectSnapshotManager.ProjectWorkspaceStateChanged(projectFilePath, projectWorkspaceState);
            }).ConfigureAwait(false);

            // Assert
            Assert.False(serializationSuccessful);
        }
        public DefaultProjectSnapshotManagerProxyTest()
        {
            var joinableTaskContext = new JoinableTaskContextNode(new JoinableTaskContext());

            JoinableTaskFactory = new JoinableTaskFactory(joinableTaskContext.Context);
            Workspace           = TestWorkspace.Create();
            var projectWorkspaceState1 = new ProjectWorkspaceState(new[]
            {
                TagHelperDescriptorBuilder.Create("test1", "TestAssembly1").Build(),
            });

            ProjectSnapshot1 = new DefaultProjectSnapshot(
                ProjectState.Create(
                    Workspace.Services,
                    new HostProject("/host/path/to/project1.csproj", RazorConfiguration.Default, "project1"),
                    projectWorkspaceState1));
            var projectWorkspaceState2 = new ProjectWorkspaceState(new[]
            {
                TagHelperDescriptorBuilder.Create("test2", "TestAssembly2").Build(),
            });

            ProjectSnapshot2 = new DefaultProjectSnapshot(
                ProjectState.Create(
                    Workspace.Services,
                    new HostProject("/host/path/to/project2.csproj", RazorConfiguration.Default, "project2"),
                    projectWorkspaceState2));
        }
        public static TestProjectSnapshot Create(
            string filePath,
            string[] documentFilePaths,
            RazorConfiguration configuration,
            ProjectWorkspaceState projectWorkspaceState)
        {
            var workspaceServices = new List <IWorkspaceService>()
            {
                new TestProjectSnapshotProjectEngineFactory(),
            };
            var languageServices = new List <ILanguageService>();

            var hostServices = TestServices.Create(workspaceServices, languageServices);
            var workspace    = TestWorkspace.Create(hostServices);
            var hostProject  = new HostProject(filePath, configuration, "TestRootNamespace");
            var state        = ProjectState.Create(workspace.Services, hostProject);

            foreach (var documentFilePath in documentFilePaths)
            {
                var hostDocument = new HostDocument(documentFilePath, documentFilePath);
                state = state.WithAddedHostDocument(hostDocument, () => Task.FromResult(TextAndVersion.Create(SourceText.From(string.Empty), VersionStamp.Default)));
            }

            if (projectWorkspaceState != null)
            {
                state = state.WithProjectWorkspaceState(projectWorkspaceState);
            }

            var testProject = new TestProjectSnapshot(state);

            return(testProject);
        }
        private ProjectSnapshotHandleProxy ConvertToProxy(ProjectSnapshot project)
        {
            var projectWorkspaceState = new ProjectWorkspaceState(project.TagHelpers);
            var projectFilePath       = _session.ConvertLocalPathToSharedUri(project.FilePath);
            var projectHandleProxy    = new ProjectSnapshotHandleProxy(projectFilePath, project.Configuration, project.RootNamespace, projectWorkspaceState);

            return(projectHandleProxy);
        }
        protected OmniSharpProjectSnapshot CreateProjectSnapshot(string projectFilePath, string[] documentFilePaths)
        {
            var projectWorkspaceState    = new ProjectWorkspaceState(ImmutableArray <TagHelperDescriptor> .Empty, CodeAnalysis.CSharp.LanguageVersion.Default);
            var projectSnapshot          = _createWithDocumentsTestProjectSnapshotMethod.Invoke(null, new object[] { projectFilePath, documentFilePaths, projectWorkspaceState });
            var omniSharpProjectSnapshot = (OmniSharpProjectSnapshot)_omniSharpSnapshotConstructor.Invoke(new[] { projectSnapshot });

            return(omniSharpProjectSnapshot);
        }
Esempio n. 9
0
        public override void UpdateProject(
            string filePath,
            RazorConfiguration configuration,
            string rootNamespace,
            ProjectWorkspaceState projectWorkspaceState,
            IReadOnlyList <DocumentSnapshotHandle> documents)
        {
            _foregroundDispatcher.AssertForegroundThread();

            var normalizedPath = _filePathNormalizer.Normalize(filePath);
            var project        = (DefaultProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(normalizedPath);

            if (project == null)
            {
                // Never tracked the project to begin with, noop.
                _logger.LogInformation($"Failed to update untracked project '{filePath}'.");
                return;
            }

            UpdateProjectDocuments(documents, project.FilePath);

            if (!projectWorkspaceState.Equals(ProjectWorkspaceState.Default))
            {
                _logger.LogInformation($"Updating project '{filePath}' TagHelpers ({projectWorkspaceState.TagHelpers.Count}) and C# Language Version ({projectWorkspaceState.CSharpLanguageVersion}).");
            }

            _projectSnapshotManagerAccessor.Instance.ProjectWorkspaceStateChanged(project.FilePath, projectWorkspaceState);

            var currentHostProject   = project.HostProject;
            var currentConfiguration = currentHostProject.Configuration;

            if (currentConfiguration.ConfigurationName == configuration?.ConfigurationName &&
                currentHostProject.RootNamespace == rootNamespace)
            {
                _logger.LogTrace($"Updating project '{filePath}'. The project is already using configuration '{configuration.ConfigurationName}' and root namespace '{rootNamespace}'.");
                return;
            }

            if (configuration == null)
            {
                configuration = RazorDefaults.Configuration;
                _logger.LogInformation($"Updating project '{filePath}' to use Razor's default configuration ('{configuration.ConfigurationName}')'.");
            }
            else if (currentConfiguration.ConfigurationName != configuration.ConfigurationName)
            {
                _logger.LogInformation($"Updating project '{filePath}' to Razor configuration '{configuration.ConfigurationName}' with language version '{configuration.LanguageVersion}'.");
            }

            if (currentHostProject.RootNamespace != rootNamespace)
            {
                _logger.LogInformation($"Updating project '{filePath}''s root namespace to '{rootNamespace}'.");
            }

            var hostProject = new HostProject(project.FilePath, configuration, rootNamespace);

            _projectSnapshotManagerAccessor.Instance.ProjectConfigurationChanged(hostProject);
        }
Esempio n. 10
0
        public ProjectSnapshotSynchronizationServiceTest()
        {
            var joinableTaskContext = new JoinableTaskContextNode(new JoinableTaskContext());

            JoinableTaskFactory = new JoinableTaskFactory(joinableTaskContext.Context);

            SessionContext = new TestCollaborationSession(isHost: false);

            ProjectSnapshotManager = new TestProjectSnapshotManager(Workspace);

            ProjectWorkspaceStateWithTagHelpers = new ProjectWorkspaceState(new[]
            {
                TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build()
            });
        }
 public SerializationTest()
 {
     var languageVersion = RazorLanguageVersion.Experimental;
     var extensions = new RazorExtension[]
     {
         new SerializedRazorExtension("TestExtension"),
     };
     Configuration = RazorConfiguration.Create(languageVersion, "Custom", extensions);
     ProjectWorkspaceState = new ProjectWorkspaceState(new[]
     {
         TagHelperDescriptorBuilder.Create("Test", "TestAssembly").Build(),
     },
     LanguageVersion.LatestMajor);
     var converterCollection = new JsonConverterCollection();
     converterCollection.RegisterRazorConverters();
     Converters = converterCollection.ToArray();
 }
        public ProjectSnapshotSynchronizationServiceTest()
        {
            var joinableTaskContext = new JoinableTaskContextNode(new JoinableTaskContext());

            JoinableTaskFactory = new JoinableTaskFactory(joinableTaskContext.Context);

            var collabSession = new TestCollaborationSession(isHost: false);

            SessionAccessor = Mock.Of <LiveShareSessionAccessor>(accessor => accessor.IsGuestSessionActive == true && accessor.Session == collabSession);

            ProjectSnapshotManager = new TestProjectSnapshotManager(Workspace);

            ProjectWorkspaceStateWithTagHelpers = new ProjectWorkspaceState(new[]
            {
                TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build()
            });
        }
        public void UpdateProject_UpdatesProjectWorkspaceState()
        {
            // Arrange
            var projectManager = TestProjectSnapshotManager.Create(Dispatcher);
            var hostProject    = new HostProject("/path/to/project.csproj", RazorConfiguration.Default, "TestRootNamespace");

            projectManager.ProjectAdded(hostProject);
            var projectService        = CreateProjectService(Mock.Of <ProjectResolver>(), projectManager);
            var projectWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), LanguageVersion.LatestMajor);

            // Act
            projectService.UpdateProject(hostProject.FilePath, hostProject.Configuration, hostProject.RootNamespace, projectWorkspaceState, EmptyDocuments);

            // Assert
            var project = projectManager.GetLoadedProject(hostProject.FilePath);

            Assert.Same(projectWorkspaceState, project.ProjectWorkspaceState);
        }
        public ProjectSnapshotHandleProxy(
            Uri filePath,
            RazorConfiguration configuration,
            ProjectWorkspaceState projectWorkspaceState)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

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

            FilePath              = filePath;
            Configuration         = configuration;
            ProjectWorkspaceState = projectWorkspaceState;
        }
        public void ProjectChanged_ProcessesNotifications_AndGoesBackToSleep()
        {
            // Arrange
            var projectManager = TestProjectSnapshotManager.Create(Dispatcher);

            projectManager.ProjectAdded(HostProject1);
            projectManager.ProjectAdded(HostProject2);
            projectManager.DocumentAdded(HostProject1, Documents[0], null);
            projectManager.DocumentOpened(HostProject1.FilePath, Documents[0].FilePath, SourceText.From(string.Empty));
            projectManager.AllowNotifyListeners = true;

            var queue = new TestOpenDocumentGenerator(Dispatcher)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart      = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkStarting  = new ManualResetEventSlim(initialState: false),
                BlockBackgroundWorkCompleting = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false),
            };

            queue.Initialize(projectManager);

            var newWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), LanguageVersion.CSharp7_3);


            // Act & Assert
            projectManager.ProjectWorkspaceStateChanged(HostProject1.FilePath, newWorkspaceState);

            Assert.True(queue.IsScheduledOrRunning, "Queue should be scheduled during Enqueue");
            Assert.True(queue.HasPendingNotifications, "Queue should have a notification created during Enqueue");

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();
            queue.BlockBackgroundWorkCompleting.Set();

            Assert.True(queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3)));

            Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted");
            Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications");
        }
        public async Task ProjectAdded_DoesNotFireWhenNotReadyAsync()
        {
            // Arrange
            var serializationSuccessful       = false;
            var expectedConfigurationFilePath = "/path/to/obj/bin/Debug/project.razor.json";

            var publisher = new TestDefaultRazorProjectChangePublisher(
                ProjectConfigurationFilePathStore,
                RazorLogger,
                onSerializeToFile: (snapshot, configurationFilePath) =>
            {
                Assert.Equal(expectedConfigurationFilePath, configurationFilePath);
                serializationSuccessful = true;
            },
                shouldSerialize: false)
            {
                _active = true,
            };

            publisher.Initialize(ProjectSnapshotManager);
            var projectFilePath = "/path/to/project.csproj";
            var hostProject     = new HostProject(projectFilePath, RazorConfiguration.Default, "TestRootNamespace");

            ProjectConfigurationFilePathStore.Set(hostProject.FilePath, expectedConfigurationFilePath);
            var projectWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), CodeAnalysis.CSharp.LanguageVersion.Default);

            // Act
            await RunOnForegroundAsync(() =>
            {
                ProjectSnapshotManager.ProjectAdded(hostProject);
                ProjectSnapshotManager.ProjectWorkspaceStateChanged(projectFilePath, projectWorkspaceState);
            }).ConfigureAwait(false);

            // Assert
            var kvp = Assert.Single(publisher._deferredPublishTasks);
            await kvp.Value.ConfigureAwait(false);

            Assert.False(serializationSuccessful);
        }
        private DocumentSnapshot CreateRazorDocumentSnapshot(RazorProjectEngine projectEngine, TestRazorProjectItem item, string rootNamespaceName, IReadOnlyList <TagHelperDescriptor> tagHelpers)
        {
            var codeDocument = projectEngine.ProcessDesignTime(item);

            var namespaceNode = (NamespaceDeclarationIntermediateNode)codeDocument
                                .GetDocumentIntermediateNode()
                                .FindDescendantNodes <IntermediateNode>()
                                .FirstOrDefault(n => n is NamespaceDeclarationIntermediateNode);

            namespaceNode.Content = rootNamespaceName;

            var sourceText            = SourceText.From(new string(item.Content));
            var projectWorkspaceState = new ProjectWorkspaceState(tagHelpers, LanguageVersion.Default);
            var projectSnapshot       = TestProjectSnapshot.Create("C:/project.csproj", projectWorkspaceState);
            var documentSnapshot      = Mock.Of <DocumentSnapshot>(d =>
                                                                   d.GetGeneratedOutputAsync() == Task.FromResult(codeDocument) &&
                                                                   d.FilePath == item.FilePath &&
                                                                   d.FileKind == FileKinds.Component &&
                                                                   d.GetTextAsync() == Task.FromResult(sourceText) &&
                                                                   d.Project == projectSnapshot, MockBehavior.Strict);

            return(documentSnapshot);
        }
        public FullProjectSnapshotHandle(
            string filePath,
            RazorConfiguration configuration,
            string rootNamespace,
            ProjectWorkspaceState projectWorkspaceState,
            IReadOnlyList <DocumentSnapshotHandle> documents)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

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

            FilePath              = filePath;
            Configuration         = configuration;
            RootNamespace         = rootNamespace;
            ProjectWorkspaceState = projectWorkspaceState;
            Documents             = documents;
        }
        public async Task ProjectAdded_PublishesToCorrectFilePathAsync()
        {
            // Arrange
            var snapshotManager         = CreateProjectSnapshotManager(allowNotifyListeners: true);
            var serializationSuccessful = false;
            var expectedPublishFilePath = "/path/to/obj/bin/Debug/project.razor.json";

            var publisher = new TestDefaultRazorProjectChangePublisher(
                JoinableTaskContext,
                RazorLogger,
                onSerializeToFile: (snapshot, publishFilePath) =>
            {
                Assert.Equal(expectedPublishFilePath, publishFilePath);
                serializationSuccessful = true;
            });

            publisher.Initialize(snapshotManager);
            var projectFilePath = "/path/to/project.csproj";
            var hostProject     = new HostProject(projectFilePath, RazorConfiguration.Default, "TestRootNamespace");

            publisher.SetPublishFilePath(hostProject.FilePath, expectedPublishFilePath);
            var projectWorkspaceState = new ProjectWorkspaceState(Array.Empty <TagHelperDescriptor>(), CodeAnalysis.CSharp.LanguageVersion.Default);

            // Act
            await RunOnForegroundAsync(() =>
            {
                snapshotManager.ProjectAdded(hostProject);
                snapshotManager.ProjectWorkspaceStateChanged(projectFilePath, projectWorkspaceState);
            }).ConfigureAwait(false);

            // Assert
            var kvp = Assert.Single(publisher._deferredPublishTasks);
            await kvp.Value.ConfigureAwait(false);

            Assert.True(serializationSuccessful);
        }
Esempio n. 20
0
        internal static ProjectSnapshot CreateProjectSnapshot(string projectFilePath, ProjectWorkspaceState projectWorkspaceState = null, string[] documentFilePaths = null)
        {
            if (documentFilePaths is null)
            {
                documentFilePaths = Array.Empty <string>();
            }

            var testProjectSnapshot = TestProjectSnapshot.Create(projectFilePath, documentFilePaths, projectWorkspaceState);

            return(testProjectSnapshot);
        }
 public abstract void ProjectWorkspaceStateChanged(string projectFilePath, ProjectWorkspaceState projectWorkspaceState);
 public abstract void UpdateProject(
     string filePath,
     RazorConfiguration configuration,
     string rootNamespace,
     ProjectWorkspaceState projectWorkspaceState,
     IReadOnlyList <DocumentSnapshotHandle> documents);
Esempio n. 23
0
 public static TestProjectSnapshot Create(string filePath, string[] documentFilePaths, ProjectWorkspaceState projectWorkspaceState = null) =>
 Create(filePath, documentFilePaths, RazorConfiguration.Default, projectWorkspaceState);
Esempio n. 24
0
 public static TestProjectSnapshot Create(string filePath, ProjectWorkspaceState projectWorkspaceState = null) => Create(filePath, Array.Empty <string>(), projectWorkspaceState);
        internal ProjectSnapshot CreateProjectSnapshot(string projectFilePath, ProjectWorkspaceState projectWorkspaceState = null)
        {
            var testProjectSnapshot = TestProjectSnapshot.Create(projectFilePath, projectWorkspaceState);

            return(testProjectSnapshot);
        }
Esempio n. 26
0
        private void ReportWorkspaceStateChange(string projectFilePath, ProjectWorkspaceState workspaceStateChange)
        {
            _foregroundDispatcher.AssertForegroundThread();

            _projectManager.ProjectWorkspaceStateChanged(projectFilePath, workspaceStateChange);
        }
Esempio n. 27
0
 public override void ProjectWorkspaceStateChanged(string projectFilePath, ProjectWorkspaceState projectWorkspaceState)
 {
     InternalProjectSnapshotManager.ProjectWorkspaceStateChanged(projectFilePath, projectWorkspaceState);
 }
Esempio n. 28
0
 public static TestProjectSnapshot Create(string filePath, ProjectWorkspaceState projectWorkspaceState = null) => Create(filePath, new string[0], projectWorkspaceState);
Esempio n. 29
0
        private async Task UpdateWorkspaceStateAsync(Project workspaceProject, ProjectSnapshot projectSnapshot, CancellationToken cancellationToken)
        {
            try
            {
                _foregroundDispatcher.AssertBackgroundThread();

                OnStartingBackgroundWork();

                if (cancellationToken.IsCancellationRequested)
                {
                    // Silently cancel, we're the only ones creating these tasks.
                    return;
                }

                var workspaceState = ProjectWorkspaceState.Default;
                try
                {
                    if (workspaceProject != null)
                    {
                        var tagHelperResolutionResult = await _tagHelperResolver.GetTagHelpersAsync(workspaceProject, projectSnapshot, cancellationToken);

                        workspaceState = new ProjectWorkspaceState(tagHelperResolutionResult.Descriptors);
                    }
                }
                catch (Exception ex)
                {
                    await Task.Factory.StartNew(
                        () => _projectManager.ReportError(ex, projectSnapshot),
                        CancellationToken.None, // Don't allow errors to be cancelled
                        TaskCreationOptions.None,
                        _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false);

                    return;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    // Silently cancel, we're the only ones creating these tasks.
                    return;
                }

                await Task.Factory.StartNew(
                    () =>
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    ReportWorkspaceStateChange(projectSnapshot.FilePath, workspaceState);
                },
                    cancellationToken,
                    TaskCreationOptions.None,
                    _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                // This is something totally unexpected, let's just send it over to the project manager.
                await Task.Factory.StartNew(
                    () => _projectManager.ReportError(ex),
                    CancellationToken.None, // Don't allow errors to be cancelled
                    TaskCreationOptions.None,
                    _foregroundDispatcher.ForegroundScheduler).ConfigureAwait(false);
            }

            OnBackgroundWorkCompleted();
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType != JsonToken.StartObject)
            {
                return(null);
            }

            string                serializationFormat   = null;
            string                filePath              = null;
            RazorConfiguration    configuration         = null;
            string                rootNamespace         = null;
            ProjectWorkspaceState projectWorkspaceState = null;

            DocumentSnapshotHandle[] documents = null;

            reader.ReadProperties(propertyName =>
            {
                switch (propertyName)
                {
                case SerializationFormatPropertyName:
                    if (reader.Read())
                    {
                        serializationFormat = (string)reader.Value;
                    }
                    break;

                case nameof(FullProjectSnapshotHandle.FilePath):
                    if (reader.Read())
                    {
                        filePath = (string)reader.Value;
                    }
                    break;

                case nameof(FullProjectSnapshotHandle.Configuration):
                    if (reader.Read())
                    {
                        configuration = RazorConfigurationJsonConverter.Instance.ReadJson(reader, objectType, existingValue, serializer) as RazorConfiguration;
                    }
                    break;

                case nameof(FullProjectSnapshotHandle.RootNamespace):
                    if (reader.Read())
                    {
                        rootNamespace = (string)reader.Value;
                    }
                    break;

                case nameof(FullProjectSnapshotHandle.ProjectWorkspaceState):
                    if (reader.Read())
                    {
                        projectWorkspaceState = serializer.Deserialize <ProjectWorkspaceState>(reader);
                    }
                    break;

                case nameof(FullProjectSnapshotHandle.Documents):
                    if (reader.Read())
                    {
                        documents = serializer.Deserialize <DocumentSnapshotHandle[]>(reader);
                    }
                    break;
                }
            });

            // We need to add a serialization format to the project response to indicate that this version of the code is compatible with what's being serialized.
            // This scenario typically happens when a user has an incompatible serialized project snapshot but is using the latest Razor bits.

            if (string.IsNullOrEmpty(serializationFormat) || serializationFormat != ProjectSerializationFormat.Version)
            {
                // Unknown serialization format.
                return(null);
            }

            return(new FullProjectSnapshotHandle(filePath, configuration, rootNamespace, projectWorkspaceState, documents));
        }