static int SearchMatchingBracketBackward(IReadonlyTextDocument document, int offset, char openBracket, char closingBracket, CancellationToken cancellationToken) { bool isInBlockComment = false; bool isInLineComment = false; int curStringQuote = -1; var lang = TextMateLanguage.Create(SyntaxHighlightingService.GetScopeForFileName(document.FileName)); var lineComments = lang.LineComments; var blockCommentStarts = lang.BlockComments.Select(b => b.Item1).ToList(); var blockCommentEnds = lang.BlockComments.Select(b => b.Item2).ToList(); var stringQuotes = new string [] { "\"", "'" }; bool startsInLineComment = StartsInLineComment(document, offset); int depth = -1; if (!startsInLineComment) { offset = GetLastSourceCodePosition(document, offset); } while (offset >= 0 && offset < document.Length) { if (offset % 100 == 0 && cancellationToken.IsCancellationRequested) { return(-1); } char ch = document.GetCharAt(offset); // check block comments if (!isInLineComment && curStringQuote < 0) { if (!isInBlockComment) { isInBlockComment = StartsWithListMember(document, blockCommentEnds, offset) >= 0; } else { isInBlockComment = StartsWithListMember(document, blockCommentStarts, offset) < 0; } } if (!isInBlockComment && !isInLineComment) { int i = StartsWithListMember(document, stringQuotes, offset); if (i >= 0) { if (curStringQuote >= 0) { if (curStringQuote == i) { curStringQuote = -1; } } else { curStringQuote = i; } } } switch (ch) { case '\n': case '\r': if (startsInLineComment) { return(-1); } offset--; while (offset > 0 && (document.GetCharAt(offset) == '\n' || document.GetCharAt(offset) == '\r')) { offset--; } offset = GetLastSourceCodePosition(document, offset) + 1; break; default: if (ch == closingBracket) { if (!(curStringQuote >= 0 || isInBlockComment)) { --depth; } } else if (ch == openBracket) { if (!(curStringQuote >= 0 || isInBlockComment)) { ++depth; if (depth == 0) { return(offset); } } } break; } offset--; } return(-1); }