diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs
index af0c77fe7a..7fcafe51d9 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs
@@ -13,64 +13,17 @@ using Boo.Lang.Compiler.Ast;
namespace Grunwald.BooBinding.CodeCompletion
{
- ///
- /// Finds an variable declaration in the boo AST.
- ///
- public class VariableLookupVisitor : DepthFirstVisitor
+ public abstract class VariableLookupVisitorBase : DepthFirstVisitor
{
- BooResolver resolver;
- string lookFor;
- bool acceptImplicit;
-
- public VariableLookupVisitor(BooResolver resolver, string lookFor, bool acceptImplicit)
- {
- this.resolver = resolver;
- this.lookFor = lookFor;
- this.acceptImplicit = acceptImplicit;
- }
-
- IField result;
-
- public IField Result {
- get {
- return result;
- }
- }
-
- private void InferResult(Expression expr, string name, LexicalInfo lexicalInfo, bool useElementType)
- {
- if (expr == null)
- return;
- if (result != null)
- return;
- IReturnType returnType = new InferredReturnType(expr, resolver.CallingClass);
- if (useElementType)
- returnType = new ElementReturnType(returnType);
- result = new DefaultField.LocalVariableField(returnType, name,
- new DomRegion(lexicalInfo.Line, lexicalInfo.Column),
- resolver.CallingClass);
- }
+ protected BooResolver resolver;
+ protected bool acceptImplicit = true;
- public override void OnDeclaration(Declaration node)
- {
- if (result != null)
- return;
- if (node.Name == lookFor) {
- if (node.Type != null) {
- result = new DefaultField.LocalVariableField(resolver.ConvertType(node.Type),
- node.Name,
- new DomRegion(node.LexicalInfo.Line, node.LexicalInfo.Column),
- resolver.CallingClass);
- }
- }
- }
+ protected abstract void DeclarationFound(string declarationName, TypeReference declarationType, Expression initializer, LexicalInfo lexicalInfo);
+ protected abstract void IterationDeclarationFound(string declarationName, TypeReference declarationType, Expression initializer, LexicalInfo lexicalInfo);
public override void OnDeclarationStatement(DeclarationStatement node)
{
- if (node.Declaration.Name == lookFor) {
- Visit(node.Declaration);
- InferResult(node.Initializer, node.Declaration.Name, node.LexicalInfo, false);
- }
+ DeclarationFound(node.Declaration.Name, node.Declaration.Type, node.Initializer, node.LexicalInfo);
}
protected override void OnError(Node node, Exception error)
@@ -84,9 +37,7 @@ namespace Grunwald.BooBinding.CodeCompletion
ReferenceExpression reference = node.Left as ReferenceExpression;
if (node.Operator == BinaryOperatorType.Assign && reference != null) {
if (!(reference is MemberReferenceExpression)) {
- if (reference.Name == lookFor) {
- InferResult(node.Right, reference.Name, reference.LexicalInfo, false);
- }
+ DeclarationFound(reference.Name, null, node.Right, node.LexicalInfo);
}
}
}
@@ -95,18 +46,12 @@ namespace Grunwald.BooBinding.CodeCompletion
public override void OnForStatement(ForStatement node)
{
- if (node.LexicalInfo.Line > resolver.CaretLine || node.Block.EndSourceLocation.Line < resolver.CaretLine)
- return;
-
- if (node.Declarations.Count != 1) {
- // TODO: support unpacking
- base.OnForStatement(node);
- return;
- }
- if (node.Declarations[0].Name == lookFor) {
- Visit(node.Declarations[0]);
- InferResult(node.Iterator, node.Declarations[0].Name, node.LexicalInfo, true);
+ if (node.LexicalInfo.Line <= resolver.CaretLine && node.Block.EndSourceLocation.Line >= resolver.CaretLine - 1) {
+ foreach (Declaration decl in node.Declarations) {
+ IterationDeclarationFound(decl.Name, decl.Type, node.Iterator, node.LexicalInfo);
+ }
}
+ base.OnForStatement(node);
}
public override void OnGeneratorExpression(GeneratorExpression node)
@@ -114,16 +59,77 @@ namespace Grunwald.BooBinding.CodeCompletion
if (node.LexicalInfo.Line != resolver.CaretLine)
return;
LoggingService.Warn("GeneratorExpression: " + node.EndSourceLocation.Line);
- if (node.Declarations.Count != 1) {
- // TODO: support unpacking
- base.OnGeneratorExpression(node);
+ foreach (Declaration decl in node.Declarations) {
+ IterationDeclarationFound(decl.Name, decl.Type, node.Iterator, node.LexicalInfo);
+ }
+ base.OnGeneratorExpression(node);
+ }
+ }
+
+ ///
+ /// Finds an variable declaration in the boo AST.
+ ///
+ public class VariableLookupVisitor : VariableLookupVisitorBase
+ {
+ string lookFor;
+
+ public VariableLookupVisitor(BooResolver resolver, string lookFor, bool acceptImplicit)
+ {
+ this.resolver = resolver;
+ this.lookFor = lookFor;
+ this.acceptImplicit = acceptImplicit;
+ }
+
+ IField result;
+
+ public IField Result {
+ get {
+ return result;
+ }
+ }
+
+ protected override void IterationDeclarationFound(string declarationName, TypeReference declarationType, Expression iterator, LexicalInfo lexicalInfo)
+ {
+ if (result != null)
return;
+ if (declarationName == lookFor) {
+ if (declarationType != null) {
+ result = new DefaultField.LocalVariableField(resolver.ConvertType(declarationType),
+ declarationName,
+ new DomRegion(lexicalInfo.Line, lexicalInfo.Column),
+ resolver.CallingClass);
+ } else if (iterator != null) {
+ InferResult(iterator, declarationName, lexicalInfo, true);
+ }
}
- if (node.Declarations[0].Name == lookFor) {
- Visit(node.Declarations[0]);
- InferResult(node.Iterator, node.Declarations[0].Name, node.LexicalInfo, true);
+ }
+
+ protected override void DeclarationFound(string declarationName, TypeReference declarationType, Expression initializer, LexicalInfo lexicalInfo)
+ {
+ if (result != null)
+ return;
+ if (declarationName == lookFor) {
+ if (declarationType != null) {
+ result = new DefaultField.LocalVariableField(resolver.ConvertType(declarationType),
+ declarationName,
+ new DomRegion(lexicalInfo.Line, lexicalInfo.Column),
+ resolver.CallingClass);
+ } else if (initializer != null) {
+ InferResult(initializer, declarationName, lexicalInfo, false);
+ }
}
- base.OnGeneratorExpression(node);
+ }
+
+ private void InferResult(Expression expr, string name, LexicalInfo lexicalInfo, bool useElementType)
+ {
+ if (expr == null)
+ return;
+ IReturnType returnType = new InferredReturnType(expr, resolver.CallingClass);
+ if (useElementType)
+ returnType = new ElementReturnType(returnType);
+ result = new DefaultField.LocalVariableField(returnType, name,
+ new DomRegion(lexicalInfo.Line, lexicalInfo.Column),
+ resolver.CallingClass);
}
}
@@ -131,10 +137,9 @@ namespace Grunwald.BooBinding.CodeCompletion
/// Creates a hashtable name => (Expression or TypeReference) for the local
/// variables in the block that is visited.
///
- public class VariableListLookupVisitor : DepthFirstVisitor
+ public class VariableListLookupVisitor : VariableLookupVisitorBase
{
List knownVariableNames;
- BooResolver resolver;
public VariableListLookupVisitor(List knownVariableNames, BooResolver resolver)
{
@@ -171,48 +176,22 @@ namespace Grunwald.BooBinding.CodeCompletion
results.Add(name, resolver.ConvertType(reference));
}
- public override void OnDeclaration(Declaration node)
+ protected override void DeclarationFound(string declarationName, TypeReference declarationType, Expression initializer, LexicalInfo lexicalInfo)
{
- Add(node.Name, node.Type);
- }
-
- public override void OnDeclarationStatement(DeclarationStatement node)
- {
- Visit(node.Declaration);
- Add(node.Declaration.Name, node.Initializer, false);
- }
-
- protected override void OnError(Node node, Exception error)
- {
- MessageService.ShowError(error, "VariableListLookupVisitor: error processing " + node);
- }
-
- public override void OnBinaryExpression(BinaryExpression node)
- {
- if (node.Operator == BinaryOperatorType.Assign && node.Left is ReferenceExpression) {
- ReferenceExpression reference = node.Left as ReferenceExpression;
- if (node.Operator == BinaryOperatorType.Assign && reference != null) {
- if (!(reference is MemberReferenceExpression)) {
- if (!knownVariableNames.Contains(reference.Name)) {
- Add(reference.Name, node.Right, false);
- }
- }
- }
+ if (declarationType != null) {
+ Add(declarationName, declarationType);
+ } else if (initializer != null) {
+ Add(declarationName, initializer, false);
}
- base.OnBinaryExpression(node);
}
- public override void OnForStatement(ForStatement node)
+ protected override void IterationDeclarationFound(string declarationName, TypeReference declarationType, Expression initializer, LexicalInfo lexicalInfo)
{
- if (node.LexicalInfo.Line > resolver.CaretLine || node.Block.EndSourceLocation.Line < resolver.CaretLine)
- return;
-
- if (node.Declarations.Count != 1) {
- // TODO: support unpacking
- base.OnForStatement(node);
- return;
+ if (declarationType != null) {
+ Add(declarationName, declarationType);
+ } else if (initializer != null) {
+ Add(declarationName, initializer, true);
}
- Add(node.Declarations[0].Name, node.Iterator, true);
}
}
}