|
|
|
@ -13,64 +13,17 @@ using Boo.Lang.Compiler.Ast;
@@ -13,64 +13,17 @@ using Boo.Lang.Compiler.Ast;
|
|
|
|
|
|
|
|
|
|
namespace Grunwald.BooBinding.CodeCompletion |
|
|
|
|
{ |
|
|
|
|
/// <summary>
|
|
|
|
|
/// Finds an variable declaration in the boo AST.
|
|
|
|
|
/// </summary>
|
|
|
|
|
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
@@ -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
@@ -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
@@ -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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Finds an variable declaration in the boo AST.
|
|
|
|
|
/// </summary>
|
|
|
|
|
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
@@ -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.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class VariableListLookupVisitor : DepthFirstVisitor |
|
|
|
|
public class VariableListLookupVisitor : VariableLookupVisitorBase |
|
|
|
|
{ |
|
|
|
|
List<string> knownVariableNames; |
|
|
|
|
BooResolver resolver; |
|
|
|
|
|
|
|
|
|
public VariableListLookupVisitor(List<string> knownVariableNames, BooResolver resolver) |
|
|
|
|
{ |
|
|
|
@ -171,48 +176,22 @@ namespace Grunwald.BooBinding.CodeCompletion
@@ -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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|