Example #1
0
        public static bool FormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange,
                                       AstRoot ast, RFormatOptions options, bool respectUserIndent = true) {
            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, ast, options, -1, respectUserIndent);
        }
Example #2
0
        public int IndexOf(string text, ITextRange range, bool ignoreCase) {
            for (int i = range.Start; i < range.End; i++) {
                bool found = true;
                int k = i;
                int j;

                for (j = 0; j < text.Length && k < range.End; j++, k++) {
                    char ch1 = text[j];
                    char ch2 = this[k];

                    if (ignoreCase) {
                        ch1 = Char.ToLowerInvariant(ch1);
                        ch2 = Char.ToLowerInvariant(ch2);
                    }

                    if (ch1 != ch2) {
                        found = false;
                        break;
                    }
                }

                if (found && j == text.Length) {
                    return i;
                }
            }

            return -1;
        }
Example #3
0
        public static void DoActionOnLines(ITextView textView, ITextBuffer textBuffer, ITextRange range, IEditorShell editorShell, Func<ITextSnapshotLine, bool> action, string actionName) {
            // When user clicks editor margin to select a line, selection actually
            // ends in the beginning of the next line. In order to prevent commenting
            // of the next line that user did not select, we need to shrink span to
            // format and exclude the trailing line break.

            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            ITextSnapshotLine line = snapshot.GetLineFromPosition(range.End);

            int start = range.Start;
            int end = range.End;

            if (line.Start.Position == range.End && range.Length > 0) {
                if (line.LineNumber > 0) {
                    line = snapshot.GetLineFromLineNumber(line.LineNumber - 1);
                    end = line.End.Position;
                    start = Math.Min(start, end);
                }
            }

            int startLineNumber = textBuffer.CurrentSnapshot.GetLineNumberFromPosition(start);
            int endLineNumber = textBuffer.CurrentSnapshot.GetLineNumberFromPosition(end);

            using (var undoAction = editorShell.CreateCompoundAction(textView, textBuffer)) {
                undoAction.Open(actionName);
                bool changed = false;
                for (int i = startLineNumber; i <= endLineNumber; i++) {
                    line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(i);
                    changed |= action(line);
                }
                if (changed) {
                    undoAction.Commit();
                }
            }
        }
Example #4
0
        /// <summary>
        /// Determines if element is a self-closing element (i.e. like &lt;br /&gt;
        /// </summary>
        /// <param name="textProvider">Text provider</param>
        /// <param name="prefixRange">Text range of the element prefix</param>
        /// <param name="nameRange">Text range of the element name</param>
        /// <returns>True if element is a self-closing element.</returns>
        public bool IsSelfClosing(ITextProvider textProvider, ITextRange prefixRange, ITextRange nameRange) {
            if (nameRange.Length == 0)
                return false;

            string name = textProvider.GetText(nameRange);
            if (name[0] == '!')
                return true; // bang tags are always self-closing

            if (prefixRange.Length == 0)
                return _defaultProvider.IsSelfClosing(textProvider, nameRange);

            string prefix = textProvider.GetText(prefixRange);

            IHtmlClosureProvider provider; ;
            _providers.TryGetValue(prefix, out provider);

            var textRangeProvider = provider as IHtmlClosureProviderTextRange;
            if (textRangeProvider != null)
                return textRangeProvider.IsSelfClosing(textProvider, nameRange);

            if (provider != null)
                return provider.IsSelfClosing(name);

            return false;
        }
Example #5
0
 public ValidationErrorBase(ITextRange range, string message, ErrorLocation location, ErrorSeverity severity) :
     base(range)
 {
     Message = message;
     Severity = severity;
     Location = location;
 }
Example #6
0
        public static AstRoot Parse(ITextProvider textProvider, ITextRange range, IExpressionTermFilter filter) {
            var tokenizer = new RTokenizer(separateComments: true);

            IReadOnlyTextRangeCollection<RToken> tokens = tokenizer.Tokenize(textProvider, range.Start, range.Length);
            TokenStream<RToken> tokenStream = new TokenStream<RToken>(tokens, new RToken(RTokenType.EndOfStream, TextRange.EmptyRange));

            return Parse(textProvider, range, tokenStream, tokenizer.CommentTokens, filter);
        }
Example #7
0
        internal WindowsRichEditRange(ITextRange range, WindowsRichEdit pattern)
        {
            Debug.Assert(range != null);
            Debug.Assert(pattern != null);

            _range = range;
            _pattern = pattern;
        }
Example #8
0
        public static ITextView MakeTextView(string content, ITextRange selectionRange) {
            TextBufferMock textBuffer = new TextBufferMock(content, RContentTypeDefinition.ContentType);
            TextViewMock textView = new TextViewMock(textBuffer);

            textView.Selection.Select(new SnapshotSpan(textBuffer.CurrentSnapshot,
                     new Span(selectionRange.Start, selectionRange.Length)), false);
            return textView;
        }
