diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCodeCompletionDataProvider.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCodeCompletionDataProvider.cs
new file mode 100644
index 0000000000..2af78c4881
--- /dev/null
+++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCodeCompletionDataProvider.cs
@@ -0,0 +1,51 @@
+//
+//
+//
+//
+// $Revision: 6077 $
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using ICSharpCode.NRefactory.Parser.VB;
+using ICSharpCode.SharpDevelop.Dom;
+using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
+using ICSharpCode.SharpDevelop.Editor;
+using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
+
+namespace ICSharpCode.VBNetBinding
+{
+ public class VBNetCodeCompletionDataProvider : NRefactoryCtrlSpaceCompletionItemProvider
+ {
+ ExpressionResult result;
+
+ public VBNetCodeCompletionDataProvider(ExpressionResult result)
+ : base(LanguageProperties.VBNet, result.Context)
+ {
+ this.result = result;
+ }
+
+ protected override List CtrlSpace(ITextEditor editor, ExpressionContext context)
+ {
+ var list = base.CtrlSpace(editor, context);
+
+ BitArray expectedSet = result.Tag as BitArray;
+
+ if (expectedSet != null)
+ AddVBNetKeywords(list, expectedSet);
+
+ return list;
+ }
+
+ static void AddVBNetKeywords(List ar, BitArray keywords)
+ {
+ for (int i = 0; i < keywords.Length; i++) {
+ if (keywords[i] && i >= Tokens.AddHandler) {
+ ar.Add(new KeywordEntry(Tokens.GetTokenString(i)));
+ }
+ }
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs
index 965d9625e7..55a4f8ff4a 100644
--- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs
+++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs
@@ -6,7 +6,16 @@
//
using System;
+using System.Collections;
+using System.Collections.Generic;
+using ICSharpCode.Core;
+using ICSharpCode.NRefactory;
+using ICSharpCode.NRefactory.Parser;
+using ICSharpCode.NRefactory.Parser.VB;
using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Dom;
+using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
+using ICSharpCode.SharpDevelop.Dom.VBNet;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
@@ -14,34 +23,176 @@ namespace ICSharpCode.VBNetBinding
{
public class VBNetCompletionBinding : ICodeCompletionBinding
{
+ static VBNetCompletionBinding instance;
+
+ public static VBNetCompletionBinding Instance {
+ get {
+ if (instance == null)
+ instance = new VBNetCompletionBinding();
+ return instance;
+ }
+ }
+
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{
+ if (IsInComment(editor))
+ return CodeCompletionKeyPressResult.None;
+
switch (ch) {
+ case '\n':
+ break;
case ' ':
if (CodeCompletionOptions.KeywordCompletionEnabled) {
string word = editor.GetWordBeforeCaret();
if (!string.IsNullOrEmpty(word)) {
- if (HandleKeyword(editor, word))
- return CodeCompletionKeyPressResult.Completed;
+ var list = HandleKeyword(editor, word);
+ editor.ShowCompletionWindow(list);
+ return CodeCompletionKeyPressResult.Completed;
}
}
break;
default:
-
+ if (CodeCompletionOptions.CompleteWhenTyping) {
+ if (editor.SelectionLength > 0) {
+ // allow code completion when overwriting an identifier
+ int endOffset = editor.SelectionStart + editor.SelectionLength;
+ // but block code completion when overwriting only part of an identifier
+ if (endOffset < editor.Document.TextLength && char.IsLetterOrDigit(editor.Document.GetCharAt(endOffset)))
+ return CodeCompletionKeyPressResult.None;
+
+ editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
+ }
+ int cursor = editor.Caret.Offset;
+ char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
+ bool afterUnderscore = prevChar == '_';
+ if (afterUnderscore) {
+ cursor--;
+ prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
+ }
+ if (!char.IsLetterOrDigit(prevChar) && prevChar != '.') {
+ VBNetExpressionFinder ef = new VBNetExpressionFinder(ParserService.GetParseInformation(editor.FileName));
+ ExpressionResult result = ef.FindExpression(editor.Document.Text, cursor);
+ LoggingService.Debug("CC: Beginning to type a word, result=" + result + ", context=" + result.Context);
+ if (result.Context != ExpressionContext.IdentifierExpected) {
+ var provider = new VBNetCodeCompletionDataProvider(result);
+ provider.ShowTemplates = true;
+ provider.AllowCompleteExistingExpression = afterUnderscore;
+ provider.ShowCompletion(editor);
+ return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
+ }
+ }
+ }
break;
}
return CodeCompletionKeyPressResult.None;
}
+ bool IsInComment(ITextEditor editor)
+ {
+ ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, editor.Document.CreateReader());
+
+ Token t = lexer.NextToken();
+ bool inXml = false;
+
+ while (t.Location < editor.Caret.Position) {
+ t = lexer.NextToken();
+
+ if (inXml && (t.Kind != Tokens.Identifier && t.Kind != Tokens.LiteralString && !(t.Kind > Tokens.LiteralDate && t.Kind < Tokens.Colon))) {
+ inXml = false;
+ continue;
+ }
+
+ if (t.Kind > Tokens.LiteralDate && t.Kind < Tokens.Assign)
+ inXml = true;
+ }
+
+ if (inXml) {
+ return true;
+ } else {
+ string lineText = editor.Document.GetLine(t.Location.Line).Text;
+
+ bool inString = false;
+ bool inComment = false;
+
+ for (int i = 0; i < lineText.Length; i++) {
+ char ch = lineText[i];
+
+ if (!inComment && ch == '"')
+ inString = !inString;
+ if (!inString && ch == '\'')
+ inComment = true;
+ }
+
+ return inComment;
+ }
+ }
+
public bool CtrlSpace(ITextEditor editor)
{
+ if (IsInComment(editor))
+ return false;
+
+ if (editor.SelectionLength > 0) {
+ // allow code completion when overwriting an identifier
+ int endOffset = editor.SelectionStart + editor.SelectionLength;
+ // but block code completion when overwriting only part of an identifier
+ if (endOffset < editor.Document.TextLength && char.IsLetterOrDigit(editor.Document.GetCharAt(endOffset)))
+ return false;
+
+ editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
+ }
+ int cursor = editor.Caret.Offset;
+ char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
+ bool afterUnderscore = prevChar == '_';
+ if (afterUnderscore) {
+ cursor--;
+ prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
+ }
+ if (!char.IsLetterOrDigit(prevChar) && prevChar != '.') {
+ VBNetExpressionFinder ef = new VBNetExpressionFinder(ParserService.GetParseInformation(editor.FileName));
+ ExpressionResult result = ef.FindExpression(editor.Document.Text, cursor);
+ LoggingService.Debug("CC: Beginning to type a word, result=" + result + ", context=" + result.Context);
+ if (result.Context != ExpressionContext.IdentifierExpected) {
+ var provider = new VBNetCodeCompletionDataProvider(result);
+ provider.ShowTemplates = true;
+ provider.AllowCompleteExistingExpression = afterUnderscore;
+ provider.ShowCompletion(editor);
+ return true;
+ }
+ }
+
return false;
}
- bool HandleKeyword(ITextEditor editor, string word)
+ sealed class GlobalCompletionItemProvider : CodeCompletionItemProvider
{
- return false;
+ public override ExpressionResult GetExpression(ITextEditor editor)
+ {
+ return new ExpressionResult("Global", ExpressionContext.Importable);
+ }
+ }
+
+ ICompletionItemList HandleKeyword(ITextEditor editor, string word)
+ {
+ DefaultCompletionItemList list = new DefaultCompletionItemList();
+
+ switch (word.ToLowerInvariant()) {
+ case "option":
+ return new TextCompletionItemProvider(
+ "Explicit On", "Explicit Off",
+ "Strict On", "Strict Off",
+ "Compare Binary", "Compare Text",
+ "Infer On", "Infer Off"
+ ).GenerateCompletionList(editor);
+ case "imports":
+ return new GlobalCompletionItemProvider().GenerateCompletionList(editor);
+ break;
+ }
+
+ return list;
}
}
+
+
}
diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin
index e68506c602..6af347b302 100644
--- a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin
+++ b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin
@@ -1,7 +1,7 @@
-
@@ -96,7 +96,7 @@
-
+
diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj
index ffff1cdd5d..28e9ef37a8 100644
--- a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj
+++ b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj
@@ -54,6 +54,7 @@
+
diff --git a/src/Libraries/NRefactory/Project/NRefactory.csproj b/src/Libraries/NRefactory/Project/NRefactory.csproj
index ea015e9367..9e9585c33b 100644
--- a/src/Libraries/NRefactory/Project/NRefactory.csproj
+++ b/src/Libraries/NRefactory/Project/NRefactory.csproj
@@ -61,8 +61,12 @@
-
+
+
+
+
+
ExpressionFinder.atg
@@ -91,7 +95,7 @@
Configuration\GlobalAssemblyInfo.cs
-
+
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs
index e0cb082431..1467132c16 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs
@@ -196,7 +196,7 @@ namespace ICSharpCode.NRefactory.Parser
this.reader = new LATextReader(reader);
}
- protected AbstractLexer(TextReader reader, AbstractLexerState state)
+ protected AbstractLexer(TextReader reader, LexerMemento state)
: this(reader)
{
SetInitialLocation(new Location(state.Column, state.Line));
@@ -368,16 +368,16 @@ namespace ICSharpCode.NRefactory.Parser
///
public abstract void SkipCurrentBlock(int targetToken);
- public event EventHandler SavepointReached;
+ public event EventHandler SavepointReached;
- protected virtual void OnSavepointReached(EventArgs e)
+ protected virtual void OnSavepointReached(SavepointEventArgs e)
{
if (SavepointReached != null) {
SavepointReached(this, e);
}
}
- public virtual AbstractLexerState Export()
+ public virtual LexerMemento Export()
{
throw new NotSupportedException();
}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs
index a5f9378b13..a40f9e0d33 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/ILexer.cs
@@ -111,12 +111,12 @@ namespace ICSharpCode.NRefactory.Parser
/// Used to export the current state of the lexer. The exported state should be
/// complete, so that it is possible to reset the lexer to a previous state completely.
///
- AbstractLexerState Export();
+ LexerMemento Export();
///
/// Is fired by the lexer as soon as a savepoint is reached.
/// The Export-method can be used to retrieve the current state.
///
- event EventHandler SavepointReached;
+ event EventHandler SavepointReached;
}
}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexerState.cs b/src/Libraries/NRefactory/Project/Src/Lexer/LexerMemento.cs
similarity index 90%
rename from src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexerState.cs
rename to src/Libraries/NRefactory/Project/Src/Lexer/LexerMemento.cs
index 666954df76..abfcb7823d 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexerState.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/LexerMemento.cs
@@ -8,7 +8,7 @@ using System;
namespace ICSharpCode.NRefactory.Parser
{
- public abstract class AbstractLexerState
+ public abstract class LexerMemento
{
public int Line { get; set; }
public int Column { get; set; }
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/SavepointEventArgs.cs b/src/Libraries/NRefactory/Project/Src/Lexer/SavepointEventArgs.cs
new file mode 100644
index 0000000000..1ac58392c5
--- /dev/null
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/SavepointEventArgs.cs
@@ -0,0 +1,24 @@
+//
+//
+//
+//
+// $Revision: 6084 $
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace ICSharpCode.NRefactory.Parser
+{
+ public class SavepointEventArgs : EventArgs
+ {
+ public Location SavepointLocation { get; private set; }
+ public LexerMemento State { get; private set; }
+
+ public SavepointEventArgs(Location savepointLocation, LexerMemento state)
+ {
+ this.SavepointLocation = savepointLocation;
+ this.State = state;
+ }
+ }
+}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Block.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Block.cs
new file mode 100644
index 0000000000..1ed14b5aee
--- /dev/null
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Block.cs
@@ -0,0 +1,55 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ICSharpCode.NRefactory.Parser.VB
+{
+ public enum Context
+ {
+ Global,
+ Type,
+ Member,
+ IdentifierExpected,
+ Body,
+ Xml,
+ Attribute,
+ Query,
+ Expression,
+ Debug,
+ Default
+ }
+
+ public class Block : ICloneable
+ {
+ public static readonly Block Default = new Block() {
+ context = Context.Global,
+ lastExpressionStart = Location.Empty
+ };
+
+ public Context context;
+ public Location lastExpressionStart;
+ public bool isClosed;
+
+ public override string ToString()
+ {
+ return string.Format("[Block Context={0}, LastExpressionStart={1}, IsClosed={2}]", context, lastExpressionStart, isClosed);
+ }
+
+ public object Clone()
+ {
+ return new Block() {
+ context = this.context,
+ lastExpressionStart = this.lastExpressionStart,
+ isClosed = this.isClosed
+ };
+ }
+ }
+}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs
index 2e8a78a9dc..88712c4cee 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs
@@ -118,6 +118,13 @@ namespace ICSharpCode.NRefactory.Parser.VB
}
}
+ public bool InContext(Context expected)
+ {
+ return stack
+ .SkipWhile(f => f.context == Context.Expression)
+ .IsElement(fx => fx.context == expected);
+ }
+
public bool NextTokenIsPotentialStartOfExpression {
get { return nextTokenIsPotentialStartOfExpression; }
}
@@ -152,56 +159,4 @@ namespace ICSharpCode.NRefactory.Parser.VB
};
}
}
-
- public class ExpressionFinderState
- {
- public bool WasQualifierTokenAtStart { get; set; }
- public bool NextTokenIsPotentialStartOfExpression { get; set; }
- public bool ReadXmlIdentifier { get; set; }
- public bool NextTokenIsStartOfImportsOrAccessExpression { get; set; }
- public Stack StateStack { get; set; }
- public Stack BlockStack { get; set; }
- public int CurrentState { get; set; }
- }
-
- public enum Context
- {
- Global,
- Type,
- Member,
- IdentifierExpected,
- Body,
- Xml,
- Attribute,
- Query,
- Expression,
- Debug,
- Default
- }
-
- public class Block : ICloneable
- {
- public static readonly Block Default = new Block() {
- context = Context.Global,
- lastExpressionStart = Location.Empty
- };
-
- public Context context;
- public Location lastExpressionStart;
- public bool isClosed;
-
- public override string ToString()
- {
- return string.Format("[Block Context={0}, LastExpressionStart={1}, IsClosed={2}]", context, lastExpressionStart, isClosed);
- }
-
- public object Clone()
- {
- return new Block() {
- context = this.context,
- lastExpressionStart = this.lastExpressionStart,
- isClosed = this.isClosed
- };
- }
- }
}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinderState.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinderState.cs
new file mode 100644
index 0000000000..cc8a069808
--- /dev/null
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinderState.cs
@@ -0,0 +1,25 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ICSharpCode.NRefactory.Parser.VB
+{
+ public class ExpressionFinderState
+ {
+ public bool WasQualifierTokenAtStart { get; set; }
+ public bool NextTokenIsPotentialStartOfExpression { get; set; }
+ public bool ReadXmlIdentifier { get; set; }
+ public bool NextTokenIsStartOfImportsOrAccessExpression { get; set; }
+ public Stack StateStack { get; set; }
+ public Stack BlockStack { get; set; }
+ public int CurrentState { get; set; }
+ }
+}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Extensions.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Extensions.cs
new file mode 100644
index 0000000000..f1a19ea0e9
--- /dev/null
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Extensions.cs
@@ -0,0 +1,26 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ICSharpCode.NRefactory.Parser.VB
+{
+ public static class Extensions
+ {
+ public static bool IsElement(this IEnumerable items, Func check)
+ {
+ T item = items.FirstOrDefault();
+
+ if (item != null)
+ return check(item);
+ return false;
+ }
+ }
+}
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs
index c5c860059a..1507aa0446 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs
@@ -34,12 +34,12 @@ namespace ICSharpCode.NRefactory.Parser.VB
ef = new ExpressionFinder();
}
- public Lexer(TextReader reader, AbstractLexerState state) : base(reader, state)
+ public Lexer(TextReader reader, LexerMemento state) : base(reader, state)
{
- if (!(state is VBLexerState))
+ if (!(state is VBLexerMemento))
throw new InvalidOperationException("state must be a VBLexerState");
- var vbState = state as VBLexerState;
+ var vbState = state as VBLexerMemento;
ef = new ExpressionFinder(vbState.ExpressionFinder);
lineEnd = vbState.LineEnd;
isAtLineBegin = vbState.IsAtLineBegin;
@@ -421,17 +421,17 @@ namespace ICSharpCode.NRefactory.Parser.VB
// 4th rule
// after a less-than (<) in an attribute context
- if (prevTokenKind == Tokens.LessThan && ef.CurrentBlock.context == Context.Attribute)
+ if (prevTokenKind == Tokens.LessThan && ef.InContext(Context.Attribute))
return true;
// 5th rule
// before a greater-than (>) in an attribute context
- if (nextTokenKind == Tokens.GreaterThan && ef.CurrentBlock.context == Context.Attribute)
+ if (nextTokenKind == Tokens.GreaterThan && ef.InContext(Context.Attribute))
return true;
// 6th rule
// after a greater-than (>) in a non-file-level attribute context
- if (prevTokenKind == Tokens.GreaterThan && ef.CurrentBlock.context == Context.Attribute)
+ if (prevTokenKind == Tokens.GreaterThan && ef.InContext(Context.Attribute))
return true;
// 7th rule
@@ -440,7 +440,7 @@ namespace ICSharpCode.NRefactory.Parser.VB
Tokens.Where, Tokens.Order, Tokens.By, Tokens.Ascending, Tokens.Descending, Tokens.Take,
Tokens.Skip, Tokens.Let, Tokens.Group, Tokens.Into, Tokens.On, Tokens.While, Tokens.Join };
if ((queryOperators.Contains(prevTokenKind) || queryOperators.Contains(nextTokenKind))
- && ef.CurrentBlock.context == Context.Query)
+ && ef.InContext(Context.Query))
return true;
// 8th rule
@@ -1133,9 +1133,9 @@ namespace ICSharpCode.NRefactory.Parser.VB
ef.SetContext(type);
}
- public override AbstractLexerState Export()
+ public override LexerMemento Export()
{
- return new VBLexerState() {
+ return new VBLexerMemento() {
Column = Col,
Line = Line,
EncounteredLineContinuation = encounteredLineContinuation,
diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerState.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerMemento.cs
similarity index 92%
rename from src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerState.cs
rename to src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerMemento.cs
index b6cd352cb7..cebe6a7a39 100644
--- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerState.cs
+++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/VBLexerMemento.cs
@@ -10,7 +10,7 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.Parser.VB
{
- public sealed class VBLexerState : AbstractLexerState
+ public sealed class VBLexerMemento : LexerMemento
{
public bool LineEnd { get; set; }
public bool IsAtLineBegin { get; set; }
diff --git a/src/Libraries/NRefactory/Project/Src/ParserFactory.cs b/src/Libraries/NRefactory/Project/Src/ParserFactory.cs
index 7673a18fe6..1fa446c404 100644
--- a/src/Libraries/NRefactory/Project/Src/ParserFactory.cs
+++ b/src/Libraries/NRefactory/Project/Src/ParserFactory.cs
@@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory
throw new System.NotSupportedException(language + " not supported.");
}
- public static Parser.ILexer CreateLexer(SupportedLanguage language, TextReader textReader, AbstractLexerState state)
+ public static Parser.ILexer CreateLexer(SupportedLanguage language, TextReader textReader, LexerMemento state)
{
switch (language) {
case SupportedLanguage.CSharp:
diff --git a/src/Libraries/NRefactory/Test/Lexer/VBNet/ImplicitLineContinuationTests.cs b/src/Libraries/NRefactory/Test/Lexer/VBNet/ImplicitLineContinuationTests.cs
index 34381eed63..e244e897b2 100644
--- a/src/Libraries/NRefactory/Test/Lexer/VBNet/ImplicitLineContinuationTests.cs
+++ b/src/Libraries/NRefactory/Test/Lexer/VBNet/ImplicitLineContinuationTests.cs
@@ -93,6 +93,52 @@ End Module";
Tokens.End, Tokens.Module);
}
+ [Test]
+ public void Query()
+ {
+ string code = @"Module Test
+ Sub A
+ Dim q = From x In a
+ Select x
+ End Sub
+End Module";
+
+ ILexer lexer = GenerateLexer(new StringReader(code));
+
+ CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
+ Tokens.Sub, Tokens.Identifier, Tokens.EOL,
+ Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier,
+ Tokens.Select, Tokens.Identifier, Tokens.EOL,
+ Tokens.End, Tokens.Sub, Tokens.EOL,
+ Tokens.End, Tokens.Module);
+ }
+
+ [Test]
+ public void Query1()
+ {
+ string code = @"Module Test
+ Sub A
+ Dim actions = From a in b Select Sub()
+ Dim i = 1
+ Select Case i
+ End Select
+ End Sub
+ End Sub
+End Module";
+
+ ILexer lexer = GenerateLexer(new StringReader(code));
+
+ CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
+ Tokens.Sub, Tokens.Identifier, Tokens.EOL,
+ Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Select, Tokens.Sub, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL,
+ Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.LiteralInteger, Tokens.EOL,
+ Tokens.Select, Tokens.Case, Tokens.Identifier, Tokens.EOL,
+ Tokens.End, Tokens.Select, Tokens.EOL,
+ Tokens.End, Tokens.Sub, Tokens.EOL,
+ Tokens.End, Tokens.Sub, Tokens.EOL,
+ Tokens.End, Tokens.Module);
+ }
+
#region Helpers
ILexer GenerateLexer(StringReader sr)
{
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
index 5cd3241aab..ad17b92828 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
@@ -1122,15 +1122,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
}
- static void AddVBNetKeywords(List ar, BitArray keywords)
- {
- for (int i = 0; i < keywords.Length; i++) {
- if (keywords[i]) {
- ar.Add(new KeywordEntry(NR.Parser.VB.Tokens.GetTokenString(i)));
- }
- }
- }
-
///
/// Returns code completion entries for given context.
///
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetExpressionFinder.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetExpressionFinder.cs
index 7c3bf873d1..0773f442e9 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetExpressionFinder.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/VBNet/VBNetExpressionFinder.cs
@@ -6,6 +6,7 @@
//
using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -81,14 +82,14 @@ namespace ICSharpCode.SharpDevelop.Dom.VBNet
if (lastExpressionStartOffset < 0)
return new ExpressionResult(null, context);
- return MakeResult(text, lastExpressionStartOffset, offset, context);
+ return MakeResult(text, lastExpressionStartOffset, offset, context, p.GetExpectedSet());
}
- ExpressionResult MakeResult(string text, int startOffset, int endOffset, ExpressionContext context)
+ ExpressionResult MakeResult(string text, int startOffset, int endOffset, ExpressionContext context, BitArray expectedKeywords)
{
return new ExpressionResult(text.Substring(startOffset, endOffset - startOffset).Trim(),
DomRegion.FromLocation(OffsetToLocation(startOffset), OffsetToLocation(endOffset)),
- context, null);
+ context, expectedKeywords);
}
void Init(string text, int offset)
@@ -160,10 +161,10 @@ namespace ICSharpCode.SharpDevelop.Dom.VBNet
if (lastExpressionStartOffset >= 0) {
if (offset < tokenOffset) {
// offset is in front of this token
- return MakeResult(text, lastExpressionStartOffset, tokenOffset, GetContext(block));
+ return MakeResult(text, lastExpressionStartOffset, tokenOffset, GetContext(block), p.GetExpectedSet());
} else {
// offset is IN this token
- return MakeResult(text, lastExpressionStartOffset, offset, GetContext(block));
+ return MakeResult(text, lastExpressionStartOffset, offset, GetContext(block), p.GetExpectedSet());
}
} else {
return new ExpressionResult(null, GetContext(block));