diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
index 72b95dc7ff..a4a8efca62 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
@@ -234,10 +234,14 @@ namespace Grunwald.BooBinding.CodeCompletion
// TODO: Type inference
IReturnType CreateReturnType(AST.Method node, IMethod method)
{
+ if (node.ReturnType == null)
+ return new InferredReturnType(node.Body);
return CreateReturnType(node.ReturnType, method);
}
IReturnType CreateReturnType(AST.Property property)
{
+ if (property.Type == null && property.Getter != null && property.Getter.Body != null)
+ return new InferredReturnType(property.Getter.Body);
return CreateReturnType(property.Type);
}
diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs
index 6907ba8853..234e0b7d9c 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs
@@ -18,29 +18,76 @@ namespace Grunwald.BooBinding.CodeCompletion
public class InferredReturnType : ProxyReturnType
{
Expression expression;
+ Block block;
+ IReturnType cachedType;
public InferredReturnType(Expression expression)
{
+ if (expression == null) throw new ArgumentNullException("expression");
this.expression = expression;
}
- bool needInfer = true;
- IReturnType cachedType;
+ public InferredReturnType(Block block)
+ {
+ if (block == null) throw new ArgumentNullException("block");
+ this.block = block;
+ }
+
+ public override bool IsDefaultReturnType {
+ get {
+ IReturnType baseType = BaseType;
+ return (baseType != null) ? baseType.IsDefaultReturnType : false;
+ }
+ }
public override IReturnType BaseType {
get {
- if (needInfer) {
- needInfer = false;
+ // clear up references to method/expression after the type has been resolved
+ if (block != null) {
+ GetReturnTypeVisitor v = new GetReturnTypeVisitor();
+ v.Visit(block);
+ block = null;
+ if (v.noReturnStatement)
+ cachedType = ReflectionReturnType.Void;
+ else if (v.result is NullReturnType)
+ cachedType = ReflectionReturnType.Object;
+ else
+ cachedType = v.result;
+ } else if (expression != null) {
cachedType = new BooResolver().GetTypeOfExpression(expression);
+ expression = null;
}
return cachedType;
}
}
- public override bool IsDefaultReturnType {
- get {
- IReturnType baseType = BaseType;
- return (baseType != null) ? baseType.IsDefaultReturnType : false;
+ class GetReturnTypeVisitor : DepthFirstVisitor
+ {
+ public IReturnType result;
+ public bool noReturnStatement = true;
+
+ public override void OnReturnStatement(ReturnStatement node)
+ {
+ noReturnStatement = false;
+ if (node.Expression == null) {
+ result = ReflectionReturnType.Void;
+ } else {
+ result = new BooResolver().GetTypeOfExpression(node.Expression);
+ }
+ }
+
+ public override void OnYieldStatement(YieldStatement node)
+ {
+ noReturnStatement = false;
+ result = ReflectionReturnType.CreatePrimitive(typeof(System.Collections.IEnumerable));
+ }
+
+ public override bool Visit(Node node)
+ {
+ if (result != null && !(result is NullReturnType))
+ return false;
+ else
+ return base.Visit(node);
}
}
}
diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
index eaccdfd0d5..88072f58eb 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
@@ -369,6 +369,46 @@ namespace Grunwald.BooBinding.CodeCompletion
}
#endregion
+ public override void OnBinaryExpression(BinaryExpression node)
+ {
+ switch (node.Operator) {
+ case BinaryOperatorType.GreaterThan:
+ case BinaryOperatorType.GreaterThanOrEqual:
+ case BinaryOperatorType.Inequality:
+ case BinaryOperatorType.LessThan:
+ case BinaryOperatorType.LessThanOrEqual:
+ case BinaryOperatorType.Match:
+ case BinaryOperatorType.Member:
+ case BinaryOperatorType.NotMatch:
+ case BinaryOperatorType.NotMember:
+ case BinaryOperatorType.Or:
+ case BinaryOperatorType.And:
+ case BinaryOperatorType.ReferenceEquality:
+ case BinaryOperatorType.ReferenceInequality:
+ case BinaryOperatorType.TypeTest:
+ MakeResult(ReflectionReturnType.Bool);
+ break;
+ default:
+ if (node.Left == null) {
+ if (node.Right == null) {
+ resolveResult = null;
+ } else {
+ node.Right.Accept(this);
+ }
+ return;
+ } else if (node.Right == null) {
+ node.Left.Accept(this);
+ return;
+ }
+ node.Left.Accept(this);
+ IReturnType left = (resolveResult != null) ? resolveResult.ResolvedType : null;
+ node.Right.Accept(this);
+ IReturnType right = (resolveResult != null) ? resolveResult.ResolvedType : null;
+ MakeResult(MemberLookupHelper.GetCommonType(left, right));
+ break;
+ }
+ }
+
protected override void OnError(Node node, Exception error)
{
MessageService.ShowError(error, "ResolveVisitor: error processing " + node);
diff --git a/src/Main/Base/Project/Src/Dom/Implementations/NullReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/NullReturnType.cs
index 35903dbd77..6b414cb813 100644
--- a/src/Main/Base/Project/Src/Dom/Implementations/NullReturnType.cs
+++ b/src/Main/Base/Project/Src/Dom/Implementations/NullReturnType.cs
@@ -11,8 +11,8 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Dom
{
- /// The type of the 'null'/'nothing' literal.
[Serializable]
+ /// The type of the 'null'/'nothing' literal.
public sealed class NullReturnType : AbstractReturnType
{
public static readonly NullReturnType Instance = new NullReturnType();
diff --git a/src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs b/src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs
index 228646f5b1..24c8c039f2 100644
--- a/src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs
+++ b/src/Main/Base/Project/Src/Dom/MemberLookupHelper.cs
@@ -671,5 +671,19 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
#endregion
+
+ ///
+ /// Gets the common base type of a and b.
+ ///
+ public static IReturnType GetCommonType(IReturnType a, IReturnType b)
+ {
+ if (a == null) return b;
+ if (b == null) return a;
+ if (ConversionExists(a, b))
+ return b;
+ if (ConversionExists(b, a))
+ return a;
+ return ReflectionReturnType.Object;
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs
index 2eea46f108..bae24230c1 100644
--- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs
+++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs
@@ -60,7 +60,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
case BinaryOperatorType.GreaterThanOrEqual:
return ReflectionReturnType.Bool;
default:
- return binaryOperatorExpression.Left.AcceptVisitor(this, data);
+ return MemberLookupHelper.GetCommonType(binaryOperatorExpression.Left.AcceptVisitor(this, data) as IReturnType,
+ binaryOperatorExpression.Right.AcceptVisitor(this, data) as IReturnType);
}
}