private static int SkipToPrefixWithWhiteSpace(ref DocSlice text, string prefix, int i) { Contract.Requires(i >= 0); Contract.Requires(!String.IsNullOrEmpty(prefix)); Contract.Ensures(Contract.Result <int>() >= -1); Contract.Ensures(Contract.Result <int>() < text.Length); Contract.Assert(prefix != null); while (i < text.Length && Char.IsWhiteSpace(text[i])) { i++; } if (i >= text.Length) { return(-1); } int start = i; int j = 0; while (i < text.Length && j < prefix.Length && text[i] == prefix[j]) { i++; j++; } if (j == prefix.Length && i < text.Length && Char.IsWhiteSpace(text[i])) { return(start); } return(-1); }
private string /*?*/ GetSource(string prefix, SourceContext sctx, out bool isVB, bool islegacy = false) { isVB = false; if (!sctx.IsValid) { return(null); } if (sctx.StartLine <= 0) { return(null); } SourceDocument doc = GetDocument(sctx.Document); if (doc == null) { return(null); } DocSlice slice = new DocSlice(doc, sctx.StartLine, (islegacy) ? 0 : sctx.StartColumn, sctx.EndLine); var parsedText = Parse(prefix, slice, out isVB); return(parsedText); }
private static string ParseVBIfThenText(DocSlice text, int start) { Contract.Requires(start >= 0); int i = start; while (i < text.Length) { // find space before Then while (i < text.Length && !Char.IsWhiteSpace(text[i])) { i++; } // skip white space (or past text) i++; // check Then if (HasChar('T', text, i) && HasChar('h', text, i + 1) && HasChar('e', text, i + 2) && HasChar('n', text, i + 3)) { return(text.Substring(start, i - start)); } } return(null); }
private static bool HasChar(char c, DocSlice text, int i) { Contract.Requires(i >= 0); Contract.Ensures(i < text.Length || !Contract.Result <bool>()); if (i >= text.Length) { return(false); } return(text[i] == c); }
private static int FindPreceedingComma(ref DocSlice text, int i) { Contract.Requires(i >= 0); Contract.Requires(i < text.Length); Contract.Ensures(Contract.Result <int>() >= -1); Contract.Ensures(Contract.Result <int>() <= i); bool insideQuotes = false; bool insideDoubleQuotes = false; int parenCount = 0; int angleCount = 0; i--; // skip closing paren while (i >= 0) { Contract.Assert(i < text.Length); if (!insideDoubleQuotes && text[i] == '\'' && !IsEscape(ref text, i - 1)) { insideQuotes = !insideQuotes; } if (!insideQuotes && text[i] == '"' && !IsEscape(ref text, i - 1)) { insideDoubleQuotes = !insideDoubleQuotes; } if (insideDoubleQuotes || insideQuotes) { // skip } else { if (text[i] == ',' && angleCount == 0 && parenCount == 0) { return(i); } else if (text[i] == ')') { parenCount++; } else if (text[i] == '(') { parenCount--; } else if (text[i] == '>') { angleCount++; } else if (text[i] == '<') { angleCount--; } } i--; } return(-1); }
private static string /*?*/ Parse(string prefix, DocSlice /*?*/ text, out bool isVB) { int i; if (prefix == "if") { // legacy. Watch for VB If ... Then, in which case we are not seeing any parentheses i = SkipToPrefixWithWhiteSpace(ref text, "If", 0); if (i >= 0) { isVB = true; return(ParseVBIfThenText(text, i + 3)); } } isVB = false; // skip to first open paren i = SkipToOpenParen(ref text, 0); if (i < 0) { return(null); } i++; // skip open paren // handle VB generics (Of if (i < text.Length && i + 1 < text.Length && text[i] == 'O' && text[i + 1] == 'f') { i = SkipToMatchingCloseParen(ref text, i + 2, false); if (i < 0) { return(null); } i = SkipToOpenParen(ref text, i + 1); if (i < 0) { return(null); } i++; // skip open paren } int indexOfFirstCharOfCondition = i; int closingParen = SkipToMatchingCloseParen(ref text, i, true); if (closingParen < indexOfFirstCharOfCondition) { return(null); } return(text.Substring(indexOfFirstCharOfCondition, closingParen - indexOfFirstCharOfCondition)); }
private static int SkipToOpenParen(ref DocSlice text, int i) { Contract.Requires(i >= 0); Contract.Ensures(Contract.Result <int>() >= -1); Contract.Ensures(Contract.Result <int>() < text.Length); while (i < text.Length && text[i] != '(') { i++; } if (i < text.Length) { return(i); } return(-1); }
private static bool IsEscape(ref DocSlice text, int i) { Contract.Requires(i < text.Length); if (i < 0) { return(false); } if (text[i] != '\\') { return(false); } // avoid escaped backslash if (!IsEscape(ref text, i - 1)) { return(true); } return(false); }
private static int SkipToMatchingCloseParen(ref DocSlice text, int i, bool allowCommaAsEndingParen) { Contract.Requires(i >= 0); Contract.Ensures(Contract.Result <int>() >= -1); Contract.Ensures(Contract.Result <int>() < text.Length); bool containsComma; var closingParen = FindClosingParenthesis(ref text, i, out containsComma); if (closingParen < 0 || !allowCommaAsEndingParen || !containsComma) { return(closingParen); } var commaPos = FindPreceedingComma(ref text, closingParen); if (commaPos >= 0) { return(commaPos); } return(closingParen); }