static VBNetFormattingStrategy() { statements = new List <VBStatement>(); statements.Add(new VBStatement(@"^if.*?(then|\s+_)$", "^end ?if$", "End If", 1, Tokens.If)); statements.Add(new VBStatement(@"\bclass\s+\w+\s*($|\(\s*Of)", "^end class$", "End Class", 1, Tokens.Class)); statements.Add(new VBStatement(@"\bnamespace\s+\w+(\.\w+)*$", "^end namespace$", "End Namespace", 1, Tokens.Namespace)); statements.Add(new VBStatement(@"\bmodule\s+\w+$", "^end module$", "End Module", 1, Tokens.Module)); statements.Add(new VBStatement(@"\bstructure\s+\w+\s*($|\(\s*Of)", "^end structure$", "End Structure", 1, Tokens.Structure)); statements.Add(new VBStatement(@"^while\s+", "^end while$", "End While", 1, Tokens.While)); statements.Add(new VBStatement(@"^select case", "^end select$", "End Select", 1, Tokens.Select)); statements.Add(new VBStatement(@"(?<!\b(delegate|mustoverride|declare(\s+(unicode|ansi|auto))?)\s+)\bsub\s+\w+", @"^end\s+sub$", "End Sub", 1, Tokens.Sub)); statements.Add(new VBStatement(@"(?<!\bmustoverride (readonly |writeonly )?)\bproperty\s+\w+", @"^end\s+property$", "End Property", 1, Tokens.Property)); statements.Add(new VBStatement(@"(?<!\b(delegate|mustoverride|declare(\s+(unicode|ansi|auto))?)\s+)\bfunction\s+\w+", @"^end\s+function$", "End Function", 1, Tokens.Function)); statements.Add(new VBStatement(@"\boperator(\s*[\+\-\*\/\&\^\>\<\=\\]+\s*|\s+\w+\s*)\(", @"^end\s+operator$", "End Operator", 1, Tokens.Operator)); statements.Add(new VBStatement(@"\bfor\s+.*?$", "^next( \\w+)?$", "Next", 1, Tokens.For)); statements.Add(new VBStatement(@"^synclock\s+.*?$", "^end synclock$", "End SyncLock", 1, Tokens.SyncLock)); statements.Add(new VBStatement(@"^get$", "^end get$", "End Get", 1, Tokens.Get)); statements.Add(new VBStatement(@"^with\s+.*?$", "^end with$", "End With", 1, Tokens.With)); statements.Add(new VBStatement(@"^set(\s*\(.*?\))?$", "^end set$", "End Set", 1, Tokens.Set)); statements.Add(new VBStatement(@"^try$", "^end try$", "End Try", 1, Tokens.Try)); statements.Add(new VBStatement(@"^do\s+.+?$", "^loop$", "Loop", 1, Tokens.Do)); statements.Add(new VBStatement(@"^do$", "^loop .+?$", "Loop While ", 1, Tokens.Do)); statements.Add(new VBStatement(@"\benum\s+\w+$", "^end enum$", "End Enum", 1, Tokens.Enum)); interfaceStatement = new VBStatement(@"\binterface\s+\w+\s*($|\(\s*Of)", "^end interface$", "End Interface", 1, Tokens.Interface); statements.Add(interfaceStatement); statements.Add(new VBStatement(@"\busing\s+", "^end using$", "End Using", 1, Tokens.Using)); statements.Add(new VBStatement(@"^#region\s+", "^#end region$", "#End Region", 0, -1)); }
static int FindEndStatementAroundOffset(IDocument document, int offset, out VBStatement statement) { IDocumentLine line = document.GetLineForOffset(offset); string interestingText = line.Text.TrimLine().Trim(' ', '\t'); //LoggingService.Debug("text: '" + interestingText + "'"); foreach (VBStatement s in VBNetFormattingStrategy.Statements) { Match match = Regex.Matches(interestingText, s.EndRegex, RegexOptions.Singleline | RegexOptions.IgnoreCase).OfType <Match>().FirstOrDefault(); if (match != null) { //LoggingService.DebugFormatted("Found end statement at offset {1}: {0}", s, offset); statement = s; int result = match.Index + (line.Length - line.Text.TrimStart(' ', '\t').Length) + line.Offset; if (offset >= result && offset <= (result + match.Length)) { return(result); } } } statement = null; return(-1); }
static Token GetClosestMissing(List <Token> missingEnds, VBStatement statement, ITextEditor editor, int lineNr) { Token closest = null; int diff = 0; foreach (Token t in missingEnds) { if (!IsSingleLine(t.Location.Line, editor)) { if (IsMatchingStatement(t, statement) && ((diff = lineNr - t.Location.Line) > 0)) { if (closest == null) { closest = t; } else { if (diff < lineNr - closest.Location.Line) { closest = t; } } } } } return(closest); }
bool IsEndStatementNeeded(ITextEditor editor, ref VBStatement statement, int lineNr) { Stack <Token> tokens = new Stack <Token>(); List <Token> missingEnds = new List <Token>(); ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text)); Token currentToken = null; Token prevToken = null; while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { if (prevToken == null) { prevToken = currentToken; } if (IsBlockStart(lexer, currentToken, prevToken)) { if ((tokens.Count > 0 && tokens.Peek().Kind != Tokens.Interface) || IsDeclaration(currentToken.Kind)) { tokens.Push(currentToken); } } if (IsBlockEnd(currentToken, prevToken)) { while (tokens.Count > 0 && !IsMatchingEnd(tokens.Peek(), currentToken)) { missingEnds.Add(tokens.Pop()); } if (tokens.Count > 0) { if (IsMatchingEnd(tokens.Peek(), currentToken)) { tokens.Pop(); } } } prevToken = currentToken; } while (tokens.Count > 0) { missingEnds.Add(tokens.Pop()); } if (missingEnds.Count > 0) { return(GetClosestMissing(missingEnds, statement, editor, lineNr) != null); } else { return(false); } }
void DoInsertionOnLine(string terminator, IDocumentLine currentLine, IDocumentLine lineAbove, string textToReplace, ITextEditor editor, int lineNr) { string curLineText = currentLine.Text; if (Regex.IsMatch(textToReplace.Trim(), "^If .*[^_]$", RegexOptions.IgnoreCase)) { if (!Regex.IsMatch(textToReplace, "\\bthen\\b", RegexOptions.IgnoreCase)) { string specialThen = "Then"; // do special check in cases like If t = True' comment if (editor.Document.GetCharAt(lineAbove.Offset + textToReplace.Length) == '\'') { specialThen += " "; } if (editor.Document.GetCharAt(lineAbove.Offset + textToReplace.Length - 1) != ' ') { specialThen = " " + specialThen; } editor.Document.Insert(lineAbove.Offset + textToReplace.Length, specialThen); textToReplace += specialThen; } } // check #Region statements if (Regex.IsMatch(textToReplace.Trim(), "^#Region", RegexOptions.IgnoreCase) && LookForEndRegion(editor)) { string indentation = DocumentUtilitites.GetWhitespaceAfter(editor.Document, lineAbove.Offset); textToReplace += indentation + "\r\n" + indentation + "#End Region"; editor.Document.Replace(currentLine.Offset, currentLine.Length, textToReplace); } foreach (VBStatement statement_ in statements) { VBStatement statement = statement_; // allow passing statement byref if (Regex.IsMatch(textToReplace.Trim(), statement.StartRegex, RegexOptions.IgnoreCase)) { string indentation = DocumentUtilitites.GetWhitespaceAfter(editor.Document, lineAbove.Offset); if (IsEndStatementNeeded(editor, ref statement, lineNr)) { editor.Document.Replace(currentLine.Offset, currentLine.Length, terminator + indentation + statement.EndStatement); } if (!IsInsideInterface(editor, lineNr) || statement == interfaceStatement) { for (int i = 0; i < statement.IndentPlus; i++) { indentation += editor.Options.IndentationString; } } editor.Document.Replace(currentLine.Offset, currentLine.Length, indentation + curLineText.Trim()); editor.Caret.Line = currentLine.LineNumber; editor.Caret.Column = indentation.Length; return; } } }
static bool IsMatchingStatement(Token token, VBStatement statement) { if (token.Kind == Tokens.For && statement.EndStatement == "Next") { return(true); } if (token.Kind == Tokens.Do && statement.EndStatement.StartsWith("Loop", StringComparison.OrdinalIgnoreCase)) { return(true); } bool empty = !string.IsNullOrEmpty(token.Value); bool match = statement.EndStatement.IndexOf(token.Value, StringComparison.OrdinalIgnoreCase) != -1; return(empty && match); }
static Token GetClosestMissing(List<Token> missingEnds, VBStatement statement, ITextEditor editor, int lineNr) { Token closest = null; int diff = 0; foreach (Token t in missingEnds) { if (!IsSingleLine(t.Location.Line, editor)) { if (IsMatchingStatement(t, statement) && ((diff = lineNr - t.Location.Line) > 0)) { if (closest == null) { closest = t; } else { if (diff < lineNr - closest.Location.Line) closest = t; } } } } return closest; }
bool IsEndStatementNeeded(ITextEditor editor, ref VBStatement statement, int lineNr) { Stack<Token> tokens = new Stack<Token>(); List<Token> missingEnds = new List<Token>(); ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text)); Token currentToken = null; Token prevToken = null; while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { if (prevToken == null) prevToken = currentToken; if (IsBlockStart(lexer, currentToken, prevToken)) { if ((tokens.Count > 0 && tokens.Peek().Kind != Tokens.Interface) || IsDeclaration(currentToken.Kind)) tokens.Push(currentToken); } if (IsBlockEnd(currentToken, prevToken)) { while (tokens.Count > 0 && !IsMatchingEnd(tokens.Peek(), currentToken)) { missingEnds.Add(tokens.Pop()); } if (tokens.Count > 0) { if (IsMatchingEnd(tokens.Peek(), currentToken)) tokens.Pop(); } } prevToken = currentToken; } while (tokens.Count > 0) missingEnds.Add(tokens.Pop()); if (missingEnds.Count > 0) return GetClosestMissing(missingEnds, statement, editor, lineNr) != null; else return false; }
static int FindEndStatement(IDocument document, VBStatement statement) { return -1; }
static int FindBeginStatement(IDocument document, VBStatement statement, Location endLocation, out int length) { ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, document.CreateReader()); Token currentToken = null; Token prevToken = null; int lookFor = statement.StatementToken; Stack<Token> tokens = new Stack<Token>(); if (statement.EndStatement == "Next") { lookFor = Tokens.For; } Token result = null; // Token firstModifier = null; while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { if (prevToken == null) prevToken = currentToken; // if (IsModifier(currentToken)) { // if (firstModifier == null) // firstModifier = currentToken; // } else // firstModifier = null; if (VBNetFormattingStrategy.IsBlockStart(lexer, currentToken, prevToken)) { tokens.Push(currentToken); } if (VBNetFormattingStrategy.IsBlockEnd(currentToken, prevToken)) { while (tokens.Count > 0 && !VBNetFormattingStrategy.IsMatchingEnd(tokens.Peek(), currentToken)) tokens.Pop(); if (tokens.Count > 0) { Token t = tokens.Pop(); if (currentToken.Location.Line == endLocation.Line) { result = t; break; } } } prevToken = currentToken; } if (result != null) { int endOffset = document.PositionToOffset(result.EndLocation.Line, result.EndLocation.Column); int offset = document.PositionToOffset(result.Location.Line, result.Location.Column); length = endOffset - offset; return offset; } length = 0; return -1; }
static int FindEndStatementAroundOffset(IDocument document, int offset, out VBStatement statement) { IDocumentLine line = document.GetLineForOffset(offset); string interestingText = VBNetFormattingStrategy.TrimLine(line.Text).Trim(' ', '\t'); //LoggingService.Debug("text: '" + interestingText + "'"); foreach (VBStatement s in VBNetFormattingStrategy.Statements) { Match match = Regex.Matches(interestingText, s.EndRegex, RegexOptions.Singleline | RegexOptions.IgnoreCase).OfType<Match>().FirstOrDefault(); if (match != null) { //LoggingService.DebugFormatted("Found end statement at offset {1}: {0}", s, offset); statement = s; int result = match.Index + (line.Length - line.Text.TrimStart(' ', '\t').Length) + line.Offset; if (offset >= result && offset <= (result + match.Length)) return result; } } statement = null; return -1; }
static int FindBeginStatementAroundOffset(IDocument document, int offset, out VBStatement statement, out int length) { length = 0; statement = null; return -1; }
static int FindEndStatement(IDocument document, VBStatement statement) { return(-1); }
static int FindBeginStatement(IDocument document, VBStatement statement, Location endLocation, out int length) { ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, document.CreateReader()); Token currentToken = null; Token prevToken = null; int lookFor = statement.StatementToken; Stack <Token> tokens = new Stack <Token>(); if (statement.EndStatement == "Next") { lookFor = Tokens.For; } Token result = null; // Token firstModifier = null; while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { if (prevToken == null) { prevToken = currentToken; } // if (IsModifier(currentToken)) { // if (firstModifier == null) // firstModifier = currentToken; // } else // firstModifier = null; if (VBNetFormattingStrategy.IsBlockStart(lexer, currentToken, prevToken)) { tokens.Push(currentToken); } if (VBNetFormattingStrategy.IsBlockEnd(currentToken, prevToken)) { while (tokens.Count > 0 && !VBNetFormattingStrategy.IsMatchingEnd(tokens.Peek(), currentToken)) { tokens.Pop(); } if (tokens.Count > 0) { Token t = tokens.Pop(); if (currentToken.Location.Line == endLocation.Line) { result = t; break; } } } prevToken = currentToken; } if (result != null) { int endOffset = document.PositionToOffset(result.EndLocation.Line, result.EndLocation.Column); int offset = document.PositionToOffset(result.Location.Line, result.Location.Column); length = endOffset - offset; return(offset); } length = 0; return(-1); }
static bool IsMatchingStatement(Token token, VBStatement statement) { if (token.Kind == Tokens.For && statement.EndStatement == "Next") return true; if (token.Kind == Tokens.Do && statement.EndStatement.StartsWith("Loop", StringComparison.OrdinalIgnoreCase)) return true; bool empty = !string.IsNullOrEmpty(token.Value); bool match = statement.EndStatement.IndexOf(token.Value, StringComparison.OrdinalIgnoreCase) != -1; return empty && match; }
static VBNetFormattingStrategy() { statements = new List<VBStatement>(); statements.Add(new VBStatement(@"^if.*?(then|\s+_)$", "^end ?if$", "End If", 1, Tokens.If)); statements.Add(new VBStatement(@"\bclass\s+\w+\s*($|\(\s*Of)", "^end class$", "End Class", 1, Tokens.Class)); statements.Add(new VBStatement(@"\bnamespace\s+\w+(\.\w+)*$", "^end namespace$", "End Namespace", 1, Tokens.Namespace)); statements.Add(new VBStatement(@"\bmodule\s+\w+$", "^end module$", "End Module", 1, Tokens.Module)); statements.Add(new VBStatement(@"\bstructure\s+\w+\s*($|\(\s*Of)", "^end structure$", "End Structure", 1, Tokens.Structure)); statements.Add(new VBStatement(@"^while\s+", "^end while$", "End While", 1, Tokens.While)); statements.Add(new VBStatement(@"^select case", "^end select$", "End Select", 1, Tokens.Select)); statements.Add(new VBStatement(@"(?<!\b(delegate|mustoverride|declare(\s+(unicode|ansi|auto))?)\s+)\bsub\s+\w+", @"^end\s+sub$", "End Sub", 1, Tokens.Sub)); statements.Add(new VBStatement(@"(?<!\bmustoverride (readonly |writeonly )?)\bproperty\s+\w+", @"^end\s+property$", "End Property", 1, Tokens.Property)); statements.Add(new VBStatement(@"(?<!\b(delegate|mustoverride|declare(\s+(unicode|ansi|auto))?)\s+)\bfunction\s+\w+", @"^end\s+function$", "End Function", 1, Tokens.Function)); statements.Add(new VBStatement(@"\boperator(\s*[\+\-\*\/\&\^\>\<\=\\]+\s*|\s+\w+\s*)\(", @"^end\s+operator$", "End Operator", 1, Tokens.Operator)); statements.Add(new VBStatement(@"\bfor\s+.*?$", "^next( \\w+)?$", "Next", 1, Tokens.For)); statements.Add(new VBStatement(@"^synclock\s+.*?$", "^end synclock$", "End SyncLock", 1, Tokens.SyncLock)); statements.Add(new VBStatement(@"^get$", "^end get$", "End Get", 1, Tokens.Get)); statements.Add(new VBStatement(@"^with\s+.*?$", "^end with$", "End With", 1, Tokens.With)); statements.Add(new VBStatement(@"^set(\s*\(.*?\))?$", "^end set$", "End Set", 1, Tokens.Set)); statements.Add(new VBStatement(@"^try$", "^end try$", "End Try", 1, Tokens.Try)); statements.Add(new VBStatement(@"^do\s+.+?$", "^loop$", "Loop", 1, Tokens.Do)); statements.Add(new VBStatement(@"^do$", "^loop .+?$", "Loop While ", 1, Tokens.Do)); statements.Add(new VBStatement(@"\benum\s+\w+$", "^end enum$", "End Enum", 1, Tokens.Enum)); interfaceStatement = new VBStatement(@"\binterface\s+\w+\s*($|\(\s*Of)", "^end interface$", "End Interface", 1, Tokens.Interface); statements.Add(interfaceStatement); statements.Add(new VBStatement(@"\busing\s+", "^end using$", "End Using", 1, Tokens.Using)); statements.Add(new VBStatement(@"^#region\s+", "^#end region$", "#End Region", 0, -1)); }
static int FindBeginStatementAroundOffset(IDocument document, int offset, out VBStatement statement, out int length) { length = 0; statement = null; return(-1); }