private static IEnumerable <string> MakeQuickInfos( IEnumerable <IRFunctionQuickInfo> infos, IEditorBufferSnapshot snapshot, int position, out ITrackingSpan applicableSpan) { applicableSpan = null; var list = new List <string>(); int s = 0, e = 0, length = int.MaxValue; foreach (var info in infos) { var start = info.ApplicableToRange.GetStartPoint(snapshot); var end = info.ApplicableToRange.GetEndPoint(snapshot); if (start <= position && position < end) { var content = info.Content.FirstOrDefault(); if (!string.IsNullOrEmpty(content)) { list.Add(content); s = Math.Max(s, start); e = Math.Min(e, end); var l = e - s; if (l < length) { applicableSpan = info.ApplicableToRange.As <ITrackingSpan>(); length = l; } } } } return(list); }
public SearchParams(Uri uri, IEditorBufferSnapshot snapshot, AstRoot ast) { Symbols = new List <SymbolInformation>(); Uri = uri; Snapshot = snapshot; Ast = ast; }
public static ITextRange ToTextRange(this Range range, IEditorBufferSnapshot snapshot) { var start = range.Start.ToStreamPosition(snapshot); var end = range.End.ToStreamPosition(snapshot); return(TextRange.FromBounds(start, end)); }
/// <summary> /// Given position in the buffer finds index of the function parameter. /// </summary> public static int ComputeCurrentParameter(this ISignatureInfo signatureInfo, IEditorBufferSnapshot snapshot, AstRoot ast, int position, IREditorSettings settings) { var parameterInfo = ast.GetSignatureInfoFromBuffer(snapshot, position); var index = 0; if (parameterInfo != null) { index = parameterInfo.ParameterIndex; if (parameterInfo.NamedParameter) { // A function f <- function(foo, bar) is said to have formal parameters "foo" and "bar", // and the call f(foo=3, ba=13) is said to have (actual) arguments "foo" and "ba". // R first matches all arguments that have exactly the same name as a formal parameter. // Two identical argument names cause an error. Then, R matches any argument names that // partially matches a(yet unmatched) formal parameter. But if two argument names partially // match the same formal parameter, that also causes an error. Also, it only matches // formal parameters before ... So formal parameters after ... must be specified using // their full names. Then the unnamed arguments are matched in positional order to // the remaining formal arguments. var argumentIndexInSignature = signatureInfo.GetArgumentIndex(parameterInfo.ParameterName, settings.PartialArgumentNameMatch); if (argumentIndexInSignature >= 0) { index = argumentIndexInSignature; } } } return(index); }
public EditorLine(IEditorBufferSnapshot snapshot, int start, int length, int lineBreakLength, int lineNumber) : base(start, length) { LineBreakLength = lineBreakLength; Snapshot = snapshot; LineNumber = lineNumber; }
public static Position ToLinePosition(this IEditorBufferSnapshot snapshot, int position) { var line = snapshot.GetLineFromPosition(position); return(new Position { Line = line.LineNumber, Character = position - line.Start }); }
public Task <TextEdit[]> FormatRangeAsync(IEditorBufferSnapshot snapshot, Range range) { var editorBuffer = snapshot.EditorBuffer; var editorView = new EditorView(editorBuffer, range.ToTextRange(snapshot).Start); var rangeFormatter = new RangeFormatter(_services, editorView, editorBuffer, new IncrementalTextChangeHandler()); return(DoFormatActionAsync(snapshot, () => rangeFormatter.FormatRange(range.ToTextRange(snapshot)))); }
public ISnapshotPoint MapToView(IEditorBufferSnapshot snapshot, int position) { var target = _textView.BufferGraph .MapUpToBuffer( new SnapshotPoint(snapshot.As <ITextSnapshot>(), position), PointTrackingMode.Positive, PositionAffinity.Successor, _textView.TextBuffer); return(target.HasValue ? new EditorSnapshotPoint(_textView.TextBuffer.CurrentSnapshot, target.Value) : null); }
public Task <TextEdit[]> FormatAsync(IEditorBufferSnapshot snapshot) { var settings = _services.GetService <IREditorSettings>(); return(DoFormatActionAsync(snapshot, () => { var formattedText = new RFormatter(settings.FormatOptions).Format(snapshot.GetText()); snapshot.EditorBuffer.Replace(TextRange.FromBounds(0, snapshot.Length), formattedText); })); }
private static IEditorLine FindFirstNonEmptyLine(IEditorBufferSnapshot snapshot, int lineNumber) { for (int i = lineNumber; i < snapshot.LineCount; i++) { var line = snapshot.GetLineFromLineNumber(i); if (!string.IsNullOrWhiteSpace(line.GetText())) { return(line); } } return(null); }
public static bool IsPositionInNamespace(this IEditorBufferSnapshot snapshot, int position) { if (position > 0) { var line = snapshot.GetLineFromPosition(position); if (line.Length > 2 && position - line.Start > 2) { return(snapshot[position - 1] == ':'); } } return(false); }
private void FireChanged(int start, int oldLength, int newLength) { var oldTextProvider = new TextStream(CurrentSnapshot.GetText()); _version++; _currentSnapshot = new EditorBufferSnapshot(this, _content.ToString(), _version); var newTextProvider = new TextStream(_currentSnapshot.GetText()); var change = new TextChange(start, oldLength, newLength, oldTextProvider, newTextProvider); var args = new TextChangeEventArgs(change); ChangedHighPriority?.Invoke(this, args); Changed?.Invoke(this, args); }
private TextEdit[] DoFormatAction(IEditorBufferSnapshot snapshot, Action action) { if (snapshot == null) { return(new TextEdit[0]); } var before = snapshot; action(); var after = snapshot.EditorBuffer.CurrentSnapshot; return(GetDifference(before, after)); }
/// <summary> /// Processes text buffer changed accumulated so far. /// Typically called on idle. /// </summary> /// <param name="snapshot">New text buffer content</param> /// <param name="async">True if processing is to be done asynchronously. /// Non-async processing is typically used in unit tests only.</param> internal void ProcessPendingTextBufferChanges(IEditorBufferSnapshot snapshot, bool async) { Check.InvalidOperation(() => Thread.CurrentThread.ManagedThreadId == _ownerThreadId, _threadCheckMessage); if (ChangesPending) { if (async && (IsTaskRunning() || _backgroundParsingResults.Count > 0)) { // Try next time or we may end up spawning a lot of tasks return; } Run(isCancelledCallback => ProcessTextChange(snapshot, async, isCancelledCallback), async); } }
private async Task <TextEdit[]> DoFormatActionAsync(IEditorBufferSnapshot snapshot, Action action) { if (snapshot == null) { return(new TextEdit[0]); } await _services.MainThread().SwitchToAsync(); var before = snapshot; action(); var after = snapshot.EditorBuffer.CurrentSnapshot; return(GetDifference(before, after)); }
/// <summary> /// Determines whitespace difference between two snapshots /// </summary> /// <param name="before">Snapshot before the change</param> /// <param name="after">Snapshot after the change</param> /// <returns></returns> private static TextEdit[] GetDifference(IEditorBufferSnapshot before, IEditorBufferSnapshot after) { var tokenizer = new RTokenizer(); var oldTokens = tokenizer.Tokenize(before.GetText()); var newTokens = tokenizer.Tokenize(after.GetText()); if (newTokens.Count != oldTokens.Count) { return(new[] { new TextEdit { newText = after.GetText(), range = TextRange.FromBounds(0, before.Length).ToLineRange(before) } }); } var edits = new List <TextEdit>(); var oldEnd = before.Length; var newEnd = after.Length; for (var i = newTokens.Count - 1; i >= 0; i--) { var oldText = before.GetText(TextRange.FromBounds(oldTokens[i].End, oldEnd)); var newText = after.GetText(TextRange.FromBounds(newTokens[i].End, newEnd)); if (oldText != newText) { var range = new TextRange(oldTokens[i].End, oldEnd - oldTokens[i].End); edits.Add(new TextEdit { range = range.ToLineRange(before), newText = newText }); } oldEnd = oldTokens[i].Start; newEnd = newTokens[i].Start; } var r = TextRange.FromBounds(0, oldEnd); var oldTextBeforeFitstToken = before.GetText(r); var newTextBeforeFirstToken = after.GetText(TextRange.FromBounds(0, newEnd)); if (oldTextBeforeFitstToken != newTextBeforeFirstToken) { edits.Add(new TextEdit { newText = newTextBeforeFirstToken, range = r.ToLineRange(before) }); } return(edits.ToArray()); }
public Task <TextEdit[]> AutoformatAsync(IEditorBufferSnapshot snapshot, Position position, string typedChar) { var editorBuffer = snapshot.EditorBuffer; var editorView = new EditorView(editorBuffer, position.ToStreamPosition(snapshot)); var formatter = new AutoFormat(_services, editorView, editorBuffer, new IncrementalTextChangeHandler()); // AST build happens asynchronously, give it a chance to finish since // up -to-date AST improves outcome of the on-type formatting. var document = editorBuffer.GetEditorDocument <IREditorDocument>(); if (!document.EditorTree.IsReady) { SpinWait.SpinUntil(() => document.EditorTree.IsReady, 50); } return(DoFormatActionAsync(snapshot, () => formatter.HandleTyping(typedChar[0], position.ToStreamPosition(snapshot)))); }
private static ITextRange GetRoxygenBlockPosition(IEditorBufferSnapshot snapshot, int definitionStart) { var line = snapshot.GetLineFromPosition(definitionStart); for (var i = line.LineNumber - 1; i >= 0; i--) { var currentLine = snapshot.GetLineFromLineNumber(i); var lineText = currentLine.GetText().TrimStart(); if (lineText.Length > 0) { if (lineText.EqualsOrdinal("##")) { return(currentLine); } if (lineText.EqualsOrdinal("#'")) { return(null); } break; } } return(new TextRange(line.Start, 0)); }
public int GetStartPoint(IEditorBufferSnapshot snapshot) => _range.Start;
public SearchParams(Uri uri, IEditorBufferSnapshot snapshot, AstRoot ast) { Uri = uri; Snapshot = snapshot; Ast = ast; }
/// <summary> /// Main asyncronous task body /// </summary> private void ProcessTextChange(IEditorBufferSnapshot snapshot, bool async, Func <bool> isCancelledCallback) { lock (_disposeLock) { if (_editorTree == null || _disposed || isCancelledCallback()) { return; } EditorTreeChangeCollection treeChanges; // Cache id since it can change if task is canceled var taskId = TaskId; try { // We only need read lock since changes will be applied from the main thread if (async) { _editorTree.AcquireReadLock(_treeUserId); } else { _editorTree.GetAstRootUnsafe(); } treeChanges = new EditorTreeChangeCollection(snapshot.Version, true); var newTree = RParser.Parse(snapshot, _editorTree.ExpressionTermFilter); treeChanges.Append(new EditorTreeChange_NewTree(newTree)); } finally { if (async) { _editorTree?.ReleaseReadLock(_treeUserId); } } // Lock should be released at this point since actual application // of tree changes is going to be happen from the main thread. if (!isCancelledCallback() && treeChanges.Changes.Any()) { // Queue results for the main thread application. This must be done before // signaling that the task is complete since if EnsureProcessingComplete // is waiting it will want to apply changes itself rather than wait for // the DispatchOnUIThread to go though and hence it will need all changes // stored and ready for application. _backgroundParsingResults.Enqueue(treeChanges); } // Signal task complete now so if main thread is waiting // it can proceed and appy the changes immediately. SignalTaskComplete(taskId); if (_backgroundParsingResults.Count > 0) { // It is OK to post results while main thread might be working // on them since if if it does, by the time posted request comes // queue will already be empty. if (async) { // Post request to apply tree changes to the main thread. // This must NOT block or else task will never enter 'RanToCompletion' state. _services.MainThread().Post(ApplyBackgroundProcessingResults); } else { // When processing is synchronous, apply changes and fire events right away. ApplyBackgroundProcessingResults(); } } } }
public static int ToStreamPosition(this IEditorBufferSnapshot snapshot, int lineNumber, int charNumber) { var line = snapshot.GetLineFromLineNumber(lineNumber); return(line?.Start + charNumber ?? 0); }
public static int ToStreamPosition(this Position position, IEditorBufferSnapshot snapshot) => snapshot.ToStreamPosition(position.Line, position.Character);
public SnapshotPoint(IEditorBufferSnapshot snapshot, int position) { Snapshot = snapshot; Position = position; }
public static Range ToLineRange(this ITextRange textRange, IEditorBufferSnapshot snapshot) => new Range { Start = snapshot.ToLinePosition(textRange.Start), End = snapshot.ToLinePosition(textRange.End) };
public static Range ToLineRange(this IEditorBufferSnapshot snapshot, int start, int end) => new Range { Start = snapshot.ToLinePosition(start), End = snapshot.ToLinePosition(end) };
public int GetStartPoint(IEditorBufferSnapshot snapshot) => _span.GetStartPoint(snapshot.As <ITextSnapshot>());
public ViewCaretPosition(IEditorBufferSnapshot snapshot, int position) : base(snapshot, position) { }
public int GetEndPoint(IEditorBufferSnapshot snapshot) => _range.End;
public ISnapshotPoint MapToView(IEditorBufferSnapshot snapshot, int position) => new SnapshotPoint(EditorBuffer.CurrentSnapshot, position);