public void Dispose() { Debug.Assert(!_disposed); _disposed = true; _workspace.Dispose(); _workspace = null; }
public void TestPreviewProjectChanges() { using (var previewWorkspace = new PreviewWorkspace()) { var solution = previewWorkspace.CurrentSolution; var project = solution.AddProject("project", "project.dll", LanguageNames.CSharp); Assert.True(previewWorkspace.TryApplyChanges(project.Solution)); var addedSolution = previewWorkspace.CurrentSolution.Projects.First() .AddMetadataReference(TestReferences.NetFx.v4_0_30319.mscorlib) .AddDocument("document", "").Project.Solution; Assert.True(previewWorkspace.TryApplyChanges(addedSolution)); Assert.Equal(1, previewWorkspace.CurrentSolution.Projects.First().MetadataReferences.Count); Assert.Equal(1, previewWorkspace.CurrentSolution.Projects.First().DocumentIds.Count); var text = "class C {}"; var changedSolution = previewWorkspace.CurrentSolution.Projects.First().Documents.First().WithText(SourceText.From(text)).Project.Solution; Assert.True(previewWorkspace.TryApplyChanges(changedSolution)); Assert.Equal(previewWorkspace.CurrentSolution.Projects.First().Documents.First().GetTextAsync().Result.ToString(), text); var removedSolution = previewWorkspace.CurrentSolution.Projects.First() .RemoveMetadataReference(previewWorkspace.CurrentSolution.Projects.First().MetadataReferences[0]) .RemoveDocument(previewWorkspace.CurrentSolution.Projects.First().DocumentIds[0]).Solution; Assert.True(previewWorkspace.TryApplyChanges(removedSolution)); Assert.Equal(0, previewWorkspace.CurrentSolution.Projects.First().MetadataReferences.Count); Assert.Equal(0, previewWorkspace.CurrentSolution.Projects.First().DocumentIds.Count); } }
public void TestPreviewCreationDefault() { using (var previewWorkspace = new PreviewWorkspace()) { Assert.NotNull(previewWorkspace.CurrentSolution); } }
public void TestPreviewCreationWithSolution() { using (var custom = new AdhocWorkspace()) using (var previewWorkspace = new PreviewWorkspace(custom.CurrentSolution)) { Assert.NotNull(previewWorkspace.CurrentSolution); } }
public void TestPreviewCreationWithExplicitHostServices() { var assembly = typeof(IWorkCoordinatorRegistrationService).Assembly; using (var previewWorkspace = new PreviewWorkspace(MefHostServices.Create(MefHostServices.DefaultAssemblies.Concat(assembly)))) { Assert.NotNull(previewWorkspace.CurrentSolution); } }
public void TestPreviewAddRemoveProject() { using (var previewWorkspace = new PreviewWorkspace()) { var solution = previewWorkspace.CurrentSolution; var project = solution.AddProject("project", "project.dll", LanguageNames.CSharp); Assert.True(previewWorkspace.TryApplyChanges(project.Solution)); var newSolution = previewWorkspace.CurrentSolution.RemoveProject(project.Id); Assert.True(previewWorkspace.TryApplyChanges(newSolution)); Assert.Equal(0, previewWorkspace.CurrentSolution.ProjectIds.Count); } }
public void TestPreviewDiagnostic() { var diagnosticService = EditorServicesUtil.ExportProvider.GetExportedValue<IDiagnosticAnalyzerService>() as IDiagnosticUpdateSource; var taskSource = new TaskCompletionSource<DiagnosticsUpdatedArgs>(); diagnosticService.DiagnosticsUpdated += (s, a) => taskSource.TrySetResult(a); using (var previewWorkspace = new PreviewWorkspace(MefV1HostServices.Create(EditorServicesUtil.ExportProvider.AsExportProvider()))) { var solution = previewWorkspace.CurrentSolution .AddProject("project", "project.dll", LanguageNames.CSharp) .AddDocument("document", "class { }") .Project .Solution; Assert.True(previewWorkspace.TryApplyChanges(solution)); previewWorkspace.OpenDocument(previewWorkspace.CurrentSolution.Projects.First().DocumentIds[0]); previewWorkspace.EnableDiagnostic(); // wait 20 seconds taskSource.Task.Wait(20000); Assert.True(taskSource.Task.IsCompleted); var args = taskSource.Task.Result; Assert.True(args.Diagnostics.Length > 0); } }
private Task<object> CreateChangedDocumentViewAsync(ITextBuffer oldBuffer, ITextBuffer newBuffer, string description, List<LineSpan> originalSpans, List<LineSpan> changedSpans, PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (!(originalSpans.Any() && changedSpans.Any())) { // Both line spans must be non-empty. Otherwise, below projection buffer factory API call will throw. // So if either is empty (signaling that there are no changes to preview in the document), then we bail out. // This can happen in cases where the user has already applied the fix and light bulb has already been dismissed, // but platform hasn't cancelled the preview operation yet. Since the light bulb has already been dismissed at // this point, the preview that we return will never be displayed to the user. So returning null here is harmless. return SpecializedTasks.Default<object>(); } var originalBuffer = _projectionBufferFactoryService.CreateProjectionBufferWithoutIndentation( _contentTypeRegistryService, _editorOptionsFactoryService.GlobalOptions, oldBuffer.CurrentSnapshot, "...", description, originalSpans.ToArray()); var changedBuffer = _projectionBufferFactoryService.CreateProjectionBufferWithoutIndentation( _contentTypeRegistryService, _editorOptionsFactoryService.GlobalOptions, newBuffer.CurrentSnapshot, "...", description, changedSpans.ToArray()); return CreateNewDifferenceViewerAsync(leftWorkspace, rightWorkspace, originalBuffer, changedBuffer, zoomLevel, cancellationToken); }
public Task<object> CreateChangedDocumentPreviewViewAsync(Document oldDocument, Document newDocument, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Note: We don't use the original buffer that is associated with oldDocument // (and currently open in the editor) for oldBuffer below. This is because oldBuffer // will be used inside a projection buffer inside our inline diff preview below // and platform's implementation currently has a bug where projection buffers // are being leaked. This leak means that if we use the original buffer that is // currently visible in the editor here, the projection buffer span calculation // would be triggered every time user changes some code in this buffer (even though // the diff view would long have been dismissed by the time user edits the code) // resulting in crashes. Instead we create a new buffer from the same content. // TODO: We could use ITextBufferCloneService instead here to clone the original buffer. var oldBuffer = CreateNewBuffer(oldDocument, cancellationToken); var newBuffer = CreateNewBuffer(newDocument, cancellationToken); // Convert the diffs to be line based. // Compute the diffs between the old text and the new. var diffResult = ComputeEditDifferences(oldDocument, newDocument, cancellationToken); // Need to show the spans in the right that are different. // We also need to show the spans that are in conflict. var originalSpans = GetOriginalSpans(diffResult, cancellationToken); var changedSpans = GetChangedSpans(diffResult, cancellationToken); var description = default(string); var allSpans = default(NormalizedSpanCollection); if (newDocument.SupportsSyntaxTree) { var newRoot = newDocument.GetSyntaxRootSynchronously(cancellationToken); var conflictNodes = newRoot.GetAnnotatedNodesAndTokens(ConflictAnnotation.Kind); var conflictSpans = conflictNodes.Select(n => n.Span.ToSpan()).ToList(); var conflictDescriptions = conflictNodes.SelectMany(n => n.GetAnnotations(ConflictAnnotation.Kind)) .Select(a => ConflictAnnotation.GetDescription(a)) .Distinct(); var warningNodes = newRoot.GetAnnotatedNodesAndTokens(WarningAnnotation.Kind); var warningSpans = warningNodes.Select(n => n.Span.ToSpan()).ToList(); var warningDescriptions = warningNodes.SelectMany(n => n.GetAnnotations(WarningAnnotation.Kind)) .Select(a => WarningAnnotation.GetDescription(a)) .Distinct(); var suppressDiagnosticsNodes = newRoot.GetAnnotatedNodesAndTokens(SuppressDiagnosticsAnnotation.Kind); var suppressDiagnosticsSpans = suppressDiagnosticsNodes.Select(n => n.Span.ToSpan()).ToList(); AttachAnnotationsToBuffer(newBuffer, conflictSpans, warningSpans, suppressDiagnosticsSpans); description = conflictSpans.Count == 0 && warningSpans.Count == 0 ? null : string.Join(Environment.NewLine, conflictDescriptions.Concat(warningDescriptions)); allSpans = new NormalizedSpanCollection(conflictSpans.Concat(warningSpans).Concat(changedSpans)); } else { allSpans = new NormalizedSpanCollection(changedSpans); } var originalLineSpans = CreateLineSpans(oldBuffer.CurrentSnapshot, originalSpans, cancellationToken); var changedLineSpans = CreateLineSpans(newBuffer.CurrentSnapshot, allSpans, cancellationToken); if (!originalLineSpans.Any()) { // This means that we have no differences (likely because of conflicts). // In such cases, use the same spans for the left (old) buffer as the right (new) buffer. originalLineSpans = changedLineSpans; } // Create PreviewWorkspaces around the buffers to be displayed on the left and right // so that all IDE services (colorizer, squiggles etc.) light up in these buffers. var leftDocument = oldDocument.Project .RemoveDocument(oldDocument.Id) .AddDocument(oldDocument.Name, oldBuffer.AsTextContainer().CurrentText, oldDocument.Folders, oldDocument.FilePath); var leftWorkspace = new PreviewWorkspace(leftDocument.Project.Solution); leftWorkspace.OpenDocument(leftDocument.Id); var rightWorkspace = new PreviewWorkspace( newDocument.WithText(newBuffer.AsTextContainer().CurrentText).Project.Solution); rightWorkspace.OpenDocument(newDocument.Id); return CreateChangedDocumentViewAsync( oldBuffer, newBuffer, description, originalLineSpans, changedLineSpans, leftWorkspace, rightWorkspace, zoomLevel, cancellationToken); }
private Task<object> CreateRemovedDocumentPreviewViewCoreAsync(ITextBuffer oldBuffer, PreviewWorkspace workspace, TextDocument document, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var firstLine = string.Format(EditorFeaturesResources.Removing_0_from_1_with_content_colon, document.Name, document.Project.Name); var span = new SnapshotSpan(oldBuffer.CurrentSnapshot, Span.FromBounds(0, oldBuffer.CurrentSnapshot.Length)) .CreateTrackingSpan(SpanTrackingMode.EdgeExclusive); var originalBuffer = _projectionBufferFactoryService.CreatePreviewProjectionBuffer( sourceSpans: new List<object> { firstLine, "\r\n", span }, registryService: _contentTypeRegistryService); var changedBuffer = _projectionBufferFactoryService.CreatePreviewProjectionBuffer( sourceSpans: new List<object> { firstLine, "\r\n" }, registryService: _contentTypeRegistryService); return CreateNewDifferenceViewerAsync(workspace, null, originalBuffer, changedBuffer, zoomLevel, cancellationToken); }
public void TestPreviewOpenCloseFile() { using (var previewWorkspace = new PreviewWorkspace()) { var solution = previewWorkspace.CurrentSolution; var project = solution.AddProject("project", "project.dll", LanguageNames.CSharp); var document = project.AddDocument("document", ""); Assert.True(previewWorkspace.TryApplyChanges(document.Project.Solution)); previewWorkspace.OpenDocument(document.Id); Assert.Equal(1, previewWorkspace.GetOpenDocumentIds().Count()); Assert.True(previewWorkspace.IsDocumentOpen(document.Id)); previewWorkspace.CloseDocument(document.Id); Assert.Equal(0, previewWorkspace.GetOpenDocumentIds().Count()); Assert.False(previewWorkspace.IsDocumentOpen(document.Id)); } }
public void TestPreviewDiagnosticTagger() { using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromLines("class { }")) using (var previewWorkspace = new PreviewWorkspace(workspace.CurrentSolution)) { //// preview workspace and owner of the solution now share solution and its underlying text buffer var hostDocument = workspace.Projects.First().Documents.First(); //// enable preview diagnostics previewWorkspace.EnableDiagnostic(); var spans = SquiggleUtilities.GetErrorSpans(workspace); Assert.Equal(1, spans.Count); } }
public async Task TestPreviewDiagnosticTagger() { using (var workspace = await TestWorkspace.CreateCSharpAsync("class { }")) using (var previewWorkspace = new PreviewWorkspace(workspace.CurrentSolution)) { //// preview workspace and owner of the solution now share solution and its underlying text buffer var hostDocument = workspace.Projects.First().Documents.First(); //// enable preview diagnostics previewWorkspace.EnableDiagnostic(); var diagnosticsAndErrorsSpans = await SquiggleUtilities.GetDiagnosticsAndErrorSpans(workspace); const string AnalzyerCount = "Analyzer Count: "; Assert.Equal(AnalzyerCount + 1, AnalzyerCount + diagnosticsAndErrorsSpans.Item1.Length); const string SquigglesCount = "Squiggles Count: "; Assert.Equal(SquigglesCount + 1, SquigglesCount + diagnosticsAndErrorsSpans.Item2.Count); } }
private DisposableToolTip CreateDisposableToolTip() { Presenter.AssertIsForeground(); // Create a new buffer that we'll show a preview for. We can't search for an // existing buffer because: // 1. the file may not be open. // 2. our results may not be in sync with what's actually in the editor. var textBuffer = CreateNewBuffer(); // Create the actual tooltip around the region of that text buffer we want to show. var toolTip = new ToolTip { Content = CreateToolTipContent(textBuffer), Background = (Brush)Application.Current.Resources[EnvironmentColors.ToolWindowBackgroundBrushKey] }; // Create a preview workspace for this text buffer and open it's corresponding // document. That way we'll get nice things like classification as well as the // reference highlight span. var newDocument = Document.WithText(textBuffer.AsTextContainer().CurrentText); var workspace = new PreviewWorkspace(newDocument.Project.Solution); workspace.OpenDocument(newDocument.Id); return new DisposableToolTip(toolTip, workspace); }
private async Task<object> CreateNewDifferenceViewerAsync( PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // leftWorkspace can be null if the change is adding a document. // rightWorkspace can be null if the change is removing a document. // However both leftWorkspace and rightWorkspace can't be null at the same time. Contract.ThrowIfTrue((leftWorkspace == null) && (rightWorkspace == null)); var diffBuffer = _differenceBufferService.CreateDifferenceBuffer( originalBuffer, changedBuffer, new StringDifferenceOptions(), disableEditing: true); var diffViewer = _differenceViewerService.CreateDifferenceView(diffBuffer, _previewRoleSet); diffViewer.Closed += (s, e) => { // Workaround Editor bug. The editor has an issue where they sometimes crash when // trying to apply changes to projection buffer. So, when the user actually invokes // a SuggestedAction we may then edit a text buffer, which the editor will then // try to propagate through the projections we have here over that buffer. To ensure // that that doesn't happen, we clear out the projections first so that this crash // won't happen. originalBuffer.DeleteSpans(0, originalBuffer.CurrentSnapshot.SpanCount); changedBuffer.DeleteSpans(0, changedBuffer.CurrentSnapshot.SpanCount); leftWorkspace?.Dispose(); leftWorkspace = null; rightWorkspace?.Dispose(); rightWorkspace = null; }; const string DiffOverviewMarginName = "deltadifferenceViewerOverview"; if (leftWorkspace == null) { diffViewer.ViewMode = DifferenceViewMode.RightViewOnly; diffViewer.RightView.ZoomLevel *= zoomLevel; diffViewer.RightHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } else if (rightWorkspace == null) { diffViewer.ViewMode = DifferenceViewMode.LeftViewOnly; diffViewer.LeftView.ZoomLevel *= zoomLevel; diffViewer.LeftHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } else { diffViewer.ViewMode = DifferenceViewMode.Inline; diffViewer.InlineView.ZoomLevel *= zoomLevel; diffViewer.InlineHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } // Disable focus / tab stop for the diff viewer. diffViewer.RightView.VisualElement.Focusable = false; diffViewer.LeftView.VisualElement.Focusable = false; diffViewer.InlineView.VisualElement.Focusable = false; // This code path must be invoked on UI thread. AssertIsForeground(); // We use ConfigureAwait(true) to stay on the UI thread. await diffViewer.SizeToFitAsync().ConfigureAwait(true); leftWorkspace?.EnableDiagnostic(); rightWorkspace?.EnableDiagnostic(); return new DifferenceViewerPreview(diffViewer); }
public DisposableToolTip(ToolTip toolTip, PreviewWorkspace workspace) { ToolTip = toolTip; _workspace = workspace; }
public Task<object> CreateAddedAdditionalDocumentPreviewViewAsync(TextDocument document, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var newBuffer = CreateNewPlainTextBuffer(document, cancellationToken); // Create PreviewWorkspace around the buffer to be displayed in the diff preview // so that all IDE services (colorizer, squiggles etc.) light up in this buffer. var rightWorkspace = new PreviewWorkspace( document.Project.Solution.WithAdditionalDocumentText(document.Id, newBuffer.AsTextContainer().CurrentText)); rightWorkspace.OpenAdditionalDocument(document.Id); return CreateAddedDocumentPreviewViewCoreAsync(newBuffer, rightWorkspace, document, zoomLevel, cancellationToken); }
public void TestPreviewServices() { using (var previewWorkspace = new PreviewWorkspace(MefV1HostServices.Create(TestExportProvider.ExportProviderWithCSharpAndVisualBasic.AsExportProvider()))) { var workcoordinatorService = previewWorkspace.Services.GetService<IWorkCoordinatorRegistrationService>(); Assert.True(workcoordinatorService is PreviewWorkCoordinatorRegistrationService); var persistentService = previewWorkspace.Services.GetService<IPersistentStorageService>(); Assert.NotNull(persistentService); var storage = persistentService.GetStorage(previewWorkspace.CurrentSolution); Assert.True(storage is NoOpPersistentStorage); } }
public Task<object> CreateRemovedAdditionalDocumentPreviewViewAsync(TextDocument document, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Note: We don't use the original buffer that is associated with oldDocument // (and possibly open in the editor) for oldBuffer below. This is because oldBuffer // will be used inside a projection buffer inside our inline diff preview below // and platform's implementation currently has a bug where projection buffers // are being leaked. This leak means that if we use the original buffer that is // currently visible in the editor here, the projection buffer span calculation // would be triggered every time user changes some code in this buffer (even though // the diff view would long have been dismissed by the time user edits the code) // resulting in crashes. Instead we create a new buffer from the same content. // TODO: We could use ITextBufferCloneService instead here to clone the original buffer. var oldBuffer = CreateNewPlainTextBuffer(document, cancellationToken); // Create PreviewWorkspace around the buffer to be displayed in the diff preview // so that all IDE services (colorizer, squiggles etc.) light up in this buffer. var leftDocumentId = DocumentId.CreateNewId(document.Project.Id); var leftSolution = document.Project.Solution .RemoveAdditionalDocument(document.Id) .AddAdditionalDocument(leftDocumentId, document.Name, oldBuffer.AsTextContainer().CurrentText); var leftDocument = leftSolution.GetAdditionalDocument(leftDocumentId); var leftWorkspace = new PreviewWorkspace(leftSolution); leftWorkspace.OpenAdditionalDocument(leftDocumentId); return CreateRemovedDocumentPreviewViewCoreAsync(oldBuffer, leftWorkspace, leftDocument, zoomLevel, cancellationToken); }
public void TestPreviewDiagnostic() { var diagnosticService = TestExportProvider.ExportProviderWithCSharpAndVisualBasic.GetExportedValue<IDiagnosticAnalyzerService>() as IDiagnosticUpdateSource; var taskSource = new TaskCompletionSource<DiagnosticsUpdatedArgs>(); diagnosticService.DiagnosticsUpdated += (s, a) => taskSource.TrySetResult(a); using (var previewWorkspace = new PreviewWorkspace(MefV1HostServices.Create(TestExportProvider.ExportProviderWithCSharpAndVisualBasic.AsExportProvider()))) { var solution = previewWorkspace.CurrentSolution .AddProject("project", "project.dll", LanguageNames.CSharp) .AddDocument("document", "class { }") .Project .Solution; Assert.True(previewWorkspace.TryApplyChanges(solution)); previewWorkspace.OpenDocument(previewWorkspace.CurrentSolution.Projects.First().DocumentIds[0]); previewWorkspace.EnableDiagnostic(); // wait 20 seconds taskSource.Task.Wait(20000); if (!taskSource.Task.IsCompleted) { // something is wrong FatalError.Report(new System.Exception("not finished after 20 seconds")); } var args = taskSource.Task.Result; Assert.True(args.Diagnostics.Length > 0); } }
public Task<object> CreateChangedAdditionalDocumentPreviewViewAsync(TextDocument oldDocument, TextDocument newDocument, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Note: We don't use the original buffer that is associated with oldDocument // (and currently open in the editor) for oldBuffer below. This is because oldBuffer // will be used inside a projection buffer inside our inline diff preview below // and platform's implementation currently has a bug where projection buffers // are being leaked. This leak means that if we use the original buffer that is // currently visible in the editor here, the projection buffer span calculation // would be triggered every time user changes some code in this buffer (even though // the diff view would long have been dismissed by the time user edits the code) // resulting in crashes. Instead we create a new buffer from the same content. // TODO: We could use ITextBufferCloneService instead here to clone the original buffer. var oldBuffer = CreateNewPlainTextBuffer(oldDocument, cancellationToken); var newBuffer = CreateNewPlainTextBuffer(newDocument, cancellationToken); // Convert the diffs to be line based. // Compute the diffs between the old text and the new. var diffResult = ComputeEditDifferences(oldDocument, newDocument, cancellationToken); // Need to show the spans in the right that are different. var originalSpans = GetOriginalSpans(diffResult, cancellationToken); var changedSpans = GetChangedSpans(diffResult, cancellationToken); string description = null; var originalLineSpans = CreateLineSpans(oldBuffer.CurrentSnapshot, originalSpans, cancellationToken); var changedLineSpans = CreateLineSpans(newBuffer.CurrentSnapshot, changedSpans, cancellationToken); // TODO: Why aren't we attaching conflict / warning annotations here like we do for regular documents above? // Create PreviewWorkspaces around the buffers to be displayed on the left and right // so that all IDE services (colorizer, squiggles etc.) light up in these buffers. var leftDocumentId = DocumentId.CreateNewId(oldDocument.Project.Id); var leftSolution = oldDocument.Project.Solution .RemoveAdditionalDocument(oldDocument.Id) .AddAdditionalDocument(leftDocumentId, oldDocument.Name, oldBuffer.AsTextContainer().CurrentText); var leftWorkspace = new PreviewWorkspace(leftSolution); leftWorkspace.OpenAdditionalDocument(leftDocumentId); var rightWorkSpace = new PreviewWorkspace( oldDocument.Project.Solution.WithAdditionalDocumentText(oldDocument.Id, newBuffer.AsTextContainer().CurrentText)); rightWorkSpace.OpenAdditionalDocument(newDocument.Id); return CreateChangedDocumentViewAsync( oldBuffer, newBuffer, description, originalLineSpans, changedLineSpans, leftWorkspace, rightWorkSpace, zoomLevel, cancellationToken); }
public void TestPreviewDiagnosticTagger() { using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromLines("class { }")) using (var previewWorkspace = new PreviewWorkspace(workspace.CurrentSolution)) { // set up to listen diagnostic changes so that we can wait until it happens var diagnosticService = workspace.ExportProvider.GetExportedValue<IDiagnosticService>() as DiagnosticService; var taskSource = new TaskCompletionSource<DiagnosticsUpdatedArgs>(); diagnosticService.DiagnosticsUpdated += (s, a) => taskSource.TrySetResult(a); // preview workspace and owner of the solution now share solution and its underlying text buffer var hostDocument = workspace.Projects.First().Documents.First(); var buffer = hostDocument.GetTextBuffer(); // enable preview diagnostics previewWorkspace.OpenDocument(hostDocument.Id); previewWorkspace.EnableDiagnostic(); var foregroundService = new TestForegroundNotificationService(); var optionsService = workspace.Services.GetService<IOptionService>(); var squiggleWaiter = new ErrorSquiggleWaiter(); // create a tagger for preview workspace var taggerSource = new DiagnosticsSquiggleTaggerProvider.TagSource(buffer, foregroundService, diagnosticService, optionsService, squiggleWaiter); // wait up to 20 seconds for diagnostic service taskSource.Task.Wait(20000); if (!taskSource.Task.IsCompleted) { // something is wrong FatalError.Report(new System.Exception("not finished after 20 seconds")); } // wait for tagger squiggleWaiter.CreateWaitTask().PumpingWait(); var snapshot = buffer.CurrentSnapshot; var intervalTree = taggerSource.GetTagIntervalTreeForBuffer(buffer); var spans = intervalTree.GetIntersectingSpans(new SnapshotSpan(snapshot, 0, snapshot.Length)); taggerSource.TestOnly_Dispose(); Assert.Equal(1, spans.Count); } }
private async Task<object> CreateNewDifferenceViewerAsync(PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // leftWorkspace can be null if the change is adding a document. // rightWorkspace can be null if the change is removing a document. // However both leftWorkspace and rightWorkspace can't be null at the same time. Contract.ThrowIfTrue((leftWorkspace == null) && (rightWorkspace == null)); var diffBuffer = _differenceBufferService.CreateDifferenceBuffer( originalBuffer, changedBuffer, new StringDifferenceOptions(), disableEditing: true); var diffViewer = _differenceViewerService.CreateDifferenceView(diffBuffer, _previewRoleSet); diffViewer.Closed += (s, e) => { if (leftWorkspace != null) { leftWorkspace.Dispose(); leftWorkspace = null; } if (rightWorkspace != null) { rightWorkspace.Dispose(); rightWorkspace = null; } }; const string DiffOverviewMarginName = "deltadifferenceViewerOverview"; if (leftWorkspace == null) { diffViewer.ViewMode = DifferenceViewMode.RightViewOnly; diffViewer.RightView.ZoomLevel *= zoomLevel; diffViewer.RightHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } else if (rightWorkspace == null) { diffViewer.ViewMode = DifferenceViewMode.LeftViewOnly; diffViewer.LeftView.ZoomLevel *= zoomLevel; diffViewer.LeftHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } else { diffViewer.ViewMode = DifferenceViewMode.Inline; diffViewer.InlineView.ZoomLevel *= zoomLevel; diffViewer.InlineHost.GetTextViewMargin(DiffOverviewMarginName).VisualElement.Visibility = Visibility.Collapsed; } // Disable focus / tab stop for the diff viewer. diffViewer.RightView.VisualElement.Focusable = false; diffViewer.LeftView.VisualElement.Focusable = false; diffViewer.InlineView.VisualElement.Focusable = false; // This code path must be invoked on UI thread. AssertIsForeground(); // We use ConfigureAwait(true) to stay on the UI thread. await diffViewer.SizeToFitAsync().ConfigureAwait(true); if (leftWorkspace != null) { leftWorkspace.EnableDiagnostic(); } if (rightWorkspace != null) { rightWorkspace.EnableDiagnostic(); } return new DifferenceViewerPreview(diffViewer); }
public void TestPreviewServices() { using (var previewWorkspace = new PreviewWorkspace(MefV1HostServices.Create(EditorServicesUtil.ExportProvider.AsExportProvider()))) { var service = previewWorkspace.Services.GetService<ISolutionCrawlerRegistrationService>(); Assert.True(service is PreviewSolutionCrawlerRegistrationServiceFactory.Service); var persistentService = previewWorkspace.Services.GetService<IPersistentStorageService>(); Assert.NotNull(persistentService); var storage = persistentService.GetStorage(previewWorkspace.CurrentSolution); Assert.True(storage is NoOpPersistentStorage); } }