GetCharAt() public method

public GetCharAt ( int offset ) : char
offset int
return char
Esempio n. 1
0
        /// <summary>
        /// Gets the type of code at offset.<br/>
        /// 0 = Code,<br/>
        /// 1 = Comment,<br/>
        /// 2 = String<br/>
        /// Block comments and multiline strings are not supported.
        /// </summary>
        static int GetStartType(TextDocument document, int linestart, int offset)
        {
            bool inString = false;
            bool inChar = false;
            bool verbatim = false;
            int result = 0;
            for (int i = linestart; i < offset; i++)
            {
                switch (document.GetCharAt(i))
                {
                    case '/':
                        if (!inString && !inChar && i + 1 < document.TextLength)
                        {
                            if (document.GetCharAt(i + 1) == '/')
                            {
                                result = 1;
                            }
                        }
                        break;

                    case '"':
                    case '\'':
                        if (!inChar)
                        {
                            if (inString && verbatim)
                            {
                                if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"')
                                {
                                    ++i; // skip escaped quote
                                    inString = false; // let the string go on
                                }
                                else
                                {
                                    verbatim = false;
                                }
                            }
                            else if (!inString && i > 0 && document.GetCharAt(i - 1) == '@')
                            {
                                verbatim = true;
                            }
                            inString = !inString;
                        }
                        break;

                    case '\\':
                        if ((inString && !verbatim) || inChar)
                            ++i; // skip next character
                        break;
                }
            }

            return (inString || inChar) ? 2 : result;
        }
Esempio n. 2
0
        /// <summary>
        /// Sets the total line length and checks the delimiter.
        /// This method can cause line to be deleted when it contains a single '\n' character
        /// and the previous line ends with '\r'.
        /// </summary>
        /// <returns>Usually returns <paramref name="line"/>, but if line was deleted due to
        /// the "\r\n" merge, returns the previous line.</returns>
        DocumentLine SetLineLength(DocumentLine line, int newTotalLength)
        {
//			changedLines.Add(line);
//			deletedOrChangedLines.Add(line);
            int delta = newTotalLength - line.TotalLength;

            if (delta != 0)
            {
                foreach (ILineTracker lt in lineTrackers)
                {
                    lt.SetLineLength(line, newTotalLength);
                }
                line.TotalLength = newTotalLength;
                DocumentLineTree.UpdateAfterChildrenChange(line);
            }
            // determine new DelimiterLength
            if (newTotalLength == 0)
            {
                line.DelimiterLength = 0;
            }
            else
            {
                int  lineOffset = line.Offset;
                char lastChar   = document.GetCharAt(lineOffset + newTotalLength - 1);
                if (lastChar == '\r')
                {
                    line.DelimiterLength = 1;
                }
                else if (lastChar == '\n')
                {
                    if (newTotalLength >= 2 && document.GetCharAt(lineOffset + newTotalLength - 2) == '\r')
                    {
                        line.DelimiterLength = 2;
                    }
                    else if (newTotalLength == 1 && lineOffset > 0 && document.GetCharAt(lineOffset - 1) == '\r')
                    {
                        // we need to join this line with the previous line
                        DocumentLine previousLine = line.PreviousLine;
                        RemoveLine(line);
                        return(SetLineLength(previousLine, previousLine.TotalLength + 1));
                    }
                    else
                    {
                        line.DelimiterLength = 1;
                    }
                }
                else
                {
                    line.DelimiterLength = 0;
                }
            }
            return(line);
        }
Esempio n. 3
0
        public BracketSearchResult SearchBracket(TextDocument document, int offset)
        {
            if (offset > 0)
            {
                var c = document.GetCharAt(offset - 1);
                int index = openingBrackets.IndexOf(c);
                int otherOffset = -1;
                if (index > -1)
                    otherOffset = SearchBracketForward(document, offset, openingBrackets[index], closingBrackets[index]);

                index = closingBrackets.IndexOf(c);
                if (index > -1)
                    otherOffset = SearchBracketBackward(document, offset - 2, openingBrackets[index], closingBrackets[index]);

                if (otherOffset > -1)
                {
                    var result = new BracketSearchResult(
                        Math.Min(offset - 1, otherOffset),
                        Math.Max(offset - 1, otherOffset));
                    SearchDefinition(document, result);
                    return result;
                }
            }

            return null;
        }
Esempio n. 4
0
        public void RawlyIndentLine(string indentString, ICSharpCode.AvalonEdit.Document.TextDocument document, DocumentLine line)
        {
            if (!_doBeginUpdateManually)
            {
                document.BeginUpdate();
            }

            // 1)
            int prevInd = 0;
            int curOff  = line.Offset;

            if (curOff < document.TextLength)
            {
                char curChar = '\0';
                while (curOff < document.TextLength && ((curChar = document.GetCharAt(curOff)) == ' ' || curChar == '\t'))
                {
                    prevInd++;
                    curOff++;
                }

                document.Remove(line.Offset, prevInd);
            }

            document.Insert(line.Offset, indentString);
            if (!_doBeginUpdateManually)
            {
                document.EndUpdate();
            }
        }
Esempio n. 5
0
 public BracketSearchResult SearchBracket(TextDocument document, int offset)
 {
     BracketSearchResult result;
     if (offset > 0)
     {
         var charAt = document.GetCharAt(offset - 1);
         var num = "([{".IndexOf(charAt);
         var num2 = -1;
         if (num > -1)
         {
             num2 = SearchBracketForward(document, offset, "([{"[num], ")]}"[num]);
         }
         num = ")]}".IndexOf(charAt);
         if (num > -1)
         {
             num2 = SearchBracketBackward(document, offset - 2, "([{"[num], ")]}"[num]);
         }
         if (num2 > -1)
         {
             result = new BracketSearchResult(Math.Min(offset - 1, num2), 1, Math.Max(offset - 1, num2), 1);
             return result;
         }
     }
     result = null;
     return result;
 }
