private ITrackingSpan CreateImmediateWindowProjectionMapping(Document document, out ImmediateWindowContext immediateWindowContext) { var caretLine = _textView.Caret.ContainingTextViewLine.Extent; var currentLineIndex = _textView.TextSnapshot.GetLineNumberFromPosition(caretLine.Start.Position); var debuggerMappedSpan = _textView.TextSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive); var projectionBuffer = this.ProjectionBufferFactoryService.CreateProjectionBuffer(null, new object[] { debuggerMappedSpan }, ProjectionBufferOptions.PermissiveEdgeInclusiveSourceSpans, _contentType); // There's currently a bug in the editor (515925) where an elision buffer can't be projected into // another projection buffer. So workaround by using a second projectiong buffer that only // projects the text we care about var elisionProjectionBuffer = this.ProjectionBufferFactoryService.CreateProjectionBuffer(null, new object[] { projectionBuffer.CurrentSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive) }, ProjectionBufferOptions.None, _contentType); immediateWindowContext = new ImmediateWindowContext() { ProjectionBuffer = projectionBuffer, ElisionBuffer = elisionProjectionBuffer }; _textView.TextBuffer.PostChanged += TextBuffer_PostChanged; SetupImmediateWindowProjectionBuffer(); return elisionProjectionBuffer.CurrentSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive); }
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; }