示例#1
0
        private bool IsValidTextBuffer()
        {
            IProjectionBuffer textBuffer = _view.TextBuffer as IProjectionBuffer;

            if (textBuffer != null)
            {
                SnapshotPoint bufferPosition = _view.Caret.Position.BufferPosition;
                var           buffers        = from s in textBuffer.SourceBuffers
                                               where
                                               (((!s.ContentType.IsOfType("html") && !s.ContentType.IsOfType("inert")) &&
                                                 (!s.ContentType.IsOfType("CSharp") &&
                                                  !s.ContentType.IsOfType("VisualBasic"))) &&
                                                !s.ContentType.IsOfType("RoslynCSharp")) &&
                                               !s.ContentType.IsOfType("RoslynVisualBasic")
                                               select s;
                foreach (ITextBuffer buffer2 in buffers)
                {
                    if (_view.BufferGraph.MapDownToBuffer(bufferPosition,
                                                          PointTrackingMode.Negative,
                                                          buffer2,
                                                          PositionAffinity.Predecessor).HasValue)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#2
0
        /// <summary>
        /// Gets content type of the text buffer that has the caret.
        /// </summary>
        public string GetContentTypeInActiveBuffer()
        {
            IContentType      retVal     = _wpfView.TextBuffer.ContentType;
            IProjectionBuffer projection = _wpfView.TextBuffer as IProjectionBuffer;

            if (null == projection)
            {
                return(retVal?.TypeName?.ToLowerInvariant());
            }

            // Current view has several buffers (e.g. html file with css code), get the one that has the caret
            var caretPosition = _wpfView.Caret.Position.BufferPosition;
            var buffers       = projection.SourceBuffers;
            var bufferGraph   = _wpfView.BufferGraph;

            foreach (ITextBuffer buffer in buffers)
            {
                SnapshotPoint?point = bufferGraph.MapDownToBuffer(
                    caretPosition,
                    PointTrackingMode.Negative,
                    buffer,
                    PositionAffinity.Predecessor);

                if (!point.HasValue)
                {
                    continue;
                }

                // Several matches possible, we are interested in the last one.
                retVal = buffer.ContentType;
            }

            return(retVal?.TypeName?.ToLowerInvariant());
        }
示例#3
0
        public TemplateProjectionBuffer(IContentTypeRegistryService contentRegistry, IProjectionBufferFactoryService bufferFactory, ITextBuffer diskBuffer, IBufferGraphFactoryService bufferGraphFactory, IContentType contentType)
        {
            _diskBuffer      = diskBuffer;
            _contentRegistry = contentRegistry;
            _contentType     = contentType;

            _projBuffer = bufferFactory.CreateProjectionBuffer(
                this,
                new object[0],
                ProjectionBufferOptions.None
                );
            _projBuffer.Properties.AddProperty(typeof(TemplateProjectionBuffer), this);

            _bufferGraph = bufferGraphFactory.CreateBufferGraph(_projBuffer);

            _htmlBuffer     = CreateHtmlBuffer(bufferFactory);
            _templateBuffer = CreateTemplateBuffer(bufferFactory);

            IVsTextBuffer buffer;

            if (_diskBuffer.Properties.TryGetProperty <IVsTextBuffer>(typeof(IVsTextBuffer), out buffer))
            {
                // keep the Venus HTML classifier happy - it wants to find a site via IVsTextBuffer
                _htmlBuffer.Properties.AddProperty(typeof(IVsTextBuffer), buffer);
            }

            var reader = new SnapshotSpanSourceCodeReader(new SnapshotSpan(diskBuffer.CurrentSnapshot, new Span(0, diskBuffer.CurrentSnapshot.Length)));

            UpdateTemplateSpans(reader);
        }
示例#4
0
        private bool IsValidTextBuffer()
        {
            IProjectionBuffer projection = _view.TextBuffer as IProjectionBuffer;

            if (projection != null)
            {
                SnapshotPoint snapshotPoint = _view.Caret.Position.BufferPosition;

                System.Collections.Generic.IEnumerable <ITextBuffer> buffers = projection.SourceBuffers.Where(
                    s =>
                    !s.ContentType.IsOfType("html") &&
                    !s.ContentType.IsOfType("htmlx") &&
                    !s.ContentType.IsOfType("inert") &&
                    !s.ContentType.IsOfType("CSharp") &&
                    !s.ContentType.IsOfType("VisualBasic") &&
                    !s.ContentType.IsOfType("RoslynCSharp") &&
                    !s.ContentType.IsOfType("RoslynVisualBasic"));


                foreach (ITextBuffer buffer in buffers)
                {
                    SnapshotPoint?point = _view.BufferGraph.MapDownToBuffer(snapshotPoint, PointTrackingMode.Negative, buffer, PositionAffinity.Predecessor);

                    if (point.HasValue)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private void SetContentType(ITextBuffer buffer, IContentType contentType)
        {
            this.isCodeContentType = Utilities.IsContentOfType(contentType, "code");

            // In VS 2013-2017 the HTML language service doesn't provide the correct tabs/spaces options
            // from IEditorOptions, so we have to read them from IVsTextManager.  Unfortunately, this means
            // we won't get OptionChanged notifications for them.
            this.textManagerLanguageName = null;
            if (Utilities.IsContentOfType(contentType, "HTML"))
            {
                this.textManagerLanguageName = "HTML";
            }
            else if (Utilities.IsContentOfType(contentType, "HTMLX"))
            {
                this.textManagerLanguageName = "HTMLX";
            }
            else
            {
                // If an HTML editor has embedded sections using other languages (e.g., JavaScript, C#, Basic, CSS)
                // then the HTML editor will also give us incorrect IEditorOptions for them.
                IProjectionBuffer projection = buffer as IProjectionBuffer;
                if (projection != null && projection.SourceBuffers.Any(
                        source => Utilities.IsContentOfType(source.ContentType, "HTML") || Utilities.IsContentOfType(source.ContentType, "HTMLX")))
                {
                    this.textManagerLanguageName = buffer.ContentType.TypeName;
                }
            }
        }
示例#6
0
        private void TextView_Closed(object sender, EventArgs e)
        {
            IWpfTextView textView = sender as IWpfTextView;

            if (textView != null)
            {
                if (textView.BufferGraph != null)
                {
                    textView.BufferGraph.GraphBuffersChanged -= OnGraphBuffersChanged;
                }

                IProjectionBuffer pb = textView.TextBuffer as IProjectionBuffer;
                if (pb != null)
                {
                    pb.SourceBuffersChanged -= OnSourceBuffersChanged;
                }

                textView.Closed -= TextView_Closed;
                ReplCommandController controller = ReplCommandController.FromTextView(textView);
                if (controller != null)
                {
                    controller.Dispose();
                }
            }
        }
示例#7
0
        public IOleCommandTarget GetCommandTarget(IWpfTextView textView, IOleCommandTarget nextTarget)
        {
            IOleCommandTarget target = ServiceManager.GetService <IOleCommandTarget>(textView);

            if (target == null)
            {
                ReplCommandController controller = ReplCommandController.Attach(textView, textView.TextBuffer);

                // Wrap controller into OLE command target
                target = VsAppShell.Current.TranslateToHostCommandTarget(textView, controller) as IOleCommandTarget;
                Debug.Assert(target != null);

                ServiceManager.AddService(target, textView, _shell);

                // Wrap next OLE target in the chain into ICommandTarget so we can have
                // chain like: OLE Target -> Shim -> ICommandTarget -> Shim -> Next OLE target
                ICommandTarget nextCommandTarget = VsAppShell.Current.TranslateCommandTarget(textView, nextTarget);
                controller.ChainedController = nextCommandTarget;

                // We need to listed when R projected buffer is attached and
                // create R editor document over it.
                textView.BufferGraph.GraphBuffersChanged += OnGraphBuffersChanged;
                IProjectionBuffer pb = textView.TextBuffer as IProjectionBuffer;
                if (pb != null)
                {
                    pb.SourceBuffersChanged += OnSourceBuffersChanged;
                }

                textView.Closed += TextView_Closed;
            }

            return(target);
        }
        public PhpProjectionBuffer(
            IContentTypeRegistryService contentRegistry,
            IProjectionBufferFactoryService bufferFactory,
            IBufferTagAggregatorFactoryService bufferTagAggregatorFactory,
            ITextBuffer diskBuffer,
            IBufferGraphFactoryService bufferGraphFactory,
            IContentType contentType)
        {
            _diskBuffer      = diskBuffer;
            _contentRegistry = contentRegistry;
            _contentType     = contentType;

            _projBuffer     = CreateProjectionBuffer(bufferFactory);
            _htmlBuffer     = CreateHtmlBuffer(bufferFactory);
            _templateBuffer = CreateTemplateBuffer(bufferFactory);

            _bufferGraph = bufferGraphFactory.CreateBufferGraph(_projBuffer);

            _contentTypeTagger              = bufferTagAggregatorFactory.CreateTagAggregator <ContentTypeTag>(_diskBuffer);
            _contentTypeTagger.TagsChanged += HandleContentTypeTagsChanged;

            IVsTextBuffer buffer;

            if (_diskBuffer.Properties.TryGetProperty <IVsTextBuffer>(typeof(IVsTextBuffer), out buffer))
            {
                // keep the Venus HTML classifier happy - it wants to find a site via IVsTextBuffer
                _htmlBuffer.Properties.AddProperty(typeof(IVsTextBuffer), buffer);
            }

            HandleContentTypeTagsChanged();
        }
示例#9
0
        private void EndTracking()
        {
            if (_textView != null)
            {
                ClearHighlight();

                if (_projectionBuffer != null)
                {
                    _projectionBuffer.SourceSpansChanged -= OnSourceSpansChanged;
                    _projectionBuffer = null;
                }

                if (_projectionsChanged || _adornmentRemoved)
                {
                    _projectionsChanged = false;
                    _adornmentRemoved   = false;
                }

                _textView.TextBuffer.Changed     -= OnTextBufferChanged;
                _textView.TextBuffer.PostChanged -= OnPostChanged;

                _textView.Caret.PositionChanged -= OnCaretPositionChanged;
                _textView = null;

                if (OnClose != null)
                {
                    OnClose(this, EventArgs.Empty);
                }
            }
        }
示例#10
0
        /// <summary>
        /// IProjectionBuffer instances can compose recursively.  This will look recursively down the
        /// source buffers to find all of the critical ones
        /// </summary>
        public static IEnumerable <ITextBuffer> GetSourceBuffersRecursive(this IProjectionBuffer projectionBuffer)
        {
            var toVisit = new Queue <IProjectionBuffer>();

            toVisit.Enqueue(projectionBuffer);

            var found = new HashSet <ITextBuffer>();

            while (toVisit.Count > 0)
            {
                var current = toVisit.Dequeue();
                if (found.Contains(current))
                {
                    continue;
                }

                found.Add(current);
                foreach (var sourceBuffer in current.SourceBuffers)
                {
                    if (sourceBuffer is IProjectionBuffer sourceProjection)
                    {
                        toVisit.Enqueue(sourceProjection);
                    }
                    else
                    {
                        found.Add(sourceBuffer);
                    }
                }
            }

            return(found.Where(x => !(x is IProjectionBuffer)));
        }
示例#11
0
        /// <summary>
        /// Given text view locates R document in underlying text buffer graph.
        /// In REPL window there may be multiple R text buffers but usually
        /// only last one (the one active at the > prompt) has attached R document.
        /// Other R buffers represent previously typed commands. They still have
        /// colorizer attached but no active R documents.
        /// </summary>
        /// <param name="viewBuffer"></param>
        /// <returns></returns>
        public static IREditorDocument FindInProjectedBuffers(ITextBuffer viewBuffer)
        {
            IREditorDocument document = null;

            if (viewBuffer.ContentType.IsOfType(RContentTypeDefinition.ContentType))
            {
                return(ServiceManager.GetService <REditorDocument>(viewBuffer));
            }

            // Try locating R buffer
            ITextBuffer       rBuffer = null;
            IProjectionBuffer pb      = viewBuffer as IProjectionBuffer;

            if (pb != null)
            {
                rBuffer = pb.SourceBuffers.FirstOrDefault((ITextBuffer tb) => {
                    if (tb.ContentType.IsOfType(RContentTypeDefinition.ContentType))
                    {
                        document = ServiceManager.GetService <REditorDocument>(tb);
                        if (document != null)
                        {
                            return(true);
                        }
                    }

                    return(false);
                });
            }

            return(document);
        }
        /// <summary>
        /// To be called from the derived class constructor!
        /// </summary>
        protected void SetDataBuffer(IProjectionBuffer dataBuffer)
        {
            if (dataBuffer == null)
            {
                throw new ArgumentNullException("dataBuffer");
            }

            this.DataBuffer = dataBuffer;
        }
示例#13
0
        /// <summary>
        /// To be called from the derived class constructor!
        /// </summary>
        protected void SetDataBuffer(IProjectionBuffer dataBuffer)
        {
            if (dataBuffer == null)
            {
                throw new ArgumentNullException("dataBuffer");
            }

            this.DataBuffer = dataBuffer;
        }
示例#14
0
 private async Task <object> CreateNewDifferenceViewerAsync(
     IProjectionBuffer originalBuffer,
     IProjectionBuffer newBuffer,
     string description,
     FrameworkElement additionalContent)
 {
     IDifferenceBuffer diffBuffer = this.differenceBufferFactoryService.CreateDifferenceBuffer(
         originalBuffer,
         newBuffer,
         options: default,
示例#15
0
        public ITagger <T> CreateTagger <T>(ITextBuffer buffer) where T : ITag
        {
            IProjectionBuffer projectionBuffer = buffer as IProjectionBuffer;

            if (projectionBuffer == null)
            {
                return(null);
            }

            return(new ProjectionWorkaroundTagger(projectionBuffer) as ITagger <T>);
        }
 public void AddClassifier(IProjectionBuffer projectionBuffer, ITextBuffer textBuffer, IClassifier classifer) {
     var elisionInfo = new ElisionInfo(textBuffer, classifer, _bufGraphFact.CreateBufferGraph(projectionBuffer));
     _elisionBuffers.Add(elisionInfo);
     
     classifer.ClassificationChanged += (sender, args) => {
         var classChanged = ClassificationChanged;
         if (classChanged != null) {
             foreach (var span in elisionInfo.BufferGraph.MapDownToBuffer(args.ChangeSpan, SpanTrackingMode.EdgeExclusive, projectionBuffer)) {
                 classChanged(this, new ClassificationChangedEventArgs(span));
             }
         }
     };
 }
        public ITextViewModel CreateTextViewModel(ITextDataModel dataModel, ITextViewRoleSet roles)
        {
            //var tempFolder = Path.Combine(Path.GetTempPath(), "dotvvmTemp");
            //if (!Directory.Exists(tempFolder))
            //    Directory.CreateDirectory(tempFolder);
            //javascriptFilePath = Path.Combine(tempFolder, Guid.NewGuid().ToString("N") + ".js");
            //File.Create(javascriptFilePath);

            IProjectionBuffer projectionBuffer = ParseDataModelToProjection(dataModel);

            textViewModel = new DothtmlProjectionTextViewModel(dataModel, projectionBuffer);

            return(textViewModel);
        }
        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));
        }
示例#19
0
        private void AdjustIndentation(IProjectionBuffer subjectBuffer, IEnumerable <int> visibleSpanIndex)
        {
            if (!visibleSpanIndex.Any())
            {
                return;
            }

            var snapshot = subjectBuffer.CurrentSnapshot;
            var document = _workspace.CurrentSolution.GetDocument(this.Id);

            if (!document.SupportsSyntaxTree)
            {
                return;
            }

            var originalText = document.GetTextSynchronously(CancellationToken.None);

            Debug.Assert(object.ReferenceEquals(originalText, snapshot.AsText()));

            var root = document.GetSyntaxRootSynchronously(CancellationToken.None);

            var editorOptionsFactory = _componentModel.GetService <IEditorOptionsFactoryService>();
            var editorOptions        = editorOptionsFactory.GetOptions(DataBuffer);
            var options = _workspace.Options
                          .WithChangedOption(FormattingOptions.NewLine, root.Language, editorOptions.GetNewLineCharacter())
                          .WithChangedOption(FormattingOptions.UseTabs, root.Language, !editorOptions.IsConvertTabsToSpacesEnabled())
                          .WithChangedOption(FormattingOptions.TabSize, root.Language, editorOptions.GetTabSize())
                          .WithChangedOption(FormattingOptions.IndentationSize, root.Language, editorOptions.GetIndentSize());

            using (var pooledObject = SharedPools.Default <List <TextSpan> >().GetPooledObject())
            {
                var spans = pooledObject.Object;

                spans.AddRange(this.GetEditorVisibleSpans());
                using (var edit = subjectBuffer.CreateEdit(s_venusEditOptions, reiteratedVersionNumber: null, editTag: null))
                {
                    foreach (var spanIndex in visibleSpanIndex)
                    {
                        var rule = GetBaseIndentationRule(root, originalText, spans, spanIndex);

                        var visibleSpan = spans[spanIndex];
                        AdjustIndentationForSpan(document, edit, visibleSpan, rule, options);
                    }

                    edit.Apply();
                }
            }
        }
示例#20
0
        public static IEnumerable<ITextBuffer> GetContributingBuffers(this ITextBuffer textBuffer) {
            List<ITextBuffer> allBuffers = new List<ITextBuffer>();

            allBuffers.Add(textBuffer);
            for (int i = 0; i < allBuffers.Count; i++) {
                IProjectionBuffer currentBuffer = allBuffers[i] as IProjectionBuffer;
                if (currentBuffer != null) {
                    foreach (ITextBuffer sourceBuffer in currentBuffer.SourceBuffers) {
                        if (!allBuffers.Contains(sourceBuffer))
                            allBuffers.Add(sourceBuffer);
                    }
                }
            }

            return allBuffers;
        }
示例#21
0
        /// <summary>
        /// Creates a new tab stops tagger instance.
        /// </summary>
        /// <param name="textView">View to create tagger for.</param>
        /// <param name="buffer">Text buffer to create tagger for.</param>
        public ITagger <T> CreateTagger <T>(ITextView textView, ITextBuffer buffer)
            where T : ITag
        {
            // Make sure that each view has only one tagger associated with it. If view has several buffers
            // (e.g. html file with css code) only the top level buffer will have a tagger associated with it.
            IProjectionBuffer projectionBuffer = textView.TextBuffer as IProjectionBuffer;

            if (null == projectionBuffer || buffer == projectionBuffer.SourceBuffers[0])
            {
                return(new TabStopsTagger(textView, buffer) as ITagger <T>);
            }
            else
            {
                return(null);
            }
        }
        public void AddClassifier(IProjectionBuffer projectionBuffer, ITextBuffer textBuffer, IClassifier classifer)
        {
            var elisionInfo = new ElisionInfo(textBuffer, classifer, _bufGraphFact.CreateBufferGraph(projectionBuffer));

            _elisionBuffers.Add(elisionInfo);

            classifer.ClassificationChanged += (sender, args) => {
                var classChanged = ClassificationChanged;
                if (classChanged != null)
                {
                    foreach (var span in elisionInfo.BufferGraph.MapDownToBuffer(args.ChangeSpan, SpanTrackingMode.EdgeExclusive, projectionBuffer))
                    {
                        classChanged(this, new ClassificationChangedEventArgs(span));
                    }
                }
            };
        }
        // return type Task<object> is required by ISuggestedAction.GetPreviewAsync
        public Task <object> CreateChangePreviewAsync(
            SarifErrorListItem errorListItem,
            ITextBuffer buffer,
            Action <ITextBuffer,
                    ITextSnapshot> applyEdit,
            string description = null,
            FrameworkElement additionalContent = null)
        {
            ITextBuffer bufferClone = this.CloneBuffer(buffer);

            applyEdit(bufferClone, buffer.CurrentSnapshot);

            IHierarchicalDifferenceCollection diffResult    = this.ComputeDifferences(buffer, bufferClone);
            NormalizedSpanCollection          originalSpans = this.GetOriginalSpans(diffResult);
            NormalizedSpanCollection          changedSpans  = this.GetChangedSpans(diffResult);

            List <LineSpan> originalLineSpans = this.CreateLineSpans(buffer.CurrentSnapshot, originalSpans);
            List <LineSpan> changedLineSpans  = this.CreateLineSpans(bufferClone.CurrentSnapshot, changedSpans);

            if (!originalLineSpans.Any())
            {
                originalLineSpans = changedLineSpans;
            }

            if (!(originalLineSpans.Any() && changedLineSpans.Any()))
            {
                return(Task.FromResult <object>(null));
            }

            const string Separator = "\u2026"; // Horizontal ellipsis.

            IProjectionBuffer originalProjectionBuffer = this.projectionBufferFactoryService.CreateProjectionBufferWithoutIndentation(
                this.editorOptionsFactoryService.GlobalOptions,
                buffer.CurrentSnapshot,
                Separator,
                originalLineSpans.ToArray());

            IProjectionBuffer newProjectionBuffer = this.projectionBufferFactoryService.CreateProjectionBufferWithoutIndentation(
                this.editorOptionsFactoryService.GlobalOptions,
                bufferClone.CurrentSnapshot,
                Separator,
                changedLineSpans.ToArray());

            return(this.CreateNewDifferenceViewerAsync(errorListItem, originalProjectionBuffer, newProjectionBuffer, description, additionalContent));
        }
示例#24
0
        private MonoDevelopContainedDocument(ITextBuffer languageBuffer, IProjectionBuffer dataBuffer, IMonoDevelopContainedLanguageHost containedLanguageHost)
        {
            LanguageBuffer        = languageBuffer;
            DataBuffer            = dataBuffer;
            ContainedLanguageHost = containedLanguageHost;

            _differenceSelectorService = CompositionManager.GetExportedValue <ITextDifferencingSelectorService> ();

            var container    = languageBuffer.CurrentSnapshot.AsText().Container;
            var registration = Workspace.GetWorkspaceRegistration(container);

            if (registration.Workspace == null)
            {
                registration.WorkspaceChanged += Registration_WorkspaceChanged;
            }
            else
            {
                FinishInitialization();
            }
        }
示例#25
0
        /// <summary>
        /// Locates first R buffer in the projection buffer graph.
        /// Note that in REPL this may not be the active buffer.
        /// In REPL used <see cref="FindInProjectedBuffers"/>.
        /// </summary>
        /// <param name="viewBuffer"></param>
        /// <returns></returns>
        public static ITextBuffer FindRBuffer(ITextBuffer viewBuffer)
        {
            if (viewBuffer.ContentType.IsOfType(RContentTypeDefinition.ContentType))
            {
                return(viewBuffer);
            }

            // Try locating R buffer
            ITextBuffer       rBuffer = null;
            IProjectionBuffer pb      = viewBuffer as IProjectionBuffer;

            if (pb != null)
            {
                rBuffer = pb.SourceBuffers.FirstOrDefault((ITextBuffer tb) => {
                    return(tb.ContentType.IsOfType(RContentTypeDefinition.ContentType));
                });
            }

            return(rBuffer);
        }
示例#26
0
        public VenusMargin(IWpfTextView textView, ITextEditorFactoryService textEditorFactory)
        {
            _projectionBuffer = (IProjectionBuffer)textView.TextBuffer;

            _control = new ProjectionBufferMargin
            {
                DataContext       = _viewModel,
                TextEditorFactory = textEditorFactory,
                TextView          = textView,
            };

            _projectionBuffer.Changed              += OnProjectionBufferChanged;
            _projectionBuffer.SourceSpansChanged   += this.OnProjectionBufferSourceSpansChanged;
            _projectionBuffer.SourceBuffersChanged += OnProjectionBufferSourceBuffersChanged;

            foreach (var b in _projectionBuffer.SourceBuffers)
            {
                _viewModel.SourceBuffers.Add(b);
            }
        }
示例#27
0
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            if (span.IsEmpty || _view == null)
            {
                return(_empty);
            }

            IList <ClassificationSpan> list = new List <ClassificationSpan>();
            ITextSnapshotLine          line = span.Snapshot.GetLineFromPosition(span.Start.Position);

            if (_caret > 0 && (line.Extent.Contains(_caret.Position) || line.Extent.End.Position == _caret.Position))
            {
                _span = span.Snapshot.CreateTrackingSpan(line.Extent, SpanTrackingMode.EdgeExclusive);
                return(_empty);
            }

            IProjectionBuffer projection = span.Snapshot.TextBuffer as IProjectionBuffer;

            if (projection != null)
            {
                SnapshotPoint     point     = projection.CurrentSnapshot.MapToSourceSnapshot(line.Start + line.Length);
                ITextSnapshotLine basePoint = point.Snapshot.GetLineFromPosition(point.Position);

                if (basePoint.Length > line.Length)
                {
                    return(_empty);
                }
            }

            string text    = line.GetText();
            string trimmed = text.TrimEnd();
            int    diff    = text.Length - trimmed.Length;

            if (diff > 0)
            {
                SnapshotSpan ss = new SnapshotSpan(span.Snapshot, line.Start + line.Length - diff, diff);
                list.Add(new ClassificationSpan(ss, _whitespace));
            }

            return(list);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ProjectionHighlightAdornment"/> class.
        /// </summary>
        /// <param name="view">Text view to create the adornment for</param>
        public ProjectionHighlightAdornment(IWpfTextView view)
        {
            if (view == null)
            {
                throw new ArgumentNullException("view");
            }

            _layer = view.GetAdornmentLayer(ProjectionAdornmentTextViewCreationListener.LayerName);

            _view                = view;
            _projectionBuffer    = view.TextBuffer as IProjectionBuffer;
            _view.LayoutChanged += OnLayoutChanged;

            // Create the pen and brush to color the box behind the a's
            _brushes    = new Brush[5];
            _pens       = new Pen[5];
            _brushes[0] = new SolidColorBrush(Color.FromArgb(0x20, 0x00, 0x00, 0xff));
            _brushes[0].Freeze();
            _pens[0] = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0x00, 0xff)), 0.5);
            _pens[0].Freeze();

            _brushes[1] = new SolidColorBrush(Color.FromArgb(0x20, 0x00, 0xff, 0x00));
            _brushes[1].Freeze();
            _pens[1] = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xff, 0x00)), 0.5);
            _pens[1].Freeze();

            _brushes[2] = new SolidColorBrush(Color.FromArgb(0x20, 0xff, 0x00, 0x00));
            _brushes[2].Freeze();
            _pens[2] = new Pen(new SolidColorBrush(Color.FromRgb(0xff, 0x00, 0x00)), 0.5);
            _pens[2].Freeze();

            _brushes[3] = new SolidColorBrush(Color.FromArgb(0x20, 0xff, 0x00, 0xff));
            _brushes[3].Freeze();
            _pens[3] = new Pen(new SolidColorBrush(Color.FromRgb(0xff, 0x00, 0xff)), 0.5);
            _pens[3].Freeze();

            _brushes[4] = new SolidColorBrush(Color.FromArgb(0x20, 0x00, 0xff, 0xff));
            _brushes[4].Freeze();
            _pens[4] = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xff, 0xff)), 0.5);
            _pens[4].Freeze();
        }