Example #9
0
 public ParseContext(ITextProvider textProvider, ITextRange range, TokenStream<RToken> tokens, IReadOnlyList<RToken> comments) {
     this.AstRoot = new AstRoot(textProvider);
     this.TextProvider = textProvider;
     this.Tokens = tokens;
     this.TextRange = range;
     this.Scopes = new Stack<IScope>();
     this.Expressions = new Stack<Expression>();
     this.Comments = comments;
 }
Example #10
0
        public IReadOnlyList<EditorErrorTag> ItemsInRange(ITextRange range) {
            IReadOnlyList<EditorErrorTag> list;

            lock (_lockObj) {
                list = _tags.ItemsInRange(range);
            }

            return list;
        }
        /// <summary>
        /// Writes a content of current range in form of valid xml.
        /// Places an artificial element xaml:FlowDocument as a root of output xml.
        /// </summary>
        /// <param name="xmlWriter">
        /// XmlWriter to which the range will be serialized
        /// </param>
        /// <param name="range">
        /// TextRange whose content is copied into XmlWriter xmlWriter.
        /// </param>
        /// <param name="useFlowDocumentAsRoot">
        /// true means that we need to serialize the whole FlowDocument - used in FileSave scenario;
        /// false means that we are in copy-paste scenario and will use Section or Span as a root - depending on context.
        /// </param>
        /// <param name="wpfPayload">
        /// When this parameter is not null, images are serialized.  When null, images are stripped out.
        /// </param>
        /// <param name="preserveTextElements">
        /// When TRUE, TextElements are serialized as-is.  When FALSE, they're upcast to their base type.
        /// </param>
        internal static void WriteXaml(XmlWriter xmlWriter, ITextRange range, bool useFlowDocumentAsRoot, WpfPayload wpfPayload, bool preserveTextElements)
        {
            // Set unindented formatting to avoid inserting insignificant whitespaces as significant ones
            Formatting saveWriterFormatting = Formatting.None;
            if (xmlWriter is XmlTextWriter)
            {
                saveWriterFormatting = ((XmlTextWriter)xmlWriter).Formatting;
                ((XmlTextWriter)xmlWriter).Formatting = Formatting.None;
            }

            // Get the default xamlTypeMapper.
            XamlTypeMapper xamlTypeMapper = XmlParserDefaults.DefaultMapper;

            // Identify structural scope of selection - nearest common ancestor
            ITextPointer commonAncestor = FindSerializationCommonAncestor(range);

            // Decide whether we need last paragraph merging or not
            bool lastParagraphMustBeMerged =
                !TextPointerBase.IsAfterLastParagraph(range.End) &&
                range.End.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementStart;

            // Write wrapping element with contextual properties
            WriteRootFlowDocument(range, commonAncestor, xmlWriter, xamlTypeMapper, lastParagraphMustBeMerged, useFlowDocumentAsRoot);

            // The ignoreWriteHyperlinkEnd flag will be set after call WriteOpeningTags.
            // If ignoreWriteHyperlinkEnd is true, WriteXamlTextSegment won't write Hyperlink end element
            // since Hyperlink writing opening tag is ignored by selecting the partial of Hyperlink.
            bool ignoreWriteHyperlinkEnd;
            List<int> ignoreList = new List<int>();

            // Start counting tags needed to be closed.
            // EmptyDocumentDepth==1 - counts FlowDocument opened in WriteRootFlowDocument above.
            int elementLevel = EmptyDocumentDepth + WriteOpeningTags(range, range.Start, commonAncestor, xmlWriter, xamlTypeMapper, /*reduceElement:*/wpfPayload == null, out ignoreWriteHyperlinkEnd, ref ignoreList, preserveTextElements);

            if (range.IsTableCellRange)
            {
                WriteXamlTableCellRange(xmlWriter, range, xamlTypeMapper, ref elementLevel, wpfPayload, preserveTextElements);
            }
            else
            {
                WriteXamlTextSegment(xmlWriter, range.Start, range.End, xamlTypeMapper, ref elementLevel, wpfPayload, ignoreWriteHyperlinkEnd, ignoreList, preserveTextElements);
            }

            // Close all remaining tags - scoping its End position
            Invariant.Assert(elementLevel >= 0, "elementLevel cannot be negative");
            while (elementLevel-- > 0)
            {
                xmlWriter.WriteFullEndElement();
            }

            // Restore xmlWriter's Formatting property
            if (xmlWriter is XmlTextWriter)
            {
                ((XmlTextWriter)xmlWriter).Formatting = saveWriterFormatting;
            }
        }
Example #12
0
        public static NextTokenType PeekNextToken(HtmlCharStream cs, int tagEnd, out ITextRange range) {
            NextTokenType tokenType = NextTokenType.Unknown;
            int current = cs.Position;

            if (cs.IsEndOfStream() || cs.Position == tagEnd) {
                range = new TextRange();
                return NextTokenType.None;
            }

            int start = cs.Position;

            while (cs.IsWhiteSpace())
                cs.MoveToNextChar();

            if (cs.IsEndOfStream() || cs.Position == tagEnd) {
                range = TextRange.FromBounds(start, cs.Position);
                return NextTokenType.Unknown;
            }

            if (cs.IsAtTagDelimiter()) {
                tokenType = NextTokenType.Tag;
            } else if (cs.CurrentChar == '=') {
                tokenType = NextTokenType.Equals;
            } else {
                int digits = 0;
                bool firstLetter = false;
                int length = 0;
                int chars = 0;

                if (cs.IsAnsiLetter())
                    firstLetter = true;

                while (!cs.IsEndOfStream() && !cs.IsWhiteSpace() && !cs.IsAtTagDelimiter() && cs.CurrentChar != '=' && cs.Position < tagEnd) {
                    if (cs.IsAnsiLetter() || cs.CurrentChar == '_' || cs.CurrentChar == '-')
                        chars++;
                    else if (cs.IsDecimal() || cs.CurrentChar == '.')
                        digits++;

                    cs.MoveToNextChar();
                    length++;
                }

                if (length > 0) {
                    if (length == digits)
                        tokenType = NextTokenType.Number;
                    else if (length == chars)
                        tokenType = NextTokenType.Letters;
                    else if (firstLetter)
                        tokenType = NextTokenType.Identifier;
                }
            }

            range = TextRange.FromBounds(start, cs.Position);
            cs.Position = current;
            return tokenType;
        }
        public CharacterStream(ITextProvider textProvider, ITextRange range) {
            _text = textProvider;

            int end = Math.Min(_text.Length, range.End);

            _range = TextRange.FromBounds(range.Start, end);

            Position = _range.Start;
            _currentChar = _text[_range.Start];
        }
Example #14
0
 public ParseContext(ITextProvider textProvider, ITextRange range, TokenStream<RToken> tokens, IReadOnlyList<RToken> comments, IExpressionTermFilter filter = null) {
     AstRoot = new AstRoot(textProvider);
     TextProvider = textProvider;
     Tokens = tokens;
     TextRange = range;
     Scopes = new Stack<IScope>();
     Expressions = new Stack<Expression>();
     Comments = comments;
     ExpressionTermFilter = filter ?? new DefaultExpressionTermFilter();
 }
Example #15
0
        /// <summary>
        /// Creates a new instance of BaseHighlighter
        /// </summary>
        /// <param name="document">Document to highlight</param>
        public BaseHighlighter(ITextDocument document)
        {
            this.document = document;

            // Much faster to keep a worker range rather than to keep requesting one from
            // the document
            this.workerRange = document.GetRange(0, 0);

            this._highlights = new List<Tuple<Regex, Action<ITextCharacterFormat>>>();

            // Add highlighting rules
            AddHighlightRules();
        }
Example #16
0
        /// <summary>
        /// Parse text from a text provider within a given range
        /// </summary>
        /// <param name="textProvider">Text provider</param>
        /// <param name="range">Range to parse</param>
        public static AstRoot Parse(ITextProvider textProvider, ITextRange range) {
            var tokenizer = new RTokenizer(separateComments: true);

            IReadOnlyTextRangeCollection<RToken> tokens = tokenizer.Tokenize(textProvider, range.Start, range.Length);
            TokenStream<RToken> tokenStream = new TokenStream<RToken>(tokens, new RToken(RTokenType.EndOfStream, TextRange.EmptyRange));

            ParseContext context = new ParseContext(textProvider, range, tokenStream, tokenizer.CommentTokens);

            context.AstRoot.Parse(context, context.AstRoot);
            context.AstRoot.Errors = new TextRangeCollection<IParseError>(context.Errors);

            return context.AstRoot;
        }
Example #17
0
        /// <summary>
        /// Determines if given element can be implicitly closed like &lt;li&gt; or &lt;td&gt; in HTML"
        /// </summary>
        /// <param name="text">Text provider</param>
        /// <param name="name">Element name</param>
        /// <returns>True if element can be implictly closed</returns>
        public bool IsImplicitlyClosed(ITextProvider text, ITextRange name, out string[] containerElementNames) {
            containerElementNames = null;

            if (name.Length < _minCharCountImplicitClosing || name.Length > _maxCharCountImplicitClosing)
                return false;

            bool found = FindElementName(text, name, _implicitlyClosingElementNameIndex, ignoreCase: true);
            if (found) {
                string elementName = text.GetText(name);
                containerElementNames = GetContainerElements(elementName);
            }
            return found;
        }
 protected ITextRange GetLanguageBlockOfLocation(int bufferPosition) {
     if (_cachedPosition != bufferPosition) {
         var items = Blocks.GetItemsContainingInclusiveEnd(bufferPosition);
         int index;
         if (items.Count > 0) {
             index = items[0];
         } else { 
             index = Blocks.GetItemAtPosition(bufferPosition);
         }
         _cachedLanguageBlock = index >= 0 ? Blocks[index] : null;
         _cachedPosition = bufferPosition;
     }
     return _cachedLanguageBlock;
 }
Example #19
0
        public static bool FormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options, IEditorShell editorShell) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            int start = formatRange.Start;
            int end = formatRange.End;

            if(!CanFormatRange(textView, textBuffer, formatRange, editorShell)) {
                return false;
            }

            // 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);

            // In case of formatting of multiline expressions formatter needs
            // to know the entire expression since otherwise it may not correctly
            // preserve user indentation. Consider 'x >% y' which is a plain statement
            // and needs to be indented at regular scope level vs
            //
            //      a %>% b %>%
            //          x %>% y
            //
            // where user indentation of 'x %>% y' must be preserved. We don't have
            // complete information here since expression may not be syntactically
            // correct and hence AST may not have correct information and besides,
            // the AST is damaged at this point. As a workaround, we will check 
            // if the previous line ends with an operator current line starts with 
            // an operator.
            int startPosition = FindStartOfExpression(textBuffer, startLine.Start);

            formatRange = TextRange.FromBounds(startPosition, endLine.End);
            return FormatRangeExact(textView, textBuffer, formatRange, options, editorShell);
        }
Example #20
0
        private static bool IsChangeDestructiveForChildNodes(IAstNode node, ITextRange changedRange) {
            if(changedRange.End <= node.Start || changedRange.Start >= node.End) {
                return false;
            }
            else if(node.Children.Count == 0) {
                return true;
            }

            bool result = false;
            foreach (var child in node.Children) {
                result |= IsChangeDestructiveForChildNodes(child, changedRange);
                if(result) {
                    break;
                }
            }

            return result;
        }
        /// <summary>
        /// Incrementally applies whitespace change to the buffer 
        /// having old and new tokens produced from the 'before formatting' 
        /// and 'after formatting' versions of the same text.
        /// </summary>
        /// <param name="textBuffer">Text buffer to apply changes to</param>
        /// <param name="newTextProvider">Text provider of the text fragment before formatting</param>
        /// <param name="newTextProvider">Text provider of the formatted text</param>
        /// <param name="oldTokens">Tokens from the 'before' text fragment</param>
        /// <param name="newTokens">Tokens from the 'after' text fragment</param>
        /// <param name="formatRange">Range that is being formatted in the text buffer</param>
        /// <param name="transactionName">Name of the undo transaction to open</param>
        /// <param name="selectionTracker">Selection tracker object that will save, track
        /// <param name="additionalAction">Action to perform after changes are applies by undo unit is not yet closed.</param>
        /// and restore selection after changes have been applied.</param>
        public static void ApplyChangeByTokens(
            ITextBuffer textBuffer,
            ITextProvider oldTextProvider,
            ITextProvider newTextProvider,
            IReadOnlyList<ITextRange> oldTokens,
            IReadOnlyList<ITextRange> newTokens,
            ITextRange formatRange,
            string transactionName,
            ISelectionTracker selectionTracker,
            IEditorShell editorShell,
            Action additionalAction = null) {

            Debug.Assert(oldTokens.Count == newTokens.Count);
            if (oldTokens.Count == newTokens.Count) {
                ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
                using (CreateSelectionUndo(selectionTracker, editorShell, transactionName)) {
                    using (ITextEdit edit = textBuffer.CreateEdit()) {
                        if (oldTokens.Count > 0) {
                            // Replace whitespace between tokens in reverse so relative positions match
                            int oldEnd = oldTextProvider.Length;
                            int newEnd = newTextProvider.Length;
                            string oldText, newText;
                            for (int i = newTokens.Count - 1; i >= 0; i--) {
                                oldText = oldTextProvider.GetText(TextRange.FromBounds(oldTokens[i].End, oldEnd));
                                newText = newTextProvider.GetText(TextRange.FromBounds(newTokens[i].End, newEnd));
                                if (oldText != newText) {
                                    edit.Replace(formatRange.Start + oldTokens[i].End, oldEnd - oldTokens[i].End, newText);
                                }
                                oldEnd = oldTokens[i].Start;
                                newEnd = newTokens[i].Start;
                            }
                            newText = newTextProvider.GetText(TextRange.FromBounds(0, newEnd));
                            edit.Replace(formatRange.Start, oldEnd, newText);
                        } else {
                            string newText = newTextProvider.GetText(TextRange.FromBounds(0, newTextProvider.Length));
                            edit.Replace(formatRange.Start, formatRange.Length, newText);
                        }
                        edit.Apply();
                        additionalAction?.Invoke();
                    }
                }
            }
        }
Example #22
0
        /// <summary>
        /// Given an R AST, and a range in that AST, determines the DataTip expression for that range.
        /// </summary>
        /// <returns>
        /// AST node corresponding to the DataTip expression, or <c>null</c> if there is no valid DataTip for the given range.
        /// </returns>
        /// <remarks>
        /// DataTip expression is defined as the outermost expression enclosing the range, such that the sequence 
        /// of operators from that outermost expression to the innermost node still enclosing the range only consists
        /// of operators: <c>$ @ :: ::: [ [[</c>. Furthermore, in case of <c>[ [[</c>, only their left operands
        /// are considered.
        /// </remarks>
        public static IAstNode GetDataTipExpression(IAstNode ast, ITextRange range) {
            var node = ast.NodeFromRange(range, inclusiveEnd: true);
            if (node == null || !IsValidInitialNode(node)) {
                return null;
            }

            // When the lookup starts at [ or [[, the immediate node is the token, but its parent is an Indexer node,
            // and the parent of the indexer is the Operator. The loop below assumes that Operator is the immediate
            // parent, so walk one level up before entering it in this case.
            var indexer = node.Parent as Indexer;
            if (indexer != null) {
                node = indexer;
            }

            // Walk the AST tree up to determine the expression that should be evaluated, according to the following rules:
            // - if current node is a child of $, @, :: or ::: (on either side of the operator), keep walking;
            // - if current node is a left child of [ or [[, keep walking;
            // - otherwise, stop.
            // Thus, for an expression like a::b$c@d, the entire expression will be considered when hovering over a, b, c or d.
            // But for a[b$c][[d]], hovering over a will consider a[b$c][d], but hovering over b or c will only consider b$c.
            while (true) {
                var parent = node.Parent as Operator;
                if (parent == null) {
                    break;
                }

                var op = parent.OperatorType;
                if (op == OperatorType.Index) {
                    // This is a[b] or a[[b]], and the current node is either a or b. If it is a, then we want to continue
                    // walking up; but if it is b, we want to stop here, so that only b is shown.
                    if (parent.Children.FirstOrDefault() != node) {
                        break;
                    }
                } else if (op != OperatorType.ListIndex && op != OperatorType.Namespace) {
                    break;
                }

                node = parent;
            }

            return node;
        }
Example #23
0
        public static bool FormatRangeExact(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options, IEditorShell editorShell) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            Span spanToFormat = new Span(formatRange.Start, formatRange.Length);
            string spanText = snapshot.GetText(spanToFormat.Start, spanToFormat.Length);
            string trimmedSpanText = spanText.Trim();

            RFormatter formatter = new RFormatter(options);
            string formattedText = formatter.Format(trimmedSpanText);

            formattedText = formattedText.Trim(); // There may be inserted line breaks after {
            // Apply formatted text without indentation. We then will update the parse tree 
            // so we can calculate proper line indents from the AST via the smart indenter.
            if (!spanText.Equals(formattedText, StringComparison.Ordinal)) {
                // Extract existing indent before applying changes. Existing indent
                // may be used by the smart indenter for function argument lists.
                var startLine = snapshot.GetLineFromPosition(spanToFormat.Start);
                var originalIndentSizeInSpaces = IndentBuilder.TextIndentInSpaces(startLine.GetText(), options.IndentSize);

                var selectionTracker = new RSelectionTracker(textView, textBuffer, formatRange);
                RTokenizer tokenizer = new RTokenizer();
                IReadOnlyTextRangeCollection<RToken> oldTokens = tokenizer.Tokenize(spanText);
                IReadOnlyTextRangeCollection<RToken> newTokens = tokenizer.Tokenize(formattedText);

                IncrementalTextChangeApplication.ApplyChangeByTokens(
                    textBuffer,
                    new TextStream(spanText), new TextStream(formattedText),
                    oldTokens, newTokens,
                    formatRange,
                    Resources.AutoFormat, selectionTracker, editorShell,
                    () => {
                        var ast = UpdateAst(textBuffer);
                        // Apply indentation
                        IndentLines(textView, textBuffer, new TextRange(formatRange.Start, formattedText.Length), ast, options, originalIndentSizeInSpaces);
                    });

                return true;
            }

            return false;
        }
Example #24
0
        public static bool FormatRangeExact(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange,
                                            AstRoot ast, RFormatOptions options, 
                                            int scopeStatementPosition, bool respectUserIndent = true) {
            ITextSnapshot snapshot = textBuffer.CurrentSnapshot;
            Span spanToFormat = new Span(formatRange.Start, formatRange.Length);
            string spanText = snapshot.GetText(spanToFormat.Start, spanToFormat.Length);
            string trimmedSpanText = spanText.Trim();

            if (trimmedSpanText == "}") {
                // Locate opening { and its statement
                var scopeNode = ast.GetNodeOfTypeFromPosition<IAstNodeWithScope>(spanToFormat.Start);
                if (scopeNode != null) {
                    scopeStatementPosition = scopeNode.Start;
                }
            }

            RFormatter formatter = new RFormatter(options);
            string formattedText = formatter.Format(trimmedSpanText);

            formattedText = formattedText.Trim(); // there may be inserted line breaks after {
            formattedText = IndentLines(textBuffer, spanToFormat.Start, ast, formattedText, options, scopeStatementPosition, respectUserIndent);

            if (!spanText.Equals(formattedText, StringComparison.Ordinal)) {
                var selectionTracker = new RSelectionTracker(textView, textBuffer);
                RTokenizer tokenizer = new RTokenizer();
                IReadOnlyTextRangeCollection<RToken> oldTokens = tokenizer.Tokenize(spanText);
                IReadOnlyTextRangeCollection<RToken> newTokens = tokenizer.Tokenize(formattedText);
                IncrementalTextChangeApplication.ApplyChangeByTokens(
                    textBuffer,
                    new TextStream(spanText), new TextStream(formattedText),
                    oldTokens, newTokens,
                    formatRange,
                    Resources.AutoFormat, selectionTracker);
                return true;
            }

            return false;
        }
Example #25
0
        //----------------------------------------------------- 
        //
        // ITextRange Methods
        //
        //----------------------------------------------------- 

        #region ITextRange Methods 
 
        //......................................................
        // 
        // Selection Building
        //
        //......................................................
 
        /// <summary>
        /// </summary> 
        // 
        internal static bool Contains(ITextRange thisRange, ITextPointer textPointer)
        { 
            NormalizeRange(thisRange);

            if (textPointer == null)
            { 
                throw new ArgumentNullException("textPointer");
            } 
 
            if (textPointer.TextContainer != thisRange.Start.TextContainer)
            { 
                throw new ArgumentException(SR.Get(SRID.NotInAssociatedTree), "textPointer");
            }

            // Correct position normalization on range boundary so that 
            // our test would not depend on what side of formatting tags
            // pointer is located. 
            if (textPointer.CompareTo(thisRange.Start) < 0) 
            {
                textPointer = textPointer.GetFormatNormalizedPosition(LogicalDirection.Forward); 
            }
            else if (textPointer.CompareTo(thisRange.End) > 0)
            {
                textPointer = textPointer.GetFormatNormalizedPosition(LogicalDirection.Backward); 
            }
 
            // Check if at least one segment contains this position. 
            for (int i = 0; i < thisRange._TextSegments.Count; i++)
            { 
                if (thisRange._TextSegments[i].Contains(textPointer))
                {
                    return true;
                } 
            }
 
            return false; 
        }
Example #26
0
 /// <summary>
 /// Finds out if range represents valid text range (when range is not null and it's length is greater than zero)
 /// </summary>
 /// <returns>True if range is valid</returns>
 public static bool IsValid(ITextRange range)
 {
     return(range != null && range.Length > 0);
 }
Example #27
0
 /// <summary>
 /// Finds out if range intersects another range
 /// </summary>
 /// <param name="range">First text range</param>
 /// <param name="rangeStart2">Start of the second range</param>
 /// <param name="rangeLength2">Length of the second range</param>
 /// <returns>True if ranges intersect</returns>
 public static bool Intersect(ITextRange range1, int rangeStart2, int rangeLength2) => Intersect(range1.Start, range1.Length, rangeStart2, rangeLength2);
Example #28
0
 /// <summary>
 /// Finds out of range intersects another range
 /// </summary>
 /// <param name="range">Text range</param>
 /// <returns>True if ranges intersect</returns>
 public virtual bool Intersect(ITextRange range) => TextRange.Intersect(this, range.Start, range.Length);
Example #29
0
 /// <summary>
 /// Determines if range contains given position
 /// </summary>
 /// <param name="range">Text range</param>
 /// <param name="position">Position</param>
 /// <returns>True if position is inside the range</returns>
 public static bool Contains(ITextRange range, int position) => Contains(range.Start, range.Length, position);
Example #30
0
        public int CompareEndpoints(TextPatternRangeEndpoint srcEndPoint, ITextRange targetRange, TextPatternRangeEndpoint targetEndPoint)
        {
            var nativeRange = ToNativeRange(targetRange);

            return(NativeRange.CompareEndpoints((UIA.Text.TextPatternRangeEndpoint)srcEndPoint, nativeRange, (UIA.Text.TextPatternRangeEndpoint)targetEndPoint));
        }
Example #31
0
        /// <summary>
        /// Determines if range contains another range
        /// </summary>
        public static bool Contains(ITextRange range, ITextRange other)
        {
            var textRange = new TextRange(range);

            return(textRange.Contains(other));
        }
Example #32
0
 /// <summary>
 /// Finds out if range intersects another range
 /// </summary>
 /// <param name="range1">First text range</param>
 /// <param name="range2">Second text range</param>
 /// <returns>True if ranges intersect</returns>
 public static bool Intersect(ITextRange range1, ITextRange range2) => Intersect(range1, range2.Start, range2.Length);
Example #33
0
 /// <summary>
 /// Finds out of range intersects another range
 /// </summary>
 /// <param name="start">Text range</param>
 /// <returns>True if ranges intersect</returns>
 public virtual bool Intersect(ITextRange range)
 {
     return(TextRange.Intersect(this, range.Start, range.Length));
 }
Example #34
0
 public TemplateCommentArtifact(ITextRange range, bool isClosed)
     : base(ArtifactTreatAs.Comment, range, isClosed) {
 }
Example #35
0
 public static TemplateArtifact Create(TemplateTokenKind kind, ITextRange range, bool isClosed) {
     switch (kind) {
         case TemplateTokenKind.Block:
             return new TemplateBlockArtifact(range, isClosed);
         case TemplateTokenKind.Variable:
             return new TemplateVariableArtifact(range, isClosed);
         case TemplateTokenKind.Comment:
             return new TemplateCommentArtifact(range, isClosed);
         default:
             throw new ArgumentException("Unsupported TemplateTokenKind", "kind");
     }
 }
 // Check the text range whether it is empty or not without normalization.
 private bool IsTextRangeEmpty(ITextRange textRange)
 {
     // We assume that TextRange.TextSegments property getter does not normalize a range,
     // thus we can avoid re-entrancy.
     Invariant.Assert(textRange._TextSegments.Count > 0);
     return textRange._TextSegments[0].Start.CompareTo(textRange._TextSegments[textRange._TextSegments.Count - 1].End) == 0;
 }
Example #37
0
 public ROutlineRegion(ITextBuffer textBuffer, ITextRange range)
     : base(textBuffer, range)
 {
 }
Example #38
0
 public ISelectionTracker CreateSelectionTracker(IEditorView editorView, IEditorBuffer editorBuffer, ITextRange selectedRange)
 => new RSelectionTracker(editorView.As <ITextView>(), editorBuffer.As <ITextBuffer>(), selectedRange);
Example #39
0
 /// <summary>
 /// Finds out if range intersects another range
 /// </summary>
 /// <param name="range1">First text range</param>
 /// <param name="range2">Second text range</param>
 /// <returns>True if ranges intersect</returns>
 public static bool Intersect(ITextRange range1, ITextRange range2)
 {
     return(Intersect(range1, range2.Start, range2.Length));
 }
Example #40
0
        public void MoveEndpointByRange(TextPatternRangeEndpoint srcEndPoint, ITextRange targetRange, TextPatternRangeEndpoint targetEndPoint)
        {
            var nativeRange = ToNativeRange(targetRange);

            NativeRange.MoveEndpointByRange((UIA.Text.TextPatternRangeEndpoint)srcEndPoint, nativeRange, (UIA.Text.TextPatternRangeEndpoint)targetEndPoint);
        }
Example #41
0
        /// <summary>
        /// Determines if range contains all ranges in a collection
        /// </summary>
        public static bool Contains(ITextRange range, IEnumerable <ITextRange> ranges)
        {
            var textRange = new TextRange(range);

            return(textRange.Contains(ranges));
        }
Example #42
0
 public ROutlineRegion(ITextBuffer textBuffer, ITextRange range, string displayText)
     : base(textBuffer, range)
 {
     _displayText = displayText;
 }
Example #43
0
 /// <summary>
 /// Determines if range contains given position
 /// </summary>
 /// <param name="range">Text range</param>
 /// <param name="position">Position</param>
 /// <returns>True if position is inside the range</returns>
 public static bool Contains(ITextRange range, int position)
 {
     return(Contains(range.Start, range.Length, position));
 }
Example #44
0
        public bool Compare(ITextRange range)
        {
            var nativeRange = ToNativeRange(range);

            return(NativeRange.Compare(nativeRange));
        }
Example #45
0
 /// <summary>
 /// Determines if range contains another range or it contains start point
 /// of the other range and their end points are the same.
 /// </summary>
 public static bool ContainsInclusiveEnd(ITextRange range, ITextRange other) => range.Contains(other.Start) && (range.Contains(other.End) || range.End == other.End);
Example #46
0
 /// <summary>
 /// Determines if text range fully contains another range
 /// </summary>
 /// <param name="range"></param>
 public virtual bool Contains(ITextRange range) => Contains(range.Start) && Contains(range.End);
Example #47
0
 /// <summary>
 /// Determines if text range fully contains another range
 /// </summary>
 /// <param name="range"></param>
 public virtual bool Contains(ITextRange range)
 {
     return(Contains(range.Start) && Contains(range.End));
 }
Example #48
0
 /// <summary>
 /// Finds out if range represents valid text range (when range is not null and it's length is greater than zero)
 /// </summary>
 /// <returns>True if range is valid</returns>
 public static bool IsValid(ITextRange range) => range != null && range.Length > 0;
Example #49
0
 /// <summary>
 /// Determines if range contains another range
 /// </summary>
 public static bool Contains(ITextRange range, ITextRange other) => range.Contains(other.Start) && range.Contains(other.End);
 public IList <T> ItemsInRange(ITextRange range)
 {
     return(_collection.ItemsInRange(range));
 }
Example #51
0
 /// <summary>
 /// Comments selected lines or current line if range has zero length.
 /// Continues adding commentcharacter even if line is already commented.
 /// # -> ## -> ### and so on. Matches C# behavior.
 /// </summary>
 public static void CommentBlock(ITextView textView, ITextBuffer textBuffer, ITextRange range)
 {
     DoActionOnLines(textView, textBuffer, range, CommentLine, Resources.CommentSelection);
 }
Example #52
0
 /// <summary>
 /// Creates text range based on another text range
 /// </summary>
 /// <param name="range">Text range to use as position source</param>
 public TextRange(ITextRange range)
     : this(range.Start, range.Length)
 {
 }
Example #53
0
        private static bool CanFormatRange(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, IEditorShell editorShell)
        {
            // Make sure we are not formatting damaging the projected range in R Markdown
            // which looks like ```{r. 'r' should not separate from {.
            var host = ContainedLanguageHost.GetHost(textView, textBuffer, editorShell);

            if (host != null)
            {
                ITextSnapshot snapshot = textBuffer.CurrentSnapshot;

                int startLine = snapshot.GetLineNumberFromPosition(formatRange.Start);
                int endLine   = snapshot.GetLineNumberFromPosition(formatRange.End);
                for (int i = startLine; i <= endLine; i++)
                {
                    if (!host.CanFormatLine(textView, textBuffer, i))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Example #54
0
 private bool CanFormatRange(ITextRange formatRange)
 {
     // Make sure we are not formatting damaging the projected range in R Markdown
     // which looks like ```{r. 'r' should not separate from {.
     return(true);
 }
Example #55
0
        public static bool FormatRangeExact(ITextView textView, ITextBuffer textBuffer, ITextRange formatRange, RFormatOptions options, IEditorShell editorShell)
        {
            ITextSnapshot snapshot        = textBuffer.CurrentSnapshot;
            Span          spanToFormat    = new Span(formatRange.Start, formatRange.Length);
            string        spanText        = snapshot.GetText(spanToFormat.Start, spanToFormat.Length);
            string        trimmedSpanText = spanText.Trim();

            RFormatter formatter     = new RFormatter(options);
            string     formattedText = formatter.Format(trimmedSpanText);

            formattedText = formattedText.Trim(); // There may be inserted line breaks after {
            // Apply formatted text without indentation. We then will update the parse tree
            // so we can calculate proper line indents from the AST via the smart indenter.
            if (!spanText.Equals(formattedText, StringComparison.Ordinal))
            {
                // Extract existing indent before applying changes. Existing indent
                // may be used by the smart indenter for function argument lists.
                var startLine = snapshot.GetLineFromPosition(spanToFormat.Start);
                var originalIndentSizeInSpaces = IndentBuilder.TextIndentInSpaces(startLine.GetText(), options.IndentSize);

                var        selectionTracker = new RSelectionTracker(textView, textBuffer, formatRange);
                RTokenizer tokenizer        = new RTokenizer();
                IReadOnlyTextRangeCollection <RToken> oldTokens = tokenizer.Tokenize(spanText);
                IReadOnlyTextRangeCollection <RToken> newTokens = tokenizer.Tokenize(formattedText);

                IncrementalTextChangeApplication.ApplyChangeByTokens(
                    textBuffer,
                    new TextStream(spanText), new TextStream(formattedText),
                    oldTokens, newTokens,
                    formatRange,
                    Resources.AutoFormat, selectionTracker, editorShell,
                    () => {
                    var ast = UpdateAst(textBuffer);
                    // Apply indentation
                    IndentLines(textView, textBuffer, new TextRange(formatRange.Start, formattedText.Length), ast, options, originalIndentSizeInSpaces);
                });

                return(true);
            }

            return(false);
        }
Example #56
0
 /// <summary>
 /// Constructs validation error for an element at a specified location.
 /// </summary>
 public ValidationError(ITextRange range, string message, ErrorLocation location) :
     base(range, message, location, ErrorSeverity.Error)
 {
 }
Example #57
0
 public TemplateVariableArtifact(ITextRange range, bool isClosed)
     : base(ArtifactTreatAs.Code, range, isClosed) {
 }
Example #58
0
 /// <summary>
 /// Creates a new parse error object with these properties.
 /// </summary>
 /// <param name="code">The code of the error.</param>
 /// <param name="range">The text range of the error.</param>
 public ParseError(ErrorCode code, ITextRange range)
 {
     _code  = code;
     _range = range;
 }
Example #59
0
 /// <param name="isClosed">Whether the artifact has a closing separator, or is terminated by EOF.</param>
 public TemplateArtifact(ArtifactTreatAs t, ITextRange range, bool isClosed) :
     base(t, range, 2, (isClosed ? 2 : 0), DjangoPredefinedClassificationTypeNames.TemplateTag, wellFormed: isClosed) {
 }
Example #60
0
 public string GetText(ITextRange range)
 {
     return(GetText(range.Start, range.Length));
 }