public async void UpdatePreview(string text) { var workspace = new PreviewWorkspace(Ide.Composition.CompositionManager.Instance.HostServices); var fileName = string.Format("project.{0}", Language == "C#" ? "csproj" : "vbproj"); project = workspace.CurrentSolution.AddProject(fileName, "assembly.dll", Language); // use the mscorlib, system, and system.core that are loaded in the current process. string [] references = { "mscorlib", "System", "System.Core" }; var metadataService = workspace.Services.GetService <IMetadataService> (); var referenceAssemblies = Thread.GetDomain().GetAssemblies() .Where(x => references.Contains(x.GetName(true).Name, StringComparer.OrdinalIgnoreCase)) .Select(a => metadataService.GetReference(a.Location, MetadataReferenceProperties.Assembly)); project = project.WithMetadataReferences(referenceAssemblies); var document = project.AddDocument("document.cs", SourceText.From(text, Encoding.UTF8)); var formatted = Formatter.FormatAsync(document, this.Options).WaitAndGetResult(CancellationToken.None); workspace.TryApplyChanges(project.Solution); TextViewHost.MimeType = "text/x-csharp"; TextViewHost.Text = (await document.GetTextAsync()).ToString(); TextViewHost.DocumentContext = new MyDocumentContext(workspace, document); TextViewHost.IsReadOnly = false; for (int i = 1; i <= TextViewHost.LineCount; i++) { var txt = TextViewHost.GetLineText(i); if (txt == "//[" || txt == "//]") { var line = TextViewHost.GetLine(i); TextViewHost.RemoveText(line.Offset, line.LengthIncludingDelimiter); i--; } } TextViewHost.IsReadOnly = true; if (curWorkspace != null) { curWorkspace.Dispose(); } this.curWorkspace = workspace; }
public void UpdatePreview(string text) { const string start = "//["; const string end = "//]"; var service = MefV1HostServices.Create(_componentModel.DefaultExportProvider); var workspace = new PreviewWorkspace(service); var fileName = string.Format("project.{0}", Language == "C#" ? "csproj" : "vbproj"); var project = workspace.CurrentSolution.AddProject(fileName, "assembly.dll", Language); // use the mscorlib, system, and system.core that are loaded in the current process. string[] references = { "mscorlib", "System", "System.Core" }; var metadataService = workspace.Services.GetService <IMetadataService>(); var referenceAssemblies = Thread.GetDomain().GetAssemblies() .Where(x => references.Contains(x.GetName(true).Name, StringComparer.OrdinalIgnoreCase)) .Select(a => metadataService.GetReference(a.Location, MetadataReferenceProperties.Assembly)); project = project.WithMetadataReferences(referenceAssemblies); var document = project.AddDocument("document", SourceText.From(text, Encoding.UTF8)); var formatted = Formatter.FormatAsync(document, this.Options).WaitAndGetResult(CancellationToken.None); var textBuffer = _textBufferFactoryService.CreateTextBuffer(formatted.GetTextAsync().Result.ToString(), _contentType); var container = textBuffer.AsTextContainer(); var documentBackedByTextBuffer = document.WithText(container.CurrentText); var bufferText = textBuffer.CurrentSnapshot.GetText().ToString(); var startIndex = bufferText.IndexOf(start, StringComparison.Ordinal); var endIndex = bufferText.IndexOf(end, StringComparison.Ordinal); var startLine = textBuffer.CurrentSnapshot.GetLineNumberFromPosition(startIndex) + 1; var endLine = textBuffer.CurrentSnapshot.GetLineNumberFromPosition(endIndex); var projection = _projectionBufferFactory.CreateProjectionBufferWithoutIndentation(_contentTypeRegistryService, _editorOptions.CreateOptions(), textBuffer.CurrentSnapshot, "", LineSpan.FromBounds(startLine, endLine)); var textView = _textEditorFactoryService.CreateTextView(projection, _textEditorFactoryService.CreateTextViewRoleSet(PredefinedTextViewRoles.Analyzable)); this.TextViewHost = _textEditorFactoryService.CreateTextViewHost(textView, setFocus: false); workspace.TryApplyChanges(documentBackedByTextBuffer.Project.Solution); workspace.OpenDocument(document.Id); this.TextViewHost.Closed += (s, a) => { workspace.Dispose(); workspace = null; }; }
public void Dispose() { Debug.Assert(!_disposed); _disposed = true; _workspace.Dispose(); _workspace = null; }
public void TestPreviewWorkspaceDoesNotLeakSolution() { // Verify that analyzer execution doesn't leak solution instances from the preview workspace. var previewWorkspace = new PreviewWorkspace(); Assert.NotNull(previewWorkspace.CurrentSolution); var project = previewWorkspace.CurrentSolution.AddProject( "project", "project.dll", LanguageNames.CSharp ); Assert.True(previewWorkspace.TryApplyChanges(project.Solution)); var solutionObjectReference = ObjectReference.Create(previewWorkspace.CurrentSolution); var analyzers = ImmutableArray.Create <DiagnosticAnalyzer>( new CommonDiagnosticAnalyzers.NotConfigurableDiagnosticAnalyzer() ); ExecuteAnalyzers(previewWorkspace, analyzers); previewWorkspace.Dispose(); solutionObjectReference.AssertReleased(); }
public void UpdatePreview(string text) { var service = VisualStudioMefHostServices.Create(_componentModel.GetService <ExportProvider>()); var workspace = new PreviewWorkspace(service); var fileName = "project." + (Language == "C#" ? "csproj" : "vbproj"); var project = workspace.CurrentSolution.AddProject(fileName, "assembly.dll", Language); // use the mscorlib, system, and system.core that are loaded in the current process. string[] references = { "mscorlib", "System", "System.Core" }; var metadataService = workspace.Services.GetService <IMetadataService>(); var referenceAssemblies = Thread.GetDomain().GetAssemblies() .Where(x => references.Contains(x.GetName(true).Name, StringComparer.OrdinalIgnoreCase)) .Select(a => metadataService.GetReference(a.Location, MetadataReferenceProperties.Assembly)); project = project.WithMetadataReferences(referenceAssemblies); var document = project.AddDocument("document", SourceText.From(text, Encoding.UTF8)); var fallbackFormattingOptions = _globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices); var optionService = workspace.Services.GetRequiredService <IOptionService>(); var configOptions = OptionStore.GetOptions().AsAnalyzerConfigOptions(optionService, document.Project.Language); var formattingService = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var formattingOptions = formattingService.GetFormattingOptions(configOptions, fallbackFormattingOptions); var formatted = Formatter.FormatAsync(document, formattingOptions, CancellationToken.None).WaitAndGetResult(CancellationToken.None); var textBuffer = _textBufferFactoryService.CreateTextBuffer(formatted.GetTextSynchronously(CancellationToken.None).ToString(), _contentType); var container = textBuffer.AsTextContainer(); var projection = _projectionBufferFactory.CreateProjectionBufferWithoutIndentation(_contentTypeRegistryService, _editorOptions.CreateOptions(), textBuffer.CurrentSnapshot, separator: "", exposedLineSpans: GetExposedLineSpans(textBuffer.CurrentSnapshot).ToArray()); var textView = _textEditorFactoryService.CreateTextView(projection, _textEditorFactoryService.CreateTextViewRoleSet(PredefinedTextViewRoles.Interactive)); this.TextViewHost = _textEditorFactoryService.CreateTextViewHost(textView, setFocus: false); workspace.TryApplyChanges(document.Project.Solution); workspace.OpenDocument(document.Id, container); this.TextViewHost.Closed += (s, a) => { workspace.Dispose(); workspace = null; }; }
private async ValueTask <DifferenceViewerPreview> CreateNewDifferenceViewerAsync( PreviewWorkspace?leftWorkspace, PreviewWorkspace?rightWorkspace, IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, double zoomLevel, CancellationToken cancellationToken) { // IWpfDifferenceViewerFactoryService is a Visual Studio API which is not documented as free-threaded await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); // 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 mode = leftWorkspace == null ? DifferenceViewMode.RightViewOnly : rightWorkspace == null ? DifferenceViewMode.LeftViewOnly : DifferenceViewMode.Inline; var diffViewer = await CreateDifferenceViewAsync(diffBuffer, _previewRoleSet, mode, zoomLevel, cancellationToken).ConfigureAwait(true); 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; }; if (_globalOptions.GetOption(SolutionCrawlerRegistrationService.EnableSolutionCrawler)) { leftWorkspace?.EnableSolutionCrawler(); rightWorkspace?.EnableSolutionCrawler(); } return(new DifferenceViewerPreview(diffViewer)); }
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(diffViewer); }
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(ThreadingContext).ConfigureAwait(true); leftWorkspace?.EnableDiagnostic(); rightWorkspace?.EnableDiagnostic(); return(new DifferenceViewerPreview(diffViewer)); }
private IWpfDifferenceViewer CreateNewDifferenceViewer(PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, double zoomLevel) { // 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; diffViewer.SizeToFit(); if (leftWorkspace != null) { leftWorkspace.EnableDiagnostic(); } if (rightWorkspace != null) { rightWorkspace.EnableDiagnostic(); } return(diffViewer); }