示例#29
0
        public VenusMargin(IWpfTextView textView, ITextEditorFactoryService textEditorFactory)
        {
            _textView = textView;
            _projectionBuffer = (IProjectionBuffer)textView.TextBuffer;

            _control = new ProjectionBufferMargin
            {
                DataContext = _viewModel,
                TextEditorFactory = textEditorFactory,
                TextView = textView,
            };

            _projectionBuffer.Changed += OnProjectionBufferChanged;
            _projectionBuffer.SourceSpansChanged += this.OnProjectionBufferSourceSpansChanged;
            _projectionBuffer.SourceBuffersChanged += OnProjectionBufferSourceBuffersChanged;

            foreach (var b in _projectionBuffer.SourceBuffers)
            {
                _viewModel.SourceBuffers.Add(b);
            }
        }
示例#30
0
        private static void ApplyChanges(
            IProjectionBuffer subjectBuffer,
            IEnumerable <TextChange> changes,
            IList <TextSpan> visibleSpansInOriginal,
            out IEnumerable <int> affectedVisibleSpansInNew)
        {
            using var edit = subjectBuffer.CreateEdit(s_venusEditOptions, reiteratedVersionNumber: null, editTag: null);

            var affectedSpans = SharedPools.Default <HashSet <int> >().AllocateAndClear();

            affectedVisibleSpansInNew = affectedSpans;

            var currentVisibleSpanIndex = 0;

            foreach (var change in changes)
            {
                // Find the next visible span that either overlaps or intersects with
                while (currentVisibleSpanIndex < visibleSpansInOriginal.Count &&
                       visibleSpansInOriginal[currentVisibleSpanIndex].End < change.Span.Start)
                {
                    currentVisibleSpanIndex++;
                }

                // no more place to apply text changes
                if (currentVisibleSpanIndex >= visibleSpansInOriginal.Count)
                {
                    break;
                }

                var newText = change.NewText;
                var span    = change.Span.ToSpan();

                edit.Replace(span, newText);

                affectedSpans.Add(currentVisibleSpanIndex);
            }

            edit.ApplyAndLogExceptions();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EditorMargin1"/> class for a given <paramref name="textView"/>.
        /// </summary>
        /// <param name="textView">The <see cref="IWpfTextView"/> to attach the margin to.</param>
        public ProjectionViewerMargin(IWpfTextView textView)
        {
            _textView = textView;

            _projectionBuffer = _textView.TextBuffer as IProjectionBuffer;
            Debug.Assert(_projectionBuffer != null);

            this.Height       = 20; // Margin height sufficient to have the label
            this.ClipToBounds = true;
            this.Background   = new SolidColorBrush(Colors.LightGreen);

            // Add a green colored label that says "Hello EditorMargin1"
            _label = new Label
            {
                Background = new SolidColorBrush(Colors.LightGreen),
                Content    = $"This text view contains {_projectionBuffer.SourceBuffers.Count} projection buffers and {_projectionBuffer.CurrentSnapshot.SpanCount} projection spans.",
            };

            this.Children.Add(_label);

            _projectionBuffer.SourceBuffersChanged += OnSourceBuffersChanged;
        }
示例#32
0
        private ITextBuffer GetTextBuffer(out SnapshotPoint?point)
        {
            IProjectionBuffer projection = _textView.TextBuffer as IProjectionBuffer;

            if (projection != null)
            {
                var snapshotPoint = _textView.Caret.Position.BufferPosition;

                foreach (ITextBuffer buffer in projection.SourceBuffers.Where(s => !s.ContentType.IsOfType("htmlx")))
                {
                    point = _textView.BufferGraph.MapDownToBuffer(snapshotPoint, PointTrackingMode.Negative, buffer, PositionAffinity.Predecessor);

                    if (point.HasValue)
                    {
                        return(buffer);
                    }
                }
            }

            point = _textView.Caret.Position.BufferPosition;

            return(_textView.TextBuffer);
        }
        internal static string GetFilePath(this ITextBuffer textBuffer)
        {
            string filePath = GetFilePathFromTextDocument(textBuffer);

            if (!string.IsNullOrEmpty(filePath))
            {
                return(filePath);
            }

            IProjectionBuffer projectionBuffer = textBuffer as IProjectionBuffer;

            if (projectionBuffer == null)
            {
                return(null);
            }

            List <string> filePaths = new List <string>();

            foreach (ITextBuffer buffer in projectionBuffer.SourceBuffers)
            {
                filePath = GetFilePathFromTextDocument(buffer);

                if (!string.IsNullOrEmpty(filePath))
                {
                    filePaths.Add(filePath);
                }
            }

            Debug.Assert(filePaths.Count <= 1, "Why is there more than one buffer with a file path?");

            if (filePaths.Count > 0)
            {
                return(filePaths[0]);
            }

            return(null);
        }
            public UIThreadOnly(
                InteractiveWindow window,
                IInteractiveWindowEditorFactoryService factory,
                IContentTypeRegistryService contentTypeRegistry,
                ITextBufferFactoryService bufferFactory,
                IProjectionBufferFactoryService projectionBufferFactory,
                IEditorOperationsFactoryService editorOperationsFactory,
                ITextEditorFactoryService editorFactory,
                IRtfBuilderService rtfBuilderService,
                IIntellisenseSessionStackMapService intellisenseSessionStackMap,
                ISmartIndentationService smartIndenterService,
                IInteractiveEvaluator evaluator,
                IWaitIndicator waitIndicator)
            {
                _window = window;
                _factory = factory;
                _rtfBuilderService = (IRtfBuilderService2)rtfBuilderService;
                _intellisenseSessionStackMap = intellisenseSessionStackMap;
                _smartIndenterService = smartIndenterService;
                _waitIndicator = waitIndicator;
                Evaluator = evaluator;

                var replContentType = contentTypeRegistry.GetContentType(PredefinedInteractiveContentTypes.InteractiveContentTypeName);
                var replOutputContentType = contentTypeRegistry.GetContentType(PredefinedInteractiveContentTypes.InteractiveOutputContentTypeName);

                OutputBuffer = bufferFactory.CreateTextBuffer(replOutputContentType);
                StandardInputBuffer = bufferFactory.CreateTextBuffer();
                _inertType = bufferFactory.InertContentType;

                _projectionBuffer = projectionBufferFactory.CreateProjectionBuffer(
                    new EditResolver(window),
                    Array.Empty<object>(),
                    ProjectionBufferOptions.None,
                    replContentType);

                _projectionBuffer.Properties.AddProperty(typeof(InteractiveWindow), window);

                AppendNewOutputProjectionBuffer();
                _projectionBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(ProjectionBufferChanged);

                var roleSet = editorFactory.CreateTextViewRoleSet(
                    PredefinedTextViewRoles.Analyzable,
                    PredefinedTextViewRoles.Editable,
                    PredefinedTextViewRoles.Interactive,
                    PredefinedTextViewRoles.Zoomable,
                    PredefinedInteractiveTextViewRoles.InteractiveTextViewRole);

                TextView = factory.CreateTextView(window, _projectionBuffer, roleSet);
                TextView.Caret.PositionChanged += CaretPositionChanged;

                var options = TextView.Options;
                options.SetOptionValue(DefaultTextViewHostOptions.HorizontalScrollBarId, true);
                options.SetOptionValue(DefaultTextViewHostOptions.LineNumberMarginId, false);
                options.SetOptionValue(DefaultTextViewHostOptions.OutliningMarginId, false);
                options.SetOptionValue(DefaultTextViewHostOptions.GlyphMarginId, false);
                options.SetOptionValue(DefaultTextViewOptions.WordWrapStyleId, WordWrapStyles.None);

                _lineBreakString = options.GetNewLineCharacter();
                EditorOperations = editorOperationsFactory.GetEditorOperations(TextView);

                _buffer = new OutputBuffer(window);
                OutputWriter = new InteractiveWindowWriter(window, spans: null);

                SortedSpans errorSpans = new SortedSpans();
                ErrorOutputWriter = new InteractiveWindowWriter(window, errorSpans);
                OutputClassifierProvider.AttachToBuffer(OutputBuffer, errorSpans);
            }
示例#35
0
        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);
        }
