private void HandleAddRemoveBuffers(ReadOnlyCollection <ITextBuffer> addedBuffers, ReadOnlyCollection <ITextBuffer> removedBuffers) { foreach (ITextBuffer tb in addedBuffers) { if (tb.ContentType.IsOfType(RContentTypeDefinition.ContentType)) { IREditorDocument doc = REditorDocument.TryFromTextBuffer(tb); if (doc == null) { var editorDocument = new REditorDocument(tb, _shell); } } } foreach (ITextBuffer tb in removedBuffers) { if (tb.ContentType.IsOfType(RContentTypeDefinition.ContentType)) { IREditorDocument doc = REditorDocument.TryFromTextBuffer(tb); if (doc != null) { doc.Close(); } } } }
/// <summary> /// Primary entry point for intellisense. This is where intellisense list is getting created. /// </summary> /// <param name="session">Completion session</param> /// <param name="completionSets">Completion sets to populate</param> public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets) { Debug.Assert(EditorShell.IsUIThread); if (_asyncSession != null) { return; } IREditorDocument doc = REditorDocument.TryFromTextBuffer(_textBuffer); if (doc == null) { return; } int position = session.GetTriggerPoint(_textBuffer).GetPosition(_textBuffer.CurrentSnapshot); if (!doc.EditorTree.IsReady) { // Parsing is pending. Make completion async. CreateAsyncSession(doc, position, session, completionSets); } else { PopulateCompletionList(position, session, completionSets, doc.EditorTree.AstRoot); } }
public EditorErrorTagger(ITextBuffer textBuffer, IEditorTaskList taskList, IServiceContainer services) { _taskList = taskList; _settings = services.GetService <IREditorSettings>(); _idleTime = services.GetService <IIdleTimeService>(); _document = textBuffer.GetEditorDocument <IREditorDocument>(); _document.Closing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved += OnNodesRemoved; _errorTags = new ErrorTagCollection(_document.EditorTree); _textBuffer = _document.EditorTree.TextBuffer(); _textBuffer.Changed += OnTextBufferChanged; // Don't push syntax errors to the Error List in transient // documents such as in document attached to a projected buffer // in the R interactive window if (_taskList != null && !_document.IsRepl) { _taskList.AddTaskSource(this); } var validator = _document.EditorBuffer.GetService <TreeValidator>(); validator.Cleared += OnCleared; _resultsQueue = validator.ValidationResults; _idleTime.Idle += OnIdle; }
/// <summary> /// Appends indentation to each line so formatted text appears properly /// indented inside the host document (script block in HTML page). /// </summary> private static void IndentLines(ITextView textView, ITextBuffer textBuffer, ITextRange range, AstRoot ast, RFormatOptions options, int originalIndentSizeInSpaces) { ITextSnapshot snapshot = textBuffer.CurrentSnapshot; ITextSnapshotLine firstLine = snapshot.GetLineFromPosition(range.Start); ITextSnapshotLine lastLine = snapshot.GetLineFromPosition(range.End); IREditorDocument document = REditorDocument.TryFromTextBuffer(textBuffer); for (int i = firstLine.LineNumber; i <= lastLine.LineNumber; i++) { // Snapshot is updated after each insertion so do not cache ITextSnapshotLine line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(i); int indent = SmartIndenter.GetSmartIndent(line, ast, originalIndentSizeInSpaces, formatting: true); if (indent > 0 && line.Length > 0 && line.Start >= range.Start) { // Check current indentation and correct for the difference int currentIndentSize = IndentBuilder.TextIndentInSpaces(line.GetText(), options.TabSize); indent = Math.Max(0, indent - currentIndentSize); if (indent > 0) { string indentString = IndentBuilder.GetIndentString(indent, options.IndentType, options.TabSize); textBuffer.Insert(line.Start, indentString); if (document == null) { // Typically this is a test scenario only. In the real editor // instance document is available and automatically updates AST // when whitespace inserted, not no manual update is necessary. ast.ReflectTextChange(line.Start, 0, indentString.Length); } } } } }
/// <summary> /// Determines if current caret position is in the same function /// argument list as before or is it a different one and signature /// help session should be dismissed and re-triggered. This is helpful /// when user types nested function calls such as 'a(b(c(...), d(...)))' /// </summary> public static bool IsSameSignatureContext(ITextView textView, ITextBuffer subjectBuffer) { ISignatureHelpBroker signatureBroker = EditorShell.Current.ExportProvider.GetExportedValue <ISignatureHelpBroker>(); var sessions = signatureBroker.GetSessions(textView); Debug.Assert(sessions.Count < 2); if (sessions.Count == 1) { IFunctionInfo sessionFunctionInfo = null; sessions[0].Properties.TryGetProperty <IFunctionInfo>("functionInfo", out sessionFunctionInfo); if (sessionFunctionInfo != null) { try { IREditorDocument document = REditorDocument.FromTextBuffer(textView.TextBuffer); document.EditorTree.EnsureTreeReady(); ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer( document.EditorTree.AstRoot, subjectBuffer.CurrentSnapshot, textView.Caret.Position.BufferPosition); return(parametersInfo != null && parametersInfo.FunctionName == sessionFunctionInfo.Name); } catch (Exception) { } } } return(false); }
private void OnDocumentClosing(object sender, EventArgs e) { if (_textBuffer != null) { EditorShell.Current.Idle -= OnIdle; _document.EditorTree.UpdateCompleted -= OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved -= OnNodesRemoved; _document.DocumentClosing -= OnDocumentClosing; _document = null; _errorTags.Clear(); _errorTags = null; ServiceManager.RemoveService <EditorErrorTagger>(_textBuffer); ResultsQueue = null; _textBuffer.Changed -= OnTextBufferChanged; _textBuffer = null; if (TaskList != null) { TaskList.RemoveTaskSource(this); } } }
/// <summary> /// Primary entry point for intellisense. This is where intellisense list is getting created. /// </summary> /// <param name="session">Completion session</param> /// <param name="completionSets">Completion sets to populate</param> public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets) { Debug.Assert(EditorShell.IsUIThread); IREditorDocument doc = REditorDocument.TryFromTextBuffer(_textBuffer); if (doc == null) { return; } int position = session.GetTriggerPoint(_textBuffer).GetPosition(_textBuffer.CurrentSnapshot); if (!doc.EditorTree.IsReady) { doc.EditorTree.InvokeWhenReady((o) => { RCompletionController controller = ServiceManager.GetService <RCompletionController>(session.TextView); if (controller != null) { controller.ShowCompletion(autoShownCompletion: true); controller.FilterCompletionSession(); } }, null, this.GetType(), processNow: true); } else { PopulateCompletionList(position, session, completionSets, doc.EditorTree.AstRoot); } }
public EditorErrorTagger(ITextBuffer textBuffer, IEditorTaskList taskList, ICoreShell shell) { _taskList = taskList; _shell = shell; _settings = _shell.GetService <IREditorSettings>(); _document = REditorDocument.FromTextBuffer(textBuffer); _document.DocumentClosing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved += OnNodesRemoved; _errorTags = new ErrorTagCollection(_document.EditorTree); _textBuffer = _document.EditorTree.TextBuffer; _textBuffer.Changed += OnTextBufferChanged; _fireCodeMarkerUponCompletion = true; // Don't push syntax errors to the Error List in transient // documents such as in document attached to a projected buffer // in the R interactive window if (_taskList != null) { var view = _document.GetFirstView(); if (view != null && !view.IsRepl()) { _taskList.AddTaskSource(this); } } TreeValidator validator = TreeValidator.EnsureFromTextBuffer(_textBuffer, _document.EditorTree, shell); validator.Cleared += OnCleared; ResultsQueue = validator.ValidationResults; _shell.Idle += OnIdle; }
public EditorErrorTagger(ITextBuffer textBuffer) { EditorShell.Current.CompositionService.SatisfyImportsOnce(this); _document = REditorDocument.FromTextBuffer(textBuffer); _document.DocumentClosing += OnDocumentClosing; _document.EditorTree.UpdateCompleted += OnTreeUpdateCompleted; _document.EditorTree.NodesRemoved += OnNodesRemoved; _errorTags = new ErrorTagCollection(_document.EditorTree); _textBuffer = _document.EditorTree.TextBuffer; _textBuffer.Changed += OnTextBufferChanged; _fireCodeMarkerUponCompletion = true; // Don't push syntax errors to the Error List in transient // documents such as in document attached to a projected buffer // in the R interactive window if (TaskList != null) { var view = _document.GetFirstView(); if (view != null && !view.IsRepl()) { TaskList.AddTaskSource(this); } } TreeValidator validator = TreeValidator.EnsureFromTextBuffer(_textBuffer, _document.EditorTree); validator.Cleared += OnCleared; ResultsQueue = validator.ValidationResults; EditorShell.Current.Idle += OnIdle; ServiceManager.AddService <EditorErrorTagger>(this, textBuffer); }
public override CommandResult Invoke(Guid group, int id, object inputArg, ref object outputArg) { string originalText = TargetBuffer.CurrentSnapshot.GetText(); string formattedText = string.Empty; var formatter = new RFormatter(Shell.GetService <IREditorSettings>().FormatOptions); try { formattedText = formatter.Format(originalText); } catch (Exception ex) { Debug.Assert(false, "Formatter exception: ", ex.Message); } if (!string.IsNullOrEmpty(formattedText) && !string.Equals(formattedText, originalText, StringComparison.Ordinal)) { var selectionTracker = new RSelectionTracker(TextView, TargetBuffer, new TextRange(0, TargetBuffer.CurrentSnapshot.Length)); selectionTracker.StartTracking(automaticTracking: false); try { using (var massiveChange = new MassiveChange(TextView, TargetBuffer, Shell, Resources.FormatDocument)) { IREditorDocument document = REditorDocument.TryFromTextBuffer(TargetBuffer); if (document != null) { document.EditorTree.Invalidate(); } var caretPosition = TextView.Caret.Position.BufferPosition; var viewPortLeft = TextView.ViewportLeft; RTokenizer tokenizer = new RTokenizer(); string oldText = TargetBuffer.CurrentSnapshot.GetText(); IReadOnlyTextRangeCollection <RToken> oldTokens = tokenizer.Tokenize(oldText); IReadOnlyTextRangeCollection <RToken> newTokens = tokenizer.Tokenize(formattedText); #if DEBUG //if (oldTokens.Count != newTokens.Count) { // for (int i = 0; i < Math.Min(oldTokens.Count, newTokens.Count); i++) { // if (oldTokens[i].TokenType != newTokens[i].TokenType) { // Debug.Assert(false, Invariant($"Token type difference at {i}")); // break; // } else if (oldTokens[i].Length != newTokens[i].Length) { // Debug.Assert(false, Invariant($"token length difference at {i}")); // break; // } // } //} #endif IncrementalTextChangeApplication.ApplyChangeByTokens( TargetBuffer, new TextStream(oldText), new TextStream(formattedText), oldTokens, newTokens, TextRange.FromBounds(0, oldText.Length), Resources.FormatDocument, selectionTracker, Shell); } } finally { selectionTracker.EndTracking(); } return(new CommandResult(CommandStatus.Supported, 0)); } return(CommandResult.NotSupported); }
private void UpdateCurrentParameter() { if (SubjectBuffer != null && TextView != null) { IREditorDocument document = REditorDocument.TryFromTextBuffer(SubjectBuffer); if (document != null) { SnapshotPoint?p = REditorDocument.MapCaretPositionFromView(TextView); if (p.HasValue) { document.EditorTree.InvokeWhenReady((o) => { if (TextView != null) { // Session is still active p = REditorDocument.MapCaretPositionFromView(TextView); if (p.HasValue) { ComputeCurrentParameter(document.EditorTree.AstRoot, p.Value.Position); } } }, null, this.GetType()); } else { DismissSession(TextView, _shell); } } } }
public override CommandResult Invoke(Guid group, int id, object inputArg, ref object outputArg) { SnapshotSpan selectionSpan = TextView.Selection.StreamSelectionSpan.SnapshotSpan; var rSpans = TextView.BufferGraph.MapDownToFirstMatch( selectionSpan, SpanTrackingMode.EdgeInclusive, snapshot => snapshot.TextBuffer.ContentType.IsOfType(RContentTypeDefinition.ContentType) ); foreach (var spanToFormat in rSpans) { IREditorDocument document = REditorDocument.TryFromTextBuffer(spanToFormat.Snapshot.TextBuffer); AstRoot ast; if (document == null) { // For unit test purposes ast = inputArg as AstRoot; } else { ast = document.EditorTree.AstRoot; } if (ast != null) { RangeFormatter.FormatRange(TextView, spanToFormat.Snapshot.TextBuffer, new TextRange(spanToFormat.Start.Position, spanToFormat.Length), ast, REditorSettings.FormatOptions); } } return(new CommandResult(CommandStatus.Supported, 0)); }
private static bool ShouldFormatScope(ITextView textView, ITextBuffer textBuffer, int lineOffset) { IREditorDocument document = REditorDocument.TryFromTextBuffer(textBuffer); if (document != null) { IEditorTree tree = document.EditorTree; tree.EnsureTreeReady(); SnapshotPoint?caret = MapCaretToBuffer(textView, textBuffer); if (caret.HasValue) { try { int lineNumber = textBuffer.CurrentSnapshot.GetLineNumberFromPosition(caret.Value.Position); ITextSnapshotLine line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(Math.Max(lineNumber - 1, 0)); string lineText = line.GetText(); if (lineText.IndexOfAny(new char[] { '{', '}' }) >= 0) { IKeywordScopeStatement scopeStatement = tree.AstRoot.GetNodeOfTypeFromPosition <IKeywordScopeStatement>(caret.Value); return(scopeStatement != null); } } catch (Exception) { } } } return(false); }
/// <summary> /// Retrieves document instance from text buffer /// </summary> public static IREditorDocument FromTextBuffer(ITextBuffer textBuffer) { IREditorDocument document = TryFromTextBuffer(textBuffer); Debug.Assert(document != null, "No editor document available"); return(document); }
public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) { int hr = VSConstants.S_OK; int startPos = -1; int endPos = -1; var vsTextLines = TextBuffer.GetBufferAdapter <IVsTextLines>(); if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) { SnapshotSpan viewSpan = new SnapshotSpan(TextView.TextBuffer.CurrentSnapshot, startPos, endPos - startPos); NormalizedSnapshotSpanCollection mappedSpans = TextView.BufferGraph.MapDownToBuffer( viewSpan, SpanTrackingMode.EdgeInclusive, TextBuffer); Debug.Assert(mappedSpans.Count == 1); if (mappedSpans.Count > 0) { IREditorDocument document = REditorDocument.TryFromTextBuffer(TextBuffer); if (document != null) { document.EditorTree.EnsureTreeReady(); RangeFormatter.FormatRange(TextView, TextBuffer, new TextRange(mappedSpans[0].Start, mappedSpans[0].Length), document.EditorTree.AstRoot, REditorSettings.FormatOptions); } } } return(hr); }
/// <summary> /// Maps given point from view buffer to R editor buffer /// </summary> public static SnapshotPoint?MapPointFromView(ITextView textView, SnapshotPoint point) { ITextBuffer rBuffer; SnapshotPoint?documentPoint = null; IREditorDocument document = REditorDocument.FindInProjectedBuffers(textView.TextBuffer); if (document != null) { rBuffer = document.TextBuffer; } else { // Last resort, typically in unit tests when document is not available rBuffer = REditorDocument.FindRBuffer(textView.TextBuffer); } if (rBuffer != null) { if (textView.BufferGraph != null) { documentPoint = textView.MapDownToBuffer(point, rBuffer); } else { documentPoint = point; } } return(documentPoint); }
public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> quickInfoContent, out ITrackingSpan applicableToSpan) { applicableToSpan = null; SnapshotPoint?triggerPoint = session.GetTriggerPoint(_subjectBuffer.CurrentSnapshot); if (!triggerPoint.HasValue) { return; } int position = triggerPoint.Value; if (_lastPosition == position) { return; } _lastPosition = position; ITextSnapshot snapshot = triggerPoint.Value.Snapshot; IREditorDocument document = REditorDocument.TryFromTextBuffer(_subjectBuffer); if (document != null) { // Document may be null in REPL window as projections are not // getting set immediately or may change as user moves mouse over. AugmentQuickInfoSession(document.EditorTree.AstRoot, position, session, quickInfoContent, out applicableToSpan, (object o) => RetriggerQuickInfoSession(o as IQuickInfoSession)); } }
/// <summary> /// Creates an <see cref="IBraceCompletionContext"/> to handle /// language-specific actions such as parsing and formatting. /// </summary> /// <remarks> /// Opening points within strings and comments are usually invalid points to start /// an <see cref="IBraceCompletionSession"/> and will return false. /// </remarks> /// <param name="textView">View containing the <paramref name="openingPoint"/>.</param> /// <param name="openingPoint">Insertion point of the <paramref name="openingBrace"/>.</param> /// <param name="openingBrace">Opening brace that has been typed by the user.</param> /// <param name="closingBrace">Closing brace character</param> /// <param name="context">Brace completion context if created.</param> /// <returns>Returns true if the <paramref name="openingPoint"/> /// was a valid point in the buffer to start a <see cref="IBraceCompletionSession"/>. /// </returns> public bool TryCreateContext(ITextView textView, SnapshotPoint openingPoint, char openingBrace, char closingBrace, out IBraceCompletionContext context) { IREditorDocument document = REditorDocument.TryFromTextBuffer(openingPoint.Snapshot.TextBuffer); if (document != null) { var ast = document.EditorTree.AstRoot; // We don't want to complete inside strings if (ast.IsPositionInsideString(openingPoint.Position)) { context = null; return(false); } // We don't want to complete inside comments int index = ast.Comments.GetItemContaining(openingPoint.Position); if (index >= 0) { context = null; return(false); } } context = new BraceCompletionContext(); return(true); }
/// <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); }
public RSuggestedActionSource(ITextView textView, ITextBuffer textBuffer, IEnumerable<IRSuggestedActionProvider> suggestedActionProviders, ICoreShell shell) { _textBuffer = textBuffer; _textView = textView; _textView.Caret.PositionChanged += OnCaretPositionChanged; _suggestedActionProviders = suggestedActionProviders; _document = REditorDocument.TryFromTextBuffer(_textBuffer); ServiceManager.AddService(this, _textView, shell); }
public override void Undo() { IREditorDocument document = REditorDocument.TryFromTextBuffer(TextBuffer); if (document != null) { document.EndMassiveChange(); } }
public RSuggestedActionSource(ITextView textView, ITextBuffer textBuffer, IEnumerable <IRSuggestedActionProvider> suggestedActionProviders) { _textBuffer = textBuffer; _textView = textView; _textView.Caret.PositionChanged += OnCaretPositionChanged; _suggestedActionProviders = suggestedActionProviders; _document = REditorDocument.TryFromTextBuffer(_textBuffer); ServiceManager.AddService(this, _textView); }
public ROutlineRegionBuilder(IREditorDocument document) : base(document.EditorTree.TextBuffer) { EditorDocument = document; EditorDocument.DocumentClosing += OnDocumentClosing; EditorTree = document.EditorTree; EditorTree.UpdateCompleted += OnTreeUpdateCompleted; }
public ROutlineRegionBuilder(IREditorDocument document, IEditorShell shell) : base(document.EditorTree.TextBuffer, shell) { EditorDocument = document; EditorDocument.DocumentClosing += OnDocumentClosing; EditorTree = document.EditorTree; EditorTree.UpdateCompleted += OnTreeUpdateCompleted; EditorTree.Closing += OnEditorTreeClosing; }
public void Dispose() { if (_textView != null) { _textView.Caret.PositionChanged -= OnCaretPositionChanged; _document = null; _textBuffer = null; _textView = null; } }
public ROutlineRegionBuilder(IREditorDocument document, IEditorShell shell) : base(document.EditorTree.TextBuffer, shell) { EditorDocument = document; EditorDocument.DocumentClosing += OnDocumentClosing; EditorTree = document.EditorTree; EditorTree.UpdateCompleted += OnTreeUpdateCompleted; EditorTree.Closing += OnEditorTreeClosing; }
private RSuggestedActionSource(ITextView textView, ITextBuffer textBuffer, IEnumerable <IRSuggestedActionProvider> suggestedActionProviders, ICoreShell shell) { _textBuffer = textBuffer; _textView = textView; _textView.Caret.PositionChanged += OnCaretPositionChanged; _suggestedActionProviders = suggestedActionProviders; _document = _textBuffer.GetEditorDocument <IREditorDocument>(); _document.Closing += OnDocumentClosing; }
public static bool IsSyntaxCheckEnabled(ITextBuffer textBuffer) { IREditorDocument document = REditorDocument.FromTextBuffer(textBuffer); if (document != null) { return(document.IsTransient ? REditorSettings.SyntaxCheckInRepl : REditorSettings.SyntaxCheck); } return(false); }
public ROutlineRegionBuilder(IREditorDocument document, IServiceContainer services) : base(document.EditorTree.TextBuffer(), services, services.GetService <IREditorSettings>().EnableOutlining) { EditorDocument = document; EditorDocument.Closing += OnDocumentClosing; EditorTree = document.EditorTree; EditorTree.UpdateCompleted += OnTreeUpdateCompleted; EditorTree.Closing += OnEditorTreeClosing; }
public void Dispose() { if (_textView != null) { ServiceManager.RemoveService <RSuggestedActionSource>(_textView); _textView.Caret.PositionChanged -= OnCaretPositionChanged; _document = null; _textBuffer = null; _textView = null; } }
private void OnDocumentClosing(object sender, EventArgs e) { if (_document != null) { _idleTime.Idle -= OnIdle; _document.EditorTree.UpdateCompleted -= OnTreeUpdateCompleted; _document.Closing -= OnDocumentClosing; _document = null; } }
private static AstRoot UpdateAst(ITextBuffer textBuffer) { IREditorDocument document = REditorDocument.TryFromTextBuffer(textBuffer); if (document != null) { document.EditorTree.EnsureTreeReady(); return(document.EditorTree.AstRoot); } return(RParser.Parse(new TextProvider(textBuffer.CurrentSnapshot))); }
private void CreateAsyncSession(IREditorDocument document, int position, ICompletionSession session, IList<CompletionSet> completionSets) { _asyncSession = session; _asyncSession.Properties.AddProperty(_asyncIntellisenseSession, String.Empty); document.EditorTree.ProcessChangesAsync(TreeUpdatedCallback); }
public void Dispose() { if (_textView != null) { ServiceManager.RemoveService<RSuggestedActionSource>(_textView); _textView.Caret.PositionChanged -= OnCaretPositionChanged; _document = null; _textBuffer = null; _textView = null; } }