Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/vbnet@5780 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61pull/1/head
30 changed files with 3228 additions and 2737 deletions
@ -0,0 +1,246 @@
@@ -0,0 +1,246 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com" />
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.NRefactory.Parser; |
||||
using ICSharpCode.NRefactory.Parser.VB; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace VBNetBinding |
||||
{ |
||||
public class VBNetBracketSearcher : IBracketSearcher |
||||
{ |
||||
string openingBrackets = "([{"; |
||||
string closingBrackets = ")]}"; |
||||
|
||||
public BracketSearchResult SearchBracket(IDocument document, int offset) |
||||
{ |
||||
if (offset > 0) { |
||||
char 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) |
||||
return new BracketSearchResult(Math.Min(offset - 1, otherOffset), 1, Math.Max(offset - 1, otherOffset), 1); |
||||
|
||||
int length; |
||||
VBStatement statement; |
||||
|
||||
int startIndex = FindBeginStatementAroundOffset(document, offset, out statement, out length); |
||||
int endIndex = 0; |
||||
|
||||
if (statement != null) |
||||
endIndex = FindEndStatement(document, statement); |
||||
else { |
||||
endIndex = FindEndStatementAroundOffset(document, offset, out statement); |
||||
|
||||
if (statement != null) |
||||
startIndex = FindBeginStatement(document, statement, document.OffsetToPosition(endIndex), out length); |
||||
} |
||||
|
||||
if (startIndex > -1 && endIndex > -1) |
||||
return new BracketSearchResult(startIndex, length, endIndex, statement.EndStatement.Length); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
#region bracket search
|
||||
int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket) |
||||
{ |
||||
bool inString = false; |
||||
char ch; |
||||
int brackets = -1; |
||||
for (int i = offset; i > 0; --i) { |
||||
ch = document.GetCharAt(i); |
||||
if (ch == openBracket && !inString) { |
||||
++brackets; |
||||
if (brackets == 0) return i; |
||||
} else if (ch == closingBracket && !inString) { |
||||
--brackets; |
||||
} else if (ch == '"') { |
||||
inString = !inString; |
||||
} else if (ch == '\n') { |
||||
int lineStart = ScanLineStart(document, i); |
||||
if (lineStart >= 0) { // line could have a comment
|
||||
inString = false; |
||||
for (int j = lineStart; j < i; ++j) { |
||||
ch = document.GetCharAt(j); |
||||
if (ch == '"') inString = !inString; |
||||
if (ch == '\'' && !inString) { |
||||
// comment found!
|
||||
// Skip searching in the comment:
|
||||
i = j; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
inString = false; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
static int ScanLineStart(IDocument document, int offset) |
||||
{ |
||||
bool hasComment = false; |
||||
for (int i = offset - 1; i > 0; --i) { |
||||
char ch = document.GetCharAt(i); |
||||
if (ch == '\n') { |
||||
if (!hasComment) return -1; |
||||
return i + 1; |
||||
} else if (ch == '\'') { |
||||
hasComment = true; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket) |
||||
{ |
||||
bool inString = false; |
||||
bool inComment = false; |
||||
int brackets = 1; |
||||
for (int i = offset; i < document.TextLength; ++i) { |
||||
char ch = document.GetCharAt(i); |
||||
if (ch == '\n') { |
||||
inString = false; |
||||
inComment = false; |
||||
} |
||||
if (inComment) continue; |
||||
if (ch == '"') inString = !inString; |
||||
if (inString) continue; |
||||
if (ch == '\'') { |
||||
inComment = true; |
||||
} else if (ch == openBracket) { |
||||
++brackets; |
||||
} else if (ch == closingBracket) { |
||||
--brackets; |
||||
if (brackets == 0) return i; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
#endregion
|
||||
|
||||
#region statement search
|
||||
int FindBeginStatementAroundOffset(IDocument document, int offset, out VBStatement statement, out int length) |
||||
{ |
||||
length = 0; |
||||
statement = null; |
||||
return -1; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
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; |
||||
|
||||
while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF) { |
||||
if (prevToken == null) |
||||
prevToken = currentToken; |
||||
|
||||
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) { |
||||
|
||||
IDocumentLine line = document.GetLine(result.Location.Line); |
||||
string interestingText = VBNetFormattingStrategy.TrimLine(line.Text).Trim(' ', '\t'); |
||||
|
||||
//LoggingService.Debug("text2: '" + interestingText + "'");
|
||||
|
||||
Match matchResult = Regex.Match(interestingText, statement.StartRegex, RegexOptions.Singleline | RegexOptions.IgnoreCase); |
||||
|
||||
if (matchResult != null) { |
||||
length = matchResult.Value.TrimEnd(' ', '\t').Length; |
||||
int diff = line.Length - line.Text.TrimStart(' ', '\t').Length; |
||||
int start = diff + line.Offset; |
||||
if (IsDeclaration(result.Kind)) { |
||||
length += diff + matchResult.Index; |
||||
return start; |
||||
} |
||||
return matchResult.Index + start; |
||||
} |
||||
} |
||||
|
||||
length = 0; |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
int FindEndStatement(IDocument document, VBStatement statement) |
||||
{ |
||||
return -1; |
||||
} |
||||
#endregion
|
||||
|
||||
bool IsDeclaration(int kind) |
||||
{ |
||||
return kind == Tokens.Sub || kind == Tokens.Function || kind == Tokens.Operator || VBNetFormattingStrategy.IsDeclaration(kind); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue