public void TextRange_CompareToTest() { TextRange r1 = TextRange.FromBounds(1, 1); r1.Equals(new object()).Should().BeFalse(); r1.Equals(null).Should().BeFalse(); }
public void FormatConditional(string original, int start, int end, string expected) { AstRoot ast; ITextView textView = TextViewTest.MakeTextView(original, out ast); RangeFormatter.FormatRange(textView, textView.TextBuffer, TextRange.FromBounds(start, end), new RFormatOptions(), _editorShell); string actual = textView.TextBuffer.CurrentSnapshot.GetText(); actual.Should().Be(expected); }
public void TextRangeCollection_AddSorted() { ITextRange[] ranges = new ITextRange[3]; ranges[0] = TextRange.FromBounds(1, 2); ranges[1] = TextRange.FromBounds(3, 5); ranges[2] = TextRange.FromBounds(5, 7); TextRangeCollection <ITextRange> target = new TextRangeCollection <ITextRange>(); target.Count.Should().Be(0); target.Add(ranges[2]); target.Count.Should().Be(1); target.AddSorted(ranges[0]); target.Count.Should().Be(2); target.Start.Should().Be(1); target.End.Should().Be(7); target[0].Start.Should().Be(1); target[1].Start.Should().Be(5); target.AddSorted(ranges[1]); target.Count.Should().Be(3); target.Start.Should().Be(1); target.End.Should().Be(7); target[0].Start.Should().Be(1); target[1].Start.Should().Be(3); target[2].Start.Should().Be(5); target.Start.Should().Be(1); target.End.Should().Be(7); }
void ReadInlineCodeBlock() { using (var peek = Peek()) { stream.MoveToNextChar(); // Report `` as an empty code block; otherwise, the artifact isn't detected properly. //if (stream.CurrentChar == '`') // return; while (stream.CurrentChar != '`') { if (stream.IsAtNewLine() || stream.IsEndOfStream()) { return; } stream.MoveToNextChar(); } ReportArtifact(new Artifact( ArtifactTreatAs.Code, TextRange.FromBounds(peek.StartPosition, stream.Position + 1), 1, 1, MarkdownClassificationTypes.MarkdownCode, true )); peek.Consume(); } }
public void TextRangeCollection_RemoveInRangeTest5() { TextRangeCollection <TextRange> target = MakeCollection(); target.RemoveInRange(TextRange.FromBounds(0, 6)); target.Count.Should().Be(0); }
internal ITextRange FindEndOfBlock(string endTag, bool simpleSearch = false) { bool ignoreCase = ParsingMode == ParsingMode.Html; int start = _cs.Position; if (simpleSearch) { int pos = _cs.Text.IndexOf(endTag, start, ignoreCase); _cs.Position = pos >= 0 ? pos : _cs.Position + _cs.DistanceFromEnd; } else { // Plain text search for script or style end tags // with artifact processing while (!_cs.IsEndOfStream()) { if (_cs.CurrentChar == '<' && _cs.NextChar == '/') { if (_cs.CompareTo(_cs.Position, endTag.Length, endTag, true)) { break; } } _cs.MoveToNextChar(); } } return(TextRange.FromBounds(start, _cs.Position)); }
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)); }
private void BuildLanguageBlockCollection() { var tokenizer = new MdTokenizer(); var tokens = tokenizer.Tokenize(TextBuffer.CurrentSnapshot.GetText()); var rCodeTokens = tokens.Where(t => { var mct = t as MarkdownCodeToken; return(mct != null && mct.LeadingSeparatorLength > 1); }); // TODO: incremental updates Blocks.Clear(); _separators.Clear(); foreach (MarkdownCodeToken t in rCodeTokens) { // Verify that code block is properly terminated. // If not, it ends at the end of the buffer. var text = t.GetText(TextBuffer.CurrentSnapshot); _separators.Add(new TextRange(t.Start, t.LeadingSeparatorLength)); // ```r{ or `r if (t.IsWellFormed) { // Count backticks Blocks.Add(TextRange.FromBounds(t.Start + t.LeadingSeparatorLength, t.End - t.TrailingSeparatorLength)); _separators.Add(new TextRange(t.End - t.TrailingSeparatorLength, t.TrailingSeparatorLength)); } else { Blocks.Add(TextRange.FromBounds(t.Start + t.LeadingSeparatorLength, t.End)); } } }
private bool HandleKeyword() { var start = _cs.Position; if (MoveToKeywordEnd()) { AddToken(RdTokenType.Keyword, start, _cs.Position - start); SkipWhitespace(); if (_cs.CurrentChar == '{' || _cs.CurrentChar == '[') { var keyword = _cs.Text.GetText(TextRange.FromBounds(start, _cs.Position)).Trim(); var contentType = RdBlockContentType.GetBlockContentType(keyword); if (_currentContentType != contentType) { _currentContentType = contentType; Debug.Assert(_tokens[_tokens.Count - 1].TokenType == RdTokenType.Keyword); _tokens[_tokens.Count - 1].ContentTypeChange = true; } // Handle argument sequence like \latex[0]{foo} or \item{}{} while (_cs.CurrentChar == '{' || _cs.CurrentChar == '[') { HandleKeywordArguments(contentType); } } return(true); } return(false); }
private void TokenFromPosition(ITextSnapshot snapshot, int position, out int itemIndex, out int offset) { // Normally token stream does not change after formatting so we can simply rely on the fact // that caret position is going to remain relative to the same token index itemIndex = -1; offset = 0; // Expand range to include the next line. This is needed when user introduces line break. var lineNumber = snapshot.GetLineNumberFromPosition(_changingRange.End); if (lineNumber < snapshot.LineCount - 1) { var end = snapshot.GetLineFromLineNumber(lineNumber + 1).End; _changingRange = TextRange.FromBounds(_changingRange.Start, end); } var tokenizer = new RTokenizer(); IReadOnlyTextRangeCollection <RToken> tokens = tokenizer.Tokenize(new TextProvider(snapshot), _changingRange.Start, _changingRange.Length, true); // Check if position is adjacent to previous token int prevItemIndex = tokens.GetFirstItemBeforePosition(position); if (prevItemIndex >= 0 && tokens[prevItemIndex].End == position) { itemIndex = prevItemIndex; offset = -tokens[itemIndex].Length; return; } int nextItemIndex = tokens.GetFirstItemAfterOrAtPosition(position); if (nextItemIndex >= 0) { // If two tokens are adjacent, gravity is negative, i.e. caret travels // with preceding token so it won't just to aniother line if, say, // formatter decides to insert a new line between tokens. if (nextItemIndex > 0 && tokens[nextItemIndex - 1].End == tokens[nextItemIndex].Start) { nextItemIndex--; } offset = tokens[nextItemIndex].Start - position; itemIndex = nextItemIndex; return; } // We are past last token if (tokens.Count > 0) { itemIndex = tokens.Count - 1; offset = tokens[itemIndex].Start - position; } else { itemIndex = -1; offset = position; } }
public void TextRangeCollection_ItemsInRangeTest() { TextRangeCollection <TextRange> target = MakeCollection(); IReadOnlyList <TextRange> list = target.ItemsInRange(TextRange.EmptyRange); list.Should().BeEmpty(); list = target.ItemsInRange(TextRange.FromBounds(-10, -1)); list.Should().BeEmpty(); list = target.ItemsInRange(TextRange.FromBounds(0, Int32.MaxValue)); list.Should().HaveCount(3); list = target.ItemsInRange(TextRange.FromBounds(Int32.MinValue / 2, Int32.MaxValue / 2)); list.Should().HaveCount(3); list = target.ItemsInRange(TextRange.FromBounds(1, 7)); list.Should().HaveCount(3); list = target.ItemsInRange(TextRange.FromBounds(0, 8)); list.Should().HaveCount(3); list = target.ItemsInRange(TextRange.FromBounds(1, 1)); list.Should().BeEmpty(); // Zero-length ranges can't contain anything list = target.ItemsInRange(TextRange.FromBounds(1, 2)); list.Should().HaveCount(1); list = target.ItemsInRange(TextRange.FromBounds(1, 3)); list.Should().HaveCount(1); list = target.ItemsInRange(TextRange.FromBounds(1, 4)); list.Should().HaveCount(2); }
public void TokenStreamLineBreakTest() { var tokens = new[] { new TestToken(TestTokenType.Token1, TextRange.FromBounds(0, 1)), new TestToken(TestTokenType.Token2, TextRange.FromBounds(3, 4)), new TestToken(TestTokenType.Token3, TextRange.FromBounds(6, 8)), new TestToken(TestTokenType.Token1, TextRange.FromBounds(12, 20)), new TestToken(TestTokenType.Token2, TextRange.FromBounds(20, 21)), }; var ts = CreateTokenStream(tokens); ITextProvider textProvider = new TextStream("1 2 11 \r\n12345678x"); ts.IsLineBreakAfter(textProvider, ts.Position).Should().BeFalse(); ts.Advance(2); ts.IsLineBreakAfter(textProvider, ts.Position).Should().BeTrue(); ts.Advance(-1); ts.IsLineBreakAfter(textProvider, ts.Position).Should().BeFalse(); ts.MoveToNextLine(textProvider); ts.CurrentToken.Should().HaveType(TestTokenType.Token1); string s = textProvider.GetText(ts.CurrentToken); s.Should().Be("12345678"); }
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 BuildLanguageBlockCollection() { var tokenizer = new MdTokenizer(); var tokens = tokenizer.Tokenize(TextBuffer.CurrentSnapshot.GetText()); var rCodeTokens = tokens.Where(t => t.TokenType == MarkdownTokenType.Code); // TODO: incremental updates Blocks.Clear(); _separators.Clear(); foreach (var t in rCodeTokens) { // Verify that code block is properly terminated. // If not, it ends at the end of the buffer. _separators.Add(new TextRange(t.Start, 5)); if (t.IsWellFormed) { Blocks.Add(TextRange.FromBounds(t.Start + 3, t.End - 3)); _separators.Add(new TextRange(t.End - 3, 3)); } else { Blocks.Add(TextRange.FromBounds(t.Start + 3, t.End)); } } }
public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out var startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out var endPos))) { var textBuffer = vsTextLines.ToITextBuffer(_services); var range = TextRange.FromBounds(startPos, endPos); var snapshot = textBuffer.CurrentSnapshot; var point = snapshot.CreateTrackingPoint(range.End, PointTrackingMode.Positive); var text = snapshot.GetText(range.ToSpan()); var line = snapshot.GetLineFromPosition(range.Start); var lineTail = snapshot.GetText(Span.FromBounds(range.End, line.End)); var formatter = new RangeFormatter(_services); formatter.FormatRange(TextView.ToEditorView(), textBuffer.ToEditorBuffer(), range); // Do not trim whitespace after standalone operators if (IsStandaloneOperator(text) && string.IsNullOrEmpty(lineTail)) { textBuffer.Insert(point.GetPosition(textBuffer.CurrentSnapshot), " "); } } return(VSConstants.S_OK); }
public static string FromTokens(RdParseContext context, int startTokenIndex, int endTokenIndex) { Debug.Assert(startTokenIndex >= 0 && startTokenIndex < endTokenIndex); // Clean descripton so it only consists of plain text var sb = new StringBuilder(); for (int i = startTokenIndex; i < endTokenIndex; i++) { TextRange range = TextRange.FromBounds(context.Tokens[i].End, context.Tokens[i + 1].Start); string s = context.TextProvider.GetText(range); s = CleanRawRdText(s); if (!string.IsNullOrWhiteSpace(s) && (sb.Length > 0 && !char.IsWhiteSpace(sb[sb.Length - 1]) && char.IsLetterOrDigit(s[0]))) { sb.Append(' '); } sb.Append(s); } return(sb.ToString()); }
public static bool FormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options) { ITextSnapshot snapshot = textBuffer.CurrentSnapshot; int start = formatRange.Start; int end = formatRange.End; // When user clicks editor margin to select a line, selection actually // ends in the beginning of the next line. In order to prevent formatting // of the next line that user did not select, we need to shrink span to // format and exclude the trailing line break. ITextSnapshotLine line = snapshot.GetLineFromPosition(formatRange.End); if (line.Start.Position == formatRange.End && formatRange.Length > 0) { if (line.LineNumber > 0) { line = snapshot.GetLineFromLineNumber(line.LineNumber - 1); end = line.End.Position; start = Math.Min(start, end); } } // Expand span to include the entire line ITextSnapshotLine startLine = snapshot.GetLineFromPosition(start); ITextSnapshotLine endLine = snapshot.GetLineFromPosition(end); formatRange = TextRange.FromBounds(startLine.Start, endLine.End); return(FormatRangeExact(textView, textBuffer, formatRange, options)); }
private ITrackingTextRange GetApplicableSpan(RFunctionSignatureInfo signatureInfo, IRIntellisenseContext context) { var snapshot = context.EditorBuffer.CurrentSnapshot; var start = signatureInfo.FunctionCall.OpenBrace.End; var end = Math.Min(signatureInfo.FunctionCall.SignatureEnd, snapshot.Length); return(snapshot.CreateTrackingRange(TextRange.FromBounds(start, end))); }
private static string GetLineTextBeforePosition(ITextProvider tp, int position) { var i = position - 1; for (; i >= 0 && !tp[i].IsLineBreak(); i--) { } return(tp.GetText(TextRange.FromBounds(i + 1, position))); }
private static string GetLineTextAfterPosition(ITextProvider tp, int position) { var i = position + 1; for (; i < tp.Length && !tp[i].IsLineBreak(); i++) { } return(tp.GetText(TextRange.FromBounds(position + 1, i))); }
private static IValidationError SpacesInsideParenthesisCheck(IAstNode node, ILintOptions options, bool projectedBuffer) { // There should be no space after (, [ or [[ and no space before ), ] or ]] // unless ] or ]] is preceded by a comma as in x[1, ] if (!options.SpacesInsideParenthesis || !(node is TokenNode t)) { return(null); } var tp = node.Root.TextProvider; switch (t.Token.TokenType) { case RTokenType.OpenBrace: case RTokenType.OpenSquareBracket: case RTokenType.OpenDoubleSquareBracket: // x[1, OK x( 2) is not if (!tp.IsNewLineAfterPosition(node.End) && tp.IsWhitespaceAfterPosition(node.End - 1)) { var lineEnd = tp.IndexOf('\n', node.End); lineEnd = lineEnd >= 0 ? lineEnd : tp.Length; var text = tp.GetText(TextRange.FromBounds(node.End, lineEnd)); var wsEnd = text.IndexWhere(ch => !char.IsWhiteSpace(ch)).FirstOrDefault(); wsEnd = wsEnd > 0 ? wsEnd + node.End : tp.Length; return(new ValidationWarning(TextRange.FromBounds(node.End, wsEnd), Resources.Lint_SpaceAfterLeftParenthesis, ErrorLocation.Token)); } break; case RTokenType.CloseBrace: // () is OK, (,,,) is OK, x( ) is not OK. But we do allow line break before ) if (tp.IsWhitespaceBeforePosition(node.Start) && !tp.IsNewLineBeforePosition(node.Start)) { var i = node.Start - 1; for (; i >= 0; i--) { if (!char.IsWhiteSpace(tp[i]) || tp[i] == '\r' || tp[i] == '\n') { i++; break; } } i = Math.Max(i, 0); return(new ValidationWarning(TextRange.FromBounds(i, node.Start), Resources.Lint_SpaceBeforeClosingBrace, ErrorLocation.Token)); } break; case RTokenType.CloseSquareBracket: case RTokenType.CloseDoubleSquareBracket: // x[1] is OK, x[1,] is not OK, should be x[1, ] var prevChar = node.Start > 0 ? tp[node.Start - 1] : '\0'; if (!tp.IsWhitespaceAfterPosition(node.End - 1) && prevChar == ',') { return(new ValidationWarning(node, Resources.Lint_NoSpaceBetweenCommaAndClosingBracket, ErrorLocation.Token)); } break; } return(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); })); }
public void FormatScope(string content, int start, int end, string expected) { var editorView = TextViewTest.MakeTextView(content, out AstRoot ast); _formatter.FormatRange(editorView, editorView.EditorBuffer, TextRange.FromBounds(start, end)); var actual = editorView.EditorBuffer.CurrentSnapshot.GetText(); actual.Should().Be(expected); }
private void AppendTextBeforeToken() { int start = _tokens.Position > 0 ? _tokens.PreviousToken.End : 0; int end = _tokens.IsEndOfStream() ? _textProvider.Length : _tokens.CurrentToken.Start; string text = _textProvider.GetText(TextRange.FromBounds(start, end)); if (string.IsNullOrWhiteSpace(text)) { // Append any user-entered whitespace. We preserve // line breaks but trim unnecessary spaces such as // on empty lines. We must, however, preserve // user indentation in long argument lists and // in expresions split into multiple lines. // We preserve user indentation of last token was // open brace, square bracket, comma or an operator bool preserveUserIndent = false; if (_tokens.Position > 0) { switch (_tokens.PreviousToken.TokenType) { case RTokenType.OpenBrace: case RTokenType.OpenSquareBracket: case RTokenType.OpenDoubleSquareBracket: case RTokenType.Comma: case RTokenType.Operator: preserveUserIndent = true; break; } } _tb.CopyPrecedingLineBreaks(_textProvider, end); if (preserveUserIndent) { int lastLineBreakIndex = text.LastIndexOfAny(CharExtensions.LineBreakChars); if (lastLineBreakIndex >= 0) { text = text.Substring(lastLineBreakIndex + 1); int textIndentInSpaces = IndentBuilder.TextIndentInSpaces(text, _options.TabSize); text = IndentBuilder.GetIndentString(textIndentInSpaces, _indentBuilder.IndentType, _indentBuilder.TabSize); _tb.AppendPreformattedText(text); } } else { _tb.SoftIndent(); } } else { // If there is unrecognized text between tokens, append it verbatim _tb.AppendPreformattedText(text); } }
public void FormatSimpleScope() { AstRoot ast; ITextView textView = TextViewTest.MakeTextView("{}", out ast); RangeFormatter.FormatRange(textView, textView.TextBuffer, TextRange.FromBounds(0, 1), ast, new RFormatOptions()); string actual = textView.TextBuffer.CurrentSnapshot.GetText(); actual.Should().Be("{ }"); }
public void Select(VirtualSnapshotPoint anchorPoint, VirtualSnapshotPoint activePoint) { int anchor = anchorPoint.Position.Position; int pt = activePoint.Position.Position; IsReversed = pt < anchor; _range = IsReversed ? TextRange.FromBounds(pt, anchor) : TextRange.FromBounds(anchor, pt); SelectionChanged?.Invoke(TextView, EventArgs.Empty); }
public void TextRangeCollection_RemoveInRangeTest6() { TextRangeCollection <TextRange> target = MakeCollection(); target.RemoveInRange(TextRange.FromBounds(0, 5)); AssertEquals(target, 5, 7); target.Start.Should().Be(5); target.End.Should().Be(7); }
public void Select(SnapshotSpan selectionSpan, bool isReversed) { IsReversed = isReversed; _range = isReversed ? TextRange.FromBounds(selectionSpan.End.Position, selectionSpan.Start.Position) : TextRange.FromBounds(selectionSpan.Start.Position, selectionSpan.End.Position); SelectionChanged?.Invoke(TextView, EventArgs.Empty); }
public void TextRangeCollection_RemoveInRangeTest2() { TextRangeCollection <TextRange> target = MakeCollection(); target.RemoveInRange(TextRange.FromBounds(Int32.MinValue / 2, Int32.MaxValue / 2)); target.Count.Should().Be(0); target.Start.Should().Be(0); target.End.Should().Be(0); }
private static TextRangeCollection <TextRange> MakeCollection() { var ranges = new TextRange[3]; ranges[0] = TextRange.FromBounds(1, 2); ranges[1] = TextRange.FromBounds(3, 5); ranges[2] = TextRange.FromBounds(5, 7); return(new TextRangeCollection <TextRange>(ranges)); }