示例#36
0
        private static void ApplyChanges(
            IProjectionBuffer subjectBuffer,
            IEnumerable<TextChange> changes,
            IList<TextSpan> visibleSpansInOriginal,
            out IEnumerable<int> affectedVisibleSpansInNew)
        {
            using (var edit = subjectBuffer.CreateEdit(s_venusEditOptions, reiteratedVersionNumber: null, editTag: null))
            {
                var affectedSpans = SharedPools.Default<HashSet<int>>().AllocateAndClear();
                affectedVisibleSpansInNew = affectedSpans;

                var currentVisibleSpanIndex = 0;
                foreach (var change in changes)
                {
                    // Find the next visible span that either overlaps or intersects with 
                    while (currentVisibleSpanIndex < visibleSpansInOriginal.Count &&
                           visibleSpansInOriginal[currentVisibleSpanIndex].End < change.Span.Start)
                    {
                        currentVisibleSpanIndex++;
                    }

                    // no more place to apply text changes
                    if (currentVisibleSpanIndex >= visibleSpansInOriginal.Count)
                    {
                        break;
                    }

                    var newText = change.NewText;
                    var span = change.Span.ToSpan();

                    edit.Replace(span, newText);

                    affectedSpans.Add(currentVisibleSpanIndex);
                }

                edit.Apply();
            }
        }
示例#37
0
        private void AdjustIndentation(IProjectionBuffer subjectBuffer, IEnumerable<int> visibleSpanIndex)
        {
            if (!visibleSpanIndex.Any())
            {
                return;
            }

            var snapshot = subjectBuffer.CurrentSnapshot;
            var document = _workspace.CurrentSolution.GetDocument(this.Id);
            if (!document.SupportsSyntaxTree)
            {
                return;
            }

            var originalText = document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None);
            Contract.Requires(object.ReferenceEquals(originalText, snapshot.AsText()));

            var root = document.GetSyntaxRootAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None);

            var editorOptionsFactory = _componentModel.GetService<IEditorOptionsFactoryService>();
            var editorOptions = editorOptionsFactory.GetOptions(_containedLanguage.DataBuffer);
            var options = _workspace.Options
                                        .WithChangedOption(FormattingOptions.UseTabs, root.Language, !editorOptions.IsConvertTabsToSpacesEnabled())
                                        .WithChangedOption(FormattingOptions.TabSize, root.Language, editorOptions.GetTabSize())
                                        .WithChangedOption(FormattingOptions.IndentationSize, root.Language, editorOptions.GetIndentSize());

            using (var pooledObject = SharedPools.Default<List<TextSpan>>().GetPooledObject())
            {
                var spans = pooledObject.Object;

                spans.AddRange(this.GetEditorVisibleSpans());
                using (var edit = subjectBuffer.CreateEdit(s_venusEditOptions, reiteratedVersionNumber: null, editTag: null))
                {
                    foreach (var spanIndex in visibleSpanIndex)
                    {
                        var rule = GetBaseIndentationRule(root, originalText, spans, spanIndex);

                        var visibleSpan = spans[spanIndex];
                        AdjustIndentationForSpan(document, edit, visibleSpan, rule, options);
                    }

                    edit.Apply();
                }
            }
        }
        private bool TrySetContext(
            bool isImmediateWindow)
        {
            // Get the workspace, and from there, the solution and document containing this buffer.
            // If there's an ExternalSource, we won't get a document. Give up in that case.
            Document document = ContextBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
            if (document == null)
            {
                _projectionBuffer = null;
                _debuggerTextView = null;
                _workspace = null;
                _immediateWindowContext = null;
                return false;
            }

            var solution = document.Project.Solution;

            // Get the appropriate ITrackingSpan for the window the user is typing in
            var viewSnapshot = _textView.TextSnapshot;
            _immediateWindowContext = null;
            var debuggerMappedSpan = isImmediateWindow
                ? CreateImmediateWindowProjectionMapping(document, out _immediateWindowContext)
                : viewSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive);

            // Wrap the original ContextBuffer in a projection buffer that we can make read-only
            this.ContextBuffer = this.ProjectionBufferFactoryService.CreateProjectionBuffer(null,
                new object[] { this.ContextBuffer.CurrentSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive) }, ProjectionBufferOptions.None, _contentType);

            // Make projection readonly so we can't edit it by mistake.
            using (var regionEdit = this.ContextBuffer.CreateReadOnlyRegionEdit())
            {
                regionEdit.CreateReadOnlyRegion(new Span(0, this.ContextBuffer.CurrentSnapshot.Length), SpanTrackingMode.EdgeInclusive, EdgeInsertionMode.Deny);
                regionEdit.Apply();
            }

            // Adjust the context point to ensure that the right information is in scope.
            // For example, we may need to move the point to the end of the last statement in a method body
            // in order to be able to access all local variables.
            var contextPoint = this.ContextBuffer.CurrentSnapshot.GetLineFromLineNumber(CurrentStatementSpan.iEndLine).Start + CurrentStatementSpan.iEndIndex;
            var adjustedContextPoint = GetAdjustedContextPoint(contextPoint, document);

            // Get the previous span/text. We might have to insert another newline or something.
            var previousStatementSpan = GetPreviousStatementBufferAndSpan(adjustedContextPoint, document);

            // Build the tracking span that includes the rest of the file
            var restOfFileSpan = ContextBuffer.CurrentSnapshot.CreateTrackingSpanFromIndexToEnd(adjustedContextPoint, SpanTrackingMode.EdgePositive);

            // Put it all into a projection buffer
            _projectionBuffer = this.ProjectionBufferFactoryService.CreateProjectionBuffer(null,
                new object[] { previousStatementSpan, debuggerMappedSpan, this.StatementTerminator, restOfFileSpan }, ProjectionBufferOptions.None, _contentType);

            // fork the solution using this new primary buffer
            var forkedSolution = solution.WithDocumentText(document.Id, _projectionBuffer.CurrentSnapshot.AsText(), PreservationMode.PreserveIdentity);

            // put it into a new workspace 
            _workspace = new DebuggerIntelliSenseWorkspace(forkedSolution);
            _workspace.OpenDocument(document.Id, _projectionBuffer.AsTextContainer());

            // Start getting the compilation so the PartialSolution will be ready when the user starts typing in the window
            _workspace.CurrentSolution.GetCompilationAsync(document.Project.Id, System.Threading.CancellationToken.None);

            _textView.TextBuffer.ChangeContentType(_contentType, null);

            var bufferGraph = _bufferGraphFactoryService.CreateBufferGraph(_projectionBuffer);

            _debuggerTextView = new DebuggerTextView(_textView, bufferGraph, this.InImmediateWindow);
            return true;
        }
        private void EndTracking()
        {
            if (_textView != null)
            {
                ClearHighlight();

                if (_projectionBuffer != null)
                {
                    _projectionBuffer.SourceSpansChanged -= OnSourceSpansChanged;
                    _projectionBuffer = null;
                }

                if (_projectionsChanged || _adornmentRemoved)
                {
                    _projectionsChanged = false;
                    _adornmentRemoved = false;
                }

                _textView.TextBuffer.Changed -= OnTextBufferChanged;
                _textView.TextBuffer.PostChanged -= OnPostChanged;

                _textView.Caret.PositionChanged -= OnCaretPositionChanged;
                _textView = null;

                if (OnClose != null)
                    OnClose(this, EventArgs.Empty);
            }
        }
示例#40
0
        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 ProjectionTextViewModel(ITextDataModel dataModel, IProjectionBuffer projectionBuffer)
 {
     this._dataModel = dataModel;
     this._projectionBuffer = projectionBuffer;
     this._properties = new PropertyCollection();
 }