static int SmartIndentInternal(ITextEditor editor, int begin, int end) { ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text)); ExpressionFinder context = new ExpressionFinder(); Stack <string> indentation = new Stack <string>(); indentation.Push(string.Empty); List <int> eols = new List <int>(); bool inInterface = false; bool isMustOverride = false; bool isDeclare = false; bool isDelegate = false; Token currentToken = null; Token prevToken = null; int blockStart = 1; int lambdaNesting = 0; bool sawAttribute = false; while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { if (context.InContext(Context.Attribute) && currentToken.Kind == Tokens.GreaterThan) { sawAttribute = true; } context.InformToken(currentToken); if (prevToken == null) { prevToken = currentToken; } if (currentToken.Kind == Tokens.MustOverride) { isMustOverride = true; } if (currentToken.Kind == Tokens.Delegate) { isDelegate = true; } if (currentToken.Kind == Tokens.Declare) { isDeclare = true; } if (currentToken.Kind == Tokens.EOL) { isDelegate = isDeclare = isMustOverride = sawAttribute = false; eols.Add(currentToken.Location.Line); } if (IsBlockEnd(currentToken, prevToken)) { // indent the lines inside the block // this is an End-statement // hence we indent from blockStart to the previous line int blockEnd = currentToken.Location.Line - 1; // if this is a lambda end include End-Statement in block // if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) { // blockEnd++; // } ApplyToRange(editor, indentation, eols, blockStart, blockEnd, begin, end, sawAttribute); if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) { Unindent(indentation); ApplyToRange(editor, indentation, eols, currentToken.Location.Line, currentToken.Location.Line, begin, end, sawAttribute); } if (currentToken.Kind == Tokens.Interface) { inInterface = false; } if (!inInterface && !isMustOverride && !isDeclare && !isDelegate) { Unindent(indentation); if (currentToken.Kind == Tokens.Select) { Unindent(indentation); } } // block start is this line (for the lines between two blocks) blockStart = currentToken.Location.Line; if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) { blockStart++; lambdaNesting--; } } bool isMultiLineLambda; if (IsBlockStart(lexer, currentToken, prevToken, out isMultiLineLambda)) { // indent the lines between the last and this block // this is a Begin-statement // hence we indent from blockStart to the this line int lastVisualLine = FindNextEol(lexer); eols.Add(lastVisualLine); ApplyToRange(editor, indentation, eols, blockStart, lastVisualLine, begin, end, sawAttribute); if (isMultiLineLambda && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) { lambdaNesting++; int endColumn = currentToken.Location.Column; int startColumn = DocumentUtilitites.GetWhitespaceAfter(editor.Document, editor.Document.GetLine(lastVisualLine).Offset).Length; if (startColumn < endColumn) { Indent(editor, indentation, new string(' ', endColumn - startColumn - 1)); } } if (!inInterface && !isMustOverride && !isDeclare && !isDelegate) { Indent(editor, indentation); if (currentToken.Kind == Tokens.Select) { Indent(editor, indentation); } } if (currentToken.Kind == Tokens.Interface) { inInterface = true; } // block start is the following line (for the lines inside a block) blockStart = lastVisualLine + 1; } prevToken = currentToken; } ApplyToRange(editor, indentation, eols, blockStart, editor.Document.TotalNumberOfLines, begin, end, sawAttribute); return((indentation.PeekOrDefault() ?? string.Empty).Length); }