Esempio n. 6
0
        public override int GetFirstInterestedOffset(int startOffset)
        {
            ICSharpCode.AvalonEdit.Document.TextDocument document = CurrentContext.Document;
            int firstOffset = CurrentContext.VisualLine.FirstDocumentLine.Offset;

            if (firstOffset == startOffset)
            {
                return(firstOffset);
            }
            else
            {
                return(-1);
            }

            int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;

            for (int i = startOffset; i < endOffset; i++)
            {
                char c = document.GetCharAt(i);
                if (c == ':')
                {
                    return(i + 1);
                }
            }
            return(-1);
        }
Esempio n. 7
0
        public void RawlyIndentLine(int tabsToInsert, TextDocument document, DocumentLine line)
        {
            if (!_doBeginUpdateManually)
                document.BeginUpdate();
            /*
             * 1) Remove old indentation
             * 2) Insert new one
             */

            // 1)
            int prevInd = 0;
            int curOff = line.Offset;
            if (curOff < document.TextLength)
            {
                char curChar = '\0';
                while (curOff < document.TextLength && ((curChar = document.GetCharAt(curOff)) == ' ' || curChar == '\t'))
                {
                    prevInd++;
                    curOff++;
                }

                document.Remove(line.Offset, prevInd);
            }

            // 2)
            string indentString = "";
            for (int i = 0; i < tabsToInsert; i++)
                indentString += dEditor.Editor.Options.IndentationString;

            document.Insert(line.Offset, indentString);
            if (!_doBeginUpdateManually)
                document.EndUpdate();
        }
        private void CreateMethodFold(TextDocument textDocument)
        {
            // TODO: Find a way to fold just functions brackets.

            this.startOffsets.Push(this.currentOffset);

            this.bracketSearcher.OpeningBrackets = "{";
            this.bracketSearcher.ClosingBrackets = "}";

            BracketSearchResult result = this.bracketSearcher.SearchBracket(textDocument, this.currentOffset + 1);

            if (result != null)
            {
                int startOffset = startOffsets.Pop();

                // Skip empty spaces.
                for(int i = startOffset - 1; i > 0; i--)
                {
                    char character = textDocument.GetCharAt(i);

                    if (char.IsWhiteSpace(character) == false && character != '\n' && character != '\r')
                    {
                        startOffset = i + 1;
                        break;
                    }
                }

                this.foldings.Foldings.Add(new NewFolding(startOffset, result.ClosingBracketOffset + 1) { Name = "..." });
            }
        }
        private void CreateCommentFold(TextDocument textDocument)
        {
            this.startOffsets.Push(this.currentOffset - 1);

            for (; this.currentOffset < textDocument.TextLength; this.currentOffset++)
            {
                char character = textDocument.GetCharAt(this.currentOffset);

                if (character == '*' && textDocument.GetCharAt(++this.currentOffset) == '/')
                {
                    this.currentOffset++;
                    foldings.Foldings.Add(new NewFolding(startOffsets.Pop(), this.currentOffset) { Name = "/* ..." });

                    break;
                }
            }
        }
Esempio n. 10
0
        static int ScanLineStart(TextDocument document, int offset)
		{
			for (int i = offset - 1; i > 0; --i) {
				if (document.GetCharAt(i) == '\n')
					return i + 1;
			}
			return 0;
		}
Esempio n. 11
0
        /// <summary>
        /// Gets the offset of the first non-whitespace character.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset where to start the search.</param>
        /// <returns>
        /// The offset of the first non-whitespace at or after <paramref name="offset"/>.
        /// <see cref="TextDocument.TextLength"/> is returned if no non-whitespace is found. (Line
        /// breaks do not count as whitespace.)
        /// </returns>
        internal static int FindFirstNonWhitespace(TextDocument document, int offset)
        {
            while (offset < document.TextLength && char.IsWhiteSpace(document.GetCharAt(offset)))
            {
                ++offset;
            }

            return(offset);
        }
Esempio n. 12
0
        /// <summary>
        /// Gets the offset of the first non-whitespace character.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset where to start the search.</param>
        /// <param name="searchBackwards">
        /// If set to <see langword="true"/>, the document is searched in backwards direction (=
        /// from <paramref name="offset"/> to start of text document.
        /// </param>
        /// <returns>
        /// <para>
        /// If <paramref name="searchBackwards"/> is <see langword="false"/>:
        /// The offset of the first non-whitespace at or after <paramref name="offset" />.
        /// <see cref="TextDocument.TextLength" /> is returned if no non-whitespace is found. (Line
        /// breaks do not count as whitespace.)
        /// </para>
        /// <para>
        /// If <paramref name="searchBackwards"/> is <see langword="true"/>:
        /// The offset of the first non-whitespace at or before <paramref name="offset" />.
        /// 0 is returned if no non-whitespace is found. (Line breaks do not count as whitespace.)
        /// </para>
        /// </returns>
        internal static int FindFirstNonWhitespace(TextDocument document, int offset, bool searchBackwards)
        {
            if (searchBackwards)
            {
                while (offset > 0 && char.IsWhiteSpace(document.GetCharAt(offset)))
                {
                    --offset;
                }
            }
            else
            {
                while (offset < document.TextLength && char.IsWhiteSpace(document.GetCharAt(offset)))
                {
                    ++offset;
                }
            }

            return(offset);
        }
Esempio n. 13
0
 void SearchDefinition(TextDocument document, BracketSearchResult result)
 {
     if (document.GetCharAt(result.OpeningOffset) != '{')
         return;
     // get line
     var documentLine = document.GetLineByOffset(result.OpeningOffset);
     while (documentLine != null && IsBracketOnly(document, documentLine))
         documentLine = documentLine.PreviousLine;
     if (documentLine != null)
     {
         result.DefinitionHeaderOffset = documentLine.Offset;
         result.DefinitionHeaderLength = documentLine.Length;
     }
 }
Esempio n. 14
0
        /// <summary>
        /// Determines whether a line of a document is empty (no characters or whitespace).
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="line">The line.</param>
        /// <returns>
        /// <see langword="true"/> if line is empty of filled with whitespace; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        internal static bool IsEmptyLine(TextDocument document, DocumentLine line)
        {
            int lineOffset  = line.Offset;
            int startOffset = lineOffset;
            int endOffset   = lineOffset + line.Length;

            for (int i = startOffset; i < endOffset; ++i)
            {
                char ch = document.GetCharAt(i);
                if (!char.IsWhiteSpace(ch))
                {
                    return(false);
                }
            }
            return(true);
        }
Esempio n. 15
0
        /// <summary>
        /// Checks whether a region (offset + length) matches a given word.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="word">The word.</param>
        /// <returns><see langword="true"/> if region matches word.</returns>
        /// <remarks>
        /// The comparison is case-sensitive.
        /// </remarks>
        internal static bool CompareSegment(TextDocument document, int offset, int length, string word)
        {
            if (length != word.Length || document.TextLength < offset + length)
            {
                return(false);
            }

            for (int i = 0; i < length; ++i)
            {
                if (document.GetCharAt(offset + i) != word[i])
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 16
0
        private void codeEditor_TextEntered(object sender, TextCompositionEventArgs e)
        {
            if (e.Text == ".")
            {
                ICSharpCode.AvalonEdit.Editing.TextArea      area = (sender as ICSharpCode.AvalonEdit.Editing.TextArea);
                ICSharpCode.AvalonEdit.Document.TextDocument doc  = area.Document;
                int startoff = area.Caret.Offset - 1;
                int off      = area.Caret.Offset - 2;
                while (true)
                {
                    char o = doc.GetCharAt(off);
                    if (!char.IsLetter(o))
                    {
                        break;
                    }
                    if (off == 0)
                    {
                        break;
                    }
                    off--;
                }
                string prevToken = doc.GetText(off, startoff - off);

                // Open code completion after the user has pressed dot:
                completionWindow        = new CompletionWindow(CodeEditor.TextArea);
                completionWindow.Margin = new Thickness(0);
                IList <ICompletionData> data = completionWindow.CompletionList.CompletionData;
                try
                {
                    List <string> items = CompletionDatabase.completionDatabase[prevToken];
                    foreach (string item in items)
                    {
                        data.Add(new CompletionData(item));
                    }
                    completionWindow.Show();
                    completionWindow.Closed += delegate
                    {
                        completionWindow = null;
                    };
                }catch (Exception)
                {
                }
            }
        }
Esempio n. 17
0
        public void RawlyIndentLine(int tabsToInsert, ICSharpCode.AvalonEdit.Document.TextDocument document, DocumentLine line)
        {
            if (!_doBeginUpdateManually)
            {
                document.BeginUpdate();
            }

            /*
             * 1) Remove old indentation
             * 2) Insert new one
             */

            // 1)
            int prevInd = 0;
            int curOff  = line.Offset;

            if (curOff < document.TextLength)
            {
                char curChar = '\0';
                while (curOff < document.TextLength && ((curChar = document.GetCharAt(curOff)) == ' ' || curChar == '\t'))
                {
                    prevInd++;
                    curOff++;
                }

                document.Remove(line.Offset, prevInd);
            }

            // 2)
            string indentString = "";

            for (int i = 0; i < tabsToInsert; i++)
            {
                indentString += dEditor.Editor.Options.IndentationString;
            }

            document.Insert(line.Offset, indentString);
            if (!_doBeginUpdateManually)
            {
                document.EndUpdate();
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Finds and marks all regions.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset where the search starts.</param>
        /// <param name="folds">The fold markers.</param>
        /// <returns>The index of the next character after the all regions.</returns>
        /// <remarks>
        /// This method returns when it finds a "#endregion" string that does not have
        /// a "#region" statement after <paramref name="offset"/>. In this case it 
        /// returns the index of the next character after the "#endregion" statement.
        /// </remarks>
        private static int FindAndMarkRegions(TextDocument document, int offset, List<NewFolding> folds)
        {
            if (offset >= document.TextLength)
                return offset;

            while (offset < document.TextLength)
            {
                char c = document.GetCharAt(offset);
                switch (c)
                {
                    case '/':
                        // Skip comments
                        offset = SkipComment(document, offset);
                        break;
                    case '#':
                        string word = TextUtilities.GetIdentifierAt(document, offset + 1);
                        if (word == "region")
                        {
                            offset = MarkRegion(document, offset, folds);
                        }
                        else if (word == "endregion")
                        {
                            return offset + "endregion".Length + 1;
                        }
                        else
                        {
                            offset++;
                        }
                        break;
                    default:
                        // Skip to next word
                        int endOfIdentifier = TextUtilities.FindEndOfIdentifier(document, offset);
                        if (endOfIdentifier > 0)
                            offset = endOfIdentifier + 1;
                        else
                            ++offset;
                        break;
                }
            }
            return offset;
        }
Esempio n. 19
0
        /// <summary>
        /// Checks whether a region (offset + length) matches a given word.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="word">The word.</param>
        /// <param name="caseSensitive">
        /// If set to <see langword="true"/> the comparison is case-sensitive.
        /// </param>
        /// <returns><see langword="true"/> if region matches word.</returns>
        internal static bool CompareSegment(TextDocument document, int offset, int length, string word, bool caseSensitive)
        {
            if (caseSensitive)
            {
                return(CompareSegment(document, offset, length, word));
            }

            if (length != word.Length || document.TextLength < offset + length)
            {
                return(false);
            }

            for (int i = 0; i < length; ++i)
            {
                if (char.ToUpper(document.GetCharAt(offset + i)) != char.ToUpper(word[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
 public static char GetPreviousChar(TextDocument doc, int offset)
 {
     if (offset - 1 == 0)
         return '\0';
     return doc.GetCharAt(offset - 1);
 }
Esempio n. 21
0
        int SearchBracketBackward(TextDocument document, int offset, char openBracket, char closingBracket)
		{
			if (offset + 1 >= document.TextLength) return -1;
			// this method parses a c# document backwards to find the matching bracket
			
			// first try "quick find" - find the matching bracket if there is no string/comment in the way
			int quickResult = QuickSearchBracketBackward(document, offset, openBracket, closingBracket);
			if (quickResult >= 0) return quickResult;
			
			// we need to parse the line from the beginning, so get the line start position
			int linestart = ScanLineStart(document, offset + 1);
						
			// I don't see any possibility to parse a C# document backwards...
			// We have to do it forwards and push all bracket positions on a stack.
			Stack<int> bracketStack = new Stack<int>();
			bool  blockComment = false;
			bool  lineComment  = false;
			bool  inChar       = false;
			bool  inString     = false;
			bool  verbatim     = false;
			
			for(int i = 0; i <= offset; ++i) {
				char ch = document.GetCharAt(i);
				switch (ch) {
					case '\r':
					case '\n':
						lineComment = false;
						inChar = false;
						if (!verbatim) inString = false;
						break;
					case '/':
						if (blockComment) {
							Debug.Assert(i > 0);
							if (document.GetCharAt(i - 1) == '*') {
								blockComment = false;
							}
						}
						if (!inString && !inChar && i + 1 < document.TextLength) {
							if (!blockComment && document.GetCharAt(i + 1) == '/') {
								lineComment = true;
							}
							if (!lineComment && document.GetCharAt(i + 1) == '*') {
								blockComment = true;
							}
						}
						break;
					case '"':
						if (!(inChar || lineComment || blockComment)) {
							if (inString && verbatim) {
								if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') {
									++i; // skip escaped quote
									inString = false; // let the string go
								} else {
									verbatim = false;
								}
							} else if (!inString && offset > 0 && document.GetCharAt(i - 1) == '@') {
								verbatim = true;
							}
							inString = !inString;
						}
						break;
					case '\'':
						if (!(inString || lineComment || blockComment)) {
							inChar = !inChar;
						}
						break;
					case '\\':
						if ((inString && !verbatim) || inChar)
							++i; // skip next character
						break;
						default :
							if (ch == openBracket) {
							if (!(inString || inChar || lineComment || blockComment)) {
								bracketStack.Push(i);
							}
						} else if (ch == closingBracket) {
							if (!(inString || inChar || lineComment || blockComment)) {
								if (bracketStack.Count > 0)
									bracketStack.Pop();
							}
						}
						break;
				}
			}
			if (bracketStack.Count > 0) return (int)bracketStack.Pop();
			return -1;
		}
Esempio n. 22
0
 /// <summary>
 /// Marks all code blocks (namespaces, classes, methods, etc.) in the document.
 /// </summary>
 /// <param name="document">The document.</param>
 /// <param name="foldMarkers">The fold markers.</param>
 private static void MarkBlocks(TextDocument document, ICollection<NewFolding> foldMarkers)
 {
     int offset = 0;
     while (offset < document.TextLength)
     {
         switch (document.GetCharAt(offset))
         {
             case '/':
                 offset = SkipComment(document, offset);
                 break;
             case '{':
                 offset = MarkMethod(document, offset, foldMarkers);
                 break;
             default:
                 offset = MarkBlock(document, offset, foldMarkers);
                 break;
         }
     }
 }
Esempio n. 23
0
        /// <summary>
        /// Marks the region that starts at the given offset.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="folds">The fold markers.</param>
        /// <returns>The index of the next character after the region.</returns>
        private static int MarkRegion(TextDocument document, int offset, List<NewFolding> folds)
        {
            if (offset >= document.TextLength)
                return offset;

            if (document.GetCharAt(offset) == '#')
            {
                int startOffset = offset;
                offset++;
                string word = TextUtilities.GetIdentifierAt(document, offset);
                if (word == "region")
                {
                    offset += "region".Length;

                    // Find label
                    var line = document.GetLineByOffset(offset);
                    int lineEnd = line.Offset + line.Length;
                    int labelLength = lineEnd - offset;
                    string label = document.GetText(offset, labelLength);
                    label = label.Trim();
                    if (label.Length == 0)
                        label = "#region";

                    // Find and mark subregions
                    offset = FindAndMarkRegions(document, lineEnd, folds);

                    if (offset <= document.TextLength)
                    {
                        AddFold(document, folds, startOffset, offset, label);
                        offset++;
                    }
                }
            }
            else
            {
                offset++;
            }
            return offset;
        }
Esempio n. 24
0
 /// <summary>
 /// Marks all code blocks (namespaces, classes, methods, etc.) in the document.
 /// </summary>
 /// <param name="document">The document.</param>
 /// <param name="foldMarkers">The fold markers.</param>
 private static void MarkBlocks(TextDocument document, ICollection<NewFolding> foldMarkers)
 {
     int offset = 0;
     while (offset < document.TextLength)
     {
         switch (document.GetCharAt(offset))
         {
             case '/':
                 offset = SkipComment(document, offset);
                 break;
             case 'c':
                 offset = MarkBlock("class", document, offset, foldMarkers);
                 break;
             case 'e':
                 offset = MarkBlock("enum", document, offset, foldMarkers);
                 break;
             case 'i':
                 offset = MarkBlock("interface", document, offset, foldMarkers);
                 break;
             case 'n':
                 offset = MarkBlock("namespace", document, offset, foldMarkers);
                 break;
             case 's':
                 offset = MarkBlock("struct", document, offset, foldMarkers);
                 break;
             case '{':
                 offset = MarkMethod(document, offset, foldMarkers);
                 break;
             default:
                 int endOfIdentifier = TextUtilities.FindEndOfIdentifier(document, offset);
                 if (endOfIdentifier > 0)
                     offset = endOfIdentifier + 1;
                 else
                     ++offset;
                 break;
         }
     }
 }
Esempio n. 25
0
        public void InsertBold(int start, int length, TextDocument document)
        {
            var chs = document.GetCharAt(start);
            var che = document.GetCharAt(start + length - 1);

            document.Insert(start + length - 1, che.ToString());
            document.Replace(start + length, 1, "]");   //trick to keep anchors

            document.Insert(start + 1, chs.ToString());
            document.Replace(start, 1, "["); //trick to keep anchors

            Blocks.Add(new TextBlockBold()
            {
                OriginallyLength = length + 2,
                OriginallyOffset = start,
                MyAnchor = new AnchorSegment(document, start, length + 2)
            });
        }
Esempio n. 26
0
        /// <summary>
        /// Gets the offset of the first non-whitespace character.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset where to start the search.</param>
        /// <returns>
        /// The offset of the first non-whitespace at or after <paramref name="offset"/>.
        /// <see cref="TextDocument.TextLength"/> is returned if no non-whitespace is found. (Line
        /// breaks do not count as whitespace.)
        /// </returns>
        internal static int FindFirstNonWhitespace(TextDocument document, int offset)
        {
            while (offset < document.TextLength && char.IsWhiteSpace(document.GetCharAt(offset)))
                ++offset;

            return offset;
        }
Esempio n. 27
0
        /// <summary>
        /// Gets the offset of the first non-whitespace character.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset where to start the search.</param>
        /// <param name="searchBackwards">
        /// If set to <see langword="true"/>, the document is searched in backwards direction (=
        /// from <paramref name="offset"/> to start of text document.
        /// </param>
        /// <returns>
        /// <para>
        /// If <paramref name="searchBackwards"/> is <see langword="false"/>:
        /// The offset of the first non-whitespace at or after <paramref name="offset" />.
        /// <see cref="TextDocument.TextLength" /> is returned if no non-whitespace is found. (Line
        /// breaks do not count as whitespace.)
        /// </para>
        /// <para>
        /// If <paramref name="searchBackwards"/> is <see langword="true"/>:
        /// The offset of the first non-whitespace at or before <paramref name="offset" />.
        /// 0 is returned if no non-whitespace is found. (Line breaks do not count as whitespace.)
        /// </para>
        /// </returns>
        internal static int FindFirstNonWhitespace(TextDocument document, int offset, bool searchBackwards)
        {
            if (searchBackwards)
            {
                while (offset > 0 && char.IsWhiteSpace(document.GetCharAt(offset)))
                    --offset;
            }
            else
            {
                while (offset < document.TextLength && char.IsWhiteSpace(document.GetCharAt(offset)))
                    ++offset;
            }

            return offset;
        }
Esempio n. 28
0
        /// <summary>
        /// Gets the expression before a given offset.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="initialOffset">The initial offset.</param>
        /// <returns>The expression.</returns>
        /// <remarks>
        /// This method returns the expression before a specified offset.
        /// That method is used in code completion to determine the expression before
        /// the caret. The expression can be passed to a parser to resolve the type
        /// or similar.
        /// </remarks>
        internal static string GetExpressionBeforeOffset(TextDocument document, int initialOffset)
        {
            int offset = initialOffset;
            while (offset - 1 > 0)
            {
                switch (document.GetCharAt(offset - 1))
                {
                    case '\n':
                    case '\r':
                    case '}':
                        goto done;
                    //offset = FindOpeningBracket(document, offset - 2, '{','}');
                    //break;
                    case ']':
                        offset = FindOpeningBracket(document, offset - 2, '[', ']');
                        break;
                    case ')':
                        offset = FindOpeningBracket(document, offset - 2, '(', ')');
                        break;
                    case '.':
                        --offset;
                        break;
                    case '"':
                        if (offset < initialOffset - 1)
                        {
                            return null;
                        }
                        return "\"\"";
                    case '\'':
                        if (offset < initialOffset - 1)
                        {
                            return null;
                        }
                        return "'a'";
                    case '>':
                        if (document.GetCharAt(offset - 2) == '-')
                        {
                            offset -= 2;
                            break;
                        }
                        goto done;
                    default:
                        if (char.IsWhiteSpace(document.GetCharAt(offset - 1)))
                        {
                            --offset;
                            break;
                        }
                        int start = offset - 1;
                        if (!IsIdentifierPart(document.GetCharAt(start)))
                        {
                            goto done;
                        }

                        while (start > 0 && IsIdentifierPart(document.GetCharAt(start - 1)))
                        {
                            --start;
                        }
                        string word = document.GetText(start, offset - start).Trim();
                        switch (word)
                        {
                            case "ref":
                            case "out":
                            case "in":
                            case "return":
                            case "throw":
                            case "case":
                                goto done;
                        }

                        if (word.Length > 0 && !IsIdentifierPart(word[0]))
                        {
                            goto done;
                        }
                        offset = start;
                        break;
                }
            }
            done:
            // simple exit fails when : is inside comment line or any other character
            // we have to check if we got several ids in resulting line, which usually happens when
            // id. is typed on next line after comment one
            // Would be better if lexer would parse properly such expressions. However this will cause
            // modifications in this area too - to get full comment line and remove it afterwards
            if (offset < 0)
                return string.Empty;

            string resText = document.GetText(offset, initialOffset - offset).Trim();
            int pos = resText.LastIndexOf('\n');
            if (pos >= 0)
            {
                offset += pos + 1;
                // whitespaces and tabs, which might be inside, will be skipped by trim below
            }

            string expression = document.GetText(offset, initialOffset - offset).Trim();
            return expression;
        }
Esempio n. 29
0
 public void GetCharAt0EmptyDocument()
 {
     document.GetCharAt(0);
 }
Esempio n. 30
0
 /// <summary>
 /// Determines whether a line of a document is empty (no characters or whitespace).
 /// </summary>
 /// <param name="document">The document.</param>
 /// <param name="line">The line.</param>
 /// <returns>
 /// <see langword="true"/> if line is empty of filled with whitespace; otherwise, 
 /// <see langword="false"/>.
 /// </returns>
 internal static bool IsEmptyLine(TextDocument document, DocumentLine line)
 {
     int lineOffset = line.Offset;
     int startOffset = lineOffset;
     int endOffset = lineOffset + line.Length;
     for (int i = startOffset; i < endOffset; ++i)
     {
         char ch = document.GetCharAt(i);
         if (!char.IsWhiteSpace(ch))
             return false;
     }
     return true;
 }
Esempio n. 31
0
        /// <summary>
        /// Gets the expression before a given offset.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="initialOffset">The initial offset.</param>
        /// <returns>The expression.</returns>
        /// <remarks>
        /// This method returns the expression before a specified offset.
        /// That method is used in code completion to determine the expression before
        /// the caret. The expression can be passed to a parser to resolve the type
        /// or similar.
        /// </remarks>
        internal static string GetExpressionBeforeOffset(TextDocument document, int initialOffset)
        {
            int offset = initialOffset;

            while (offset - 1 > 0)
            {
                switch (document.GetCharAt(offset - 1))
                {
                case '\n':
                case '\r':
                case '}':
                    goto done;

                //offset = FindOpeningBracket(document, offset - 2, '{','}');
                //break;
                case ']':
                    offset = FindOpeningBracket(document, offset - 2, '[', ']');
                    break;

                case ')':
                    offset = FindOpeningBracket(document, offset - 2, '(', ')');
                    break;

                case '.':
                    --offset;
                    break;

                case '"':
                    if (offset < initialOffset - 1)
                    {
                        return(null);
                    }
                    return("\"\"");

                case '\'':
                    if (offset < initialOffset - 1)
                    {
                        return(null);
                    }
                    return("'a'");

                case '>':
                    if (document.GetCharAt(offset - 2) == '-')
                    {
                        offset -= 2;
                        break;
                    }
                    goto done;

                default:
                    if (char.IsWhiteSpace(document.GetCharAt(offset - 1)))
                    {
                        --offset;
                        break;
                    }
                    int start = offset - 1;
                    if (!IsIdentifierPart(document.GetCharAt(start)))
                    {
                        goto done;
                    }

                    while (start > 0 && IsIdentifierPart(document.GetCharAt(start - 1)))
                    {
                        --start;
                    }
                    string word = document.GetText(start, offset - start).Trim();
                    switch (word)
                    {
                    case "ref":
                    case "out":
                    case "in":
                    case "return":
                    case "throw":
                    case "case":
                        goto done;
                    }

                    if (word.Length > 0 && !IsIdentifierPart(word[0]))
                    {
                        goto done;
                    }
                    offset = start;
                    break;
                }
            }
done:
            // simple exit fails when : is inside comment line or any other character
            // we have to check if we got several ids in resulting line, which usually happens when
            // id. is typed on next line after comment one
            // Would be better if lexer would parse properly such expressions. However this will cause
            // modifications in this area too - to get full comment line and remove it afterwards
            if (offset < 0)
            {
                return(string.Empty);
            }

            string resText = document.GetText(offset, initialOffset - offset).Trim();
            int    pos     = resText.LastIndexOf('\n');

            if (pos >= 0)
            {
                offset += pos + 1;
                // whitespaces and tabs, which might be inside, will be skipped by trim below
            }

            string expression = document.GetText(offset, initialOffset - offset).Trim();

            return(expression);
        }
Esempio n. 32
0
        private void CreateNewFoldings(TextDocument textDocument)
        {
            for (this.currentOffset = 0; this.currentOffset < textDocument.TextLength; this.currentOffset++)
            {
                char character = textDocument.GetCharAt(this.currentOffset);

                if (character == '{')
                {
                    this.CreateMethodFold(textDocument);
                }
                else if (character == '/' && ++this.currentOffset < textDocument.TextLength && textDocument.GetCharAt(this.currentOffset) == '*')
                {
                    this.CreateCommentFold(textDocument);
                }
            }

            this.foldings.Foldings.Sort((first, second) => first.StartOffset.CompareTo(second.StartOffset));
        }
Esempio n. 33
0
        private IEnumerable<NewFolding> CreateNewFoldings(TextDocument document)
        {
            var newFoldings = new List<NewFolding>();

            var startOffsets = new Stack<int>();
            var titles = new Stack<string>();
            var lastNewLineOffset = 0;
            for (var i = 0; i < document.TextLength; i++)
            {
                var c = document.GetCharAt(i);
                if (c == '#')
                {
                    // see if the next word is 'region', or 'endregion'
                    var directive = new StringBuilder();

                    var j = i + 1;
                    while (j < document.TextLength && !Char.IsWhiteSpace(document.GetCharAt(j)))
                    {
                        directive.Append(document.GetCharAt(j++));
                    }

                    if (directive.ToString().Equals("region"))
                    {

                        j++;

                        var nameBuilder = new StringBuilder();
                        while (j < document.TextLength && !Char.IsWhiteSpace(document.GetCharAt(j)))
                        {
                            nameBuilder.Append(document.GetCharAt(j++));
                        }

                        titles.Push(nameBuilder.ToString());

                        // go to next newline (if there is one), otherwise we don't start an offset
                        while(j < document.TextLength)
                        {
                            c = document.GetCharAt(j++);
                            if (c != '\n' && c != '\r') continue;

                            lastNewLineOffset = j;
                            startOffsets.Push(i);
                            break;
                        }
                    }
                    else if (directive.ToString().Equals("endregion") && startOffsets.Count > 0)
                    {
                        var startOffset = startOffsets.Pop();
                        var name = titles.Pop();

                        // don't fold if opening and closing brace are on the same line
                        if (startOffset < lastNewLineOffset)
                        {
                            newFoldings.Add(new NewFolding(startOffset, j) {Name = name} );
                        }
                    }

                    i = j;
                }
                else if (c == '\n' || c == '\r')
                {
                    lastNewLineOffset = i + 1;
                }

            }

            lastNewLineOffset = 0;
            const char openingBrace = '{';
            const char closingBrace = '}';
            for (var i = 0; i < document.TextLength; i++)
            {
                var c = document.GetCharAt(i);
                if (c == openingBrace)
                {
                    startOffsets.Push(i);
                }
                else if (c == closingBrace && startOffsets.Count > 0)
                {
                    var startOffset = startOffsets.Pop();
                    // don't fold if opening and closing brace are on the same line
                    if (startOffset < lastNewLineOffset)
                    {
                        newFoldings.Add(new NewFolding(startOffset, i + 1));
                    }
                }
                else if (c == '\n' || c == '\r')
                {
                    lastNewLineOffset = i + 1;
                }
            }

            newFoldings.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
            return newFoldings;
        }
Esempio n. 34
0
        /// <summary>
        /// Checks whether a region (offset + length) matches a given word.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="word">The word.</param>
        /// <param name="caseSensitive">
        /// If set to <see langword="true"/> the comparison is case-sensitive.
        /// </param>
        /// <returns><see langword="true"/> if region matches word.</returns>
        internal static bool CompareSegment(TextDocument document, int offset, int length, string word, bool caseSensitive)
        {
            if (caseSensitive)
                return CompareSegment(document, offset, length, word);

            if (length != word.Length || document.TextLength < offset + length)
                return false;

            for (int i = 0; i < length; ++i)
                if (char.ToUpper(document.GetCharAt(offset + i)) != char.ToUpper(word[i]))
                    return false;

            return true;
        }
Esempio n. 35
0
        /// <summary>
        /// Marks the block that starts at the current offset.
        /// </summary>
        /// <param name="name">The identifier of the block (e.g. "class", "struct").</param>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset of the identifier.</param>
        /// <param name="foldMarkers">The fold markers.</param>
        /// <returns>The index of the next character after the block.</returns>
        private static int MarkBlock(string name, TextDocument document, int offset, ICollection<NewFolding> foldMarkers)
        {
            if (offset >= document.TextLength)
                return offset;

            string word = TextUtilities.GetIdentifierAt(document, offset);
            if (word == name)
            {
                offset += word.Length;
                while (offset < document.TextLength)
                {
                    char c = document.GetCharAt(offset);
                    if (c == '}' || c == ';')
                    {
                        offset++;
                        break;
                    }
                    if (c == '{')
                    {
                        int startOffset = offset;
                        while (Char.IsWhiteSpace(document.GetCharAt(startOffset - 1)))
                            startOffset--;

                        int offsetOfClosingBracket = TextUtilities.FindClosingBracket(document, offset + 1, '{', '}');
                        if (offsetOfClosingBracket > 0)
                        {
                            AddFold(document, foldMarkers, startOffset, offsetOfClosingBracket + 1, "{...}");

                            // Skip to offset after '{'.
                            offset++;
                            break;
                        }
                    }
                    offset++;
                }
            }
            else
            {
                // Skip to next word
                offset += word.Length;
            }
            return offset;
        }
Esempio n. 36
0
 /// <summary>
 /// Access the document like a char array
 /// (first char at index 0 at the beginning of document)
 /// </summary>
 public char CharAt(int offset)
 {
     return(_avalonEditTextDocument.GetCharAt(offset));
 }
Esempio n. 37
0
        /// <summary>
        /// Marks the method whose block starts at the given offset.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset of the method body ('{').</param>
        /// <param name="folds">The fold markers.</param>
        /// <returns>The index of the next character after the method.</returns>
        private static int MarkMethod(TextDocument document, int offset, ICollection<NewFolding> folds)
        {
            if (offset >= document.TextLength)
                return offset;

            int startOffset = offset;
            while (startOffset - 1 > 0 && Char.IsWhiteSpace(document.GetCharAt(startOffset - 1)))
                startOffset--;

            int offsetOfClosingBracket = TextUtilities.FindClosingBracket(document, offset + 1, '{', '}');
            if (offsetOfClosingBracket > 0)
            {
                // Check whether next character is ';'
                int offsetOfNextCharacter = TextUtilities.FindFirstNonWhitespace(document, offsetOfClosingBracket + 1);
                if (offsetOfNextCharacter < document.TextLength && document.GetCharAt(offsetOfNextCharacter) == ';')
                    return offset + 1;

                AddFold(document, folds, startOffset, offsetOfClosingBracket + 1, "{...}");

                // Skip to offset after '}'. (Ignore nested blocks.)
                offset = offsetOfClosingBracket + 1;
                return offset;
            }

            return offset + 1;
        }
Esempio n. 38
0
        int SearchBracketForward(TextDocument document, int offset, char openBracket, char closingBracket)
		{
			bool inString = false;
			bool inChar   = false;
			bool verbatim = false;
			
			bool lineComment  = false;
			bool blockComment = false;
			
			if (offset < 0) return -1;
			
			// first try "quick find" - find the matching bracket if there is no string/comment in the way
			int quickResult = QuickSearchBracketForward(document, offset, openBracket, closingBracket);
			if (quickResult >= 0) return quickResult;
			
			// we need to parse the line from the beginning, so get the line start position
			int linestart = ScanLineStart(document, offset);
			
			int brackets = 1;
			
			while (offset < document.TextLength) {
				char ch = document.GetCharAt(offset);
				switch (ch) {
					case '\r':
					case '\n':
						lineComment = false;
						inChar = false;
						if (!verbatim) inString = false;
						break;
					case '/':
						if (blockComment) {
							Debug.Assert(offset > 0);
							if (document.GetCharAt(offset - 1) == '*') {
								blockComment = false;
							}
						}
						if (!inString && !inChar && offset + 1 < document.TextLength) {
							if (!blockComment && document.GetCharAt(offset + 1) == '/') {
								lineComment = true;
							}
							if (!lineComment && document.GetCharAt(offset + 1) == '*') {
								blockComment = true;
							}
						}
						break;
					case '"':
						if (!(inChar || lineComment || blockComment)) {
							if (inString && verbatim) {
								if (offset + 1 < document.TextLength && document.GetCharAt(offset + 1) == '"') {
									++offset; // skip escaped quote
									inString = false; // let the string go
								} else {
									verbatim = false;
								}
							} else if (!inString && offset > 0 && document.GetCharAt(offset - 1) == '@') {
								verbatim = true;
							}
							inString = !inString;
						}
						break;
					case '\'':
						if (!(inString || lineComment || blockComment)) {
							inChar = !inChar;
						}
						break;
					case '\\':
						if ((inString && !verbatim) || inChar)
							++offset; // skip next character
						break;
						default :
							if (ch == openBracket) {
							if (!(inString || inChar || lineComment || blockComment)) {
								++brackets;
							}
						} else if (ch == closingBracket) {
							if (!(inString || inChar || lineComment || blockComment)) {
								--brackets;
								if (brackets == 0) {
									return offset;
								}
							}
						}
						break;
				}
				++offset;
			}
			return -1;
		}
Esempio n. 39
0
        /// <summary>
        /// Skips any comments that start at the current offset.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <returns>The index of the next character after the comments.</returns>
        private static int SkipComment(TextDocument document, int offset)
        {
            if (offset >= document.TextLength - 1)
                return offset + 1;

            char current = document.GetCharAt(offset);
            char next = document.GetCharAt(offset + 1);

            if (current == '/' && next == '/')
            {
                // Skip line comment "//"
                var line = document.GetLineByOffset(offset);
                int offsetOfNextLine = line.Offset + line.TotalLength;
                return offsetOfNextLine;
            }

            if (current == '/' && next == '*')
            {
                // Skip block comment "/* ... */"
                offset += 2;
                while (offset + 1 < document.TextLength)
                {
                    if (document.GetCharAt(offset) == '*' && document.GetCharAt(offset + 1) == '/')
                    {
                        offset = offset + 2;
                        break;
                    }
                    offset++;
                }
                return offset;
            }

            return offset + 1;
        }
Esempio n. 40
0
        int QuickSearchBracketForward(TextDocument document, int offset, char openBracket, char closingBracket)
		{
			int brackets = 1;
			// try "quick find" - find the matching bracket if there is no string/comment in the way
			for (int i = offset; i < document.TextLength; ++i) {
				char ch = document.GetCharAt(i);
				if (ch == openBracket) {
					++brackets;
				} else if (ch == closingBracket) {
					--brackets;
					if (brackets == 0) return i;
				} else if (ch == '"') {
					break;
				} else if (ch == '\'') {
					break;
				} else if (ch == '/' && i > 0) {
					if (document.GetCharAt(i - 1) == '/') break;
				} else if (ch == '*' && i > 0) {
					if (document.GetCharAt(i - 1) == '/') break;
				}
			}
			return -1;
		}
Esempio n. 41
0
 public char this[int o] {
     get {
         return(document.GetCharAt(o));
     }
 }
Esempio n. 42
0
        /// <summary>
        /// Checks whether a region (offset + length) matches a given word.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The length.</param>
        /// <param name="word">The word.</param>
        /// <returns><see langword="true"/> if region matches word.</returns>
        /// <remarks>
        /// The comparison is case-sensitive.
        /// </remarks>
        internal static bool CompareSegment(TextDocument document, int offset, int length, string word)
        {
            if (length != word.Length || document.TextLength < offset + length)
                return false;

            for (int i = 0; i < length; ++i)
                if (document.GetCharAt(offset + i) != word[i])
                    return false;

            return true;
        }
Esempio n. 43
0
 public void GetCharAt0EmptyDocument()
 {
     Assert.Throws <ArgumentOutOfRangeException>(() => document.GetCharAt(0));
 }
Esempio n. 44
0
 private static int FindPrevWordStart(TextDocument document, int offset, IList<char> allowedChars)
 {
     for (var num = offset - 1; num != -1; num--)
     {
         var charAt = document.GetCharAt(num);
         if (!IsWordPart(charAt) && !allowedChars.Contains(charAt))
         {
             return num + 1;
         }
     }
     return 0;
 }