Browse Source

Merge pull request #145 from erik-kallen/conversions-in-lambda-body

Add a ConversionResolveResult to lambda body expressions, if required
pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
7424b69b48
  1. 28
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  2. 50
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

28
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -2000,6 +2000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2000,6 +2000,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver storedContext;
ResolveVisitor visitor;
AstNode body;
ResolveResult bodyRR;
IType inferredReturnType;
IList<Expression> returnExpressions;
@ -2024,12 +2025,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2024,12 +2025,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult Body {
get {
if (bodyRR != null)
return bodyRR;
if (body is Expression) {
Analyze();
if (returnValues.Count == 1)
return returnValues[0];
if (returnValues.Count == 1) {
bodyRR = returnValues[0];
if (!actualReturnType.IsKnownType(KnownTypeCode.Void)) {
var conv = storedContext.conversions.ImplicitConversion(bodyRR, actualReturnType);
if (!conv.IsIdentityConversion)
bodyRR = new ConversionResolveResult(actualReturnType, bodyRR, conv, storedContext.CheckForOverflow);
}
return bodyRR;
}
}
return visitor.voidResult;
return bodyRR = visitor.voidResult;
}
}
@ -2282,7 +2293,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2282,7 +2293,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return h;
}
ResolveVisitor visitor = new ResolveVisitor(storedContext, unresolvedFile);
var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null);
var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null, storedContext);
hypotheses.Add(newHypothesis);
return newHypothesis;
}
@ -2360,6 +2371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2360,6 +2371,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly IParameter[] lambdaParameters;
internal readonly IType[] parameterTypes;
readonly ResolveVisitor visitor;
readonly CSharpResolver storedContext;
internal readonly IType inferredReturnType;
IList<Expression> returnExpressions;
@ -2369,13 +2381,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2369,13 +2381,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal bool success;
public LambdaTypeHypothesis(ImplicitlyTypedLambda lambda, IType[] parameterTypes, ResolveVisitor visitor,
ICollection<ParameterDeclaration> parameterDeclarations)
ICollection<ParameterDeclaration> parameterDeclarations, CSharpResolver storedContext)
{
Debug.Assert(parameterTypes.Length == lambda.Parameters.Count);
this.lambda = lambda;
this.parameterTypes = parameterTypes;
this.visitor = visitor;
this.storedContext = storedContext;
visitor.SetNavigator(this);
Log.WriteLine("Analyzing " + ToString() + "...");
@ -2454,6 +2467,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2454,6 +2467,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
lambda.parameters = lambdaParameters; // replace untyped parameters with typed parameters
if (lambda.BodyExpression is Expression && returnValues.Count == 1) {
lambda.bodyResult = returnValues[0];
if (!returnType.IsKnownType(KnownTypeCode.Void)) {
var conv = storedContext.conversions.ImplicitConversion(lambda.bodyResult, returnType);
if (!conv.IsIdentityConversion)
lambda.bodyResult = new ConversionResolveResult(returnType, lambda.bodyResult, conv, storedContext.CheckForOverflow);
}
}
Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression);

50
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

@ -668,5 +668,55 @@ class C @@ -668,5 +668,55 @@ class C
Assert.IsFalse(mrr.IsError);
Assert.AreEqual("System.Threading.Tasks.Task", mrr.Type.ReflectionName);
}
[Test]
public void ConversionInExplicitlyTypedLambdaBody() {
string program = @"using System;
class Test {
public object M() {
System.Func<int, string> f = $(int i) => null$;
}
}";
var rr = Resolve<LambdaResolveResult>(program);
Assert.IsInstanceOf<ConversionResolveResult>(rr.Body);
Assert.That(((ConversionResolveResult)rr.Body).Conversion.IsNullLiteralConversion);
}
[Test]
public void ConversionInImplicitlyTypedLambdaBody() {
string program = @"using System;
class Test {
public object M() {
System.Func<int, string> f = $i => null$;
}
}";
var rr = Resolve<LambdaResolveResult>(program);
Assert.IsInstanceOf<ConversionResolveResult>(rr.Body);
Assert.That(((ConversionResolveResult)rr.Body).Conversion.IsNullLiteralConversion);
}
[Test]
public void NoConversionInVoidExplicitlyTypedLambdaBody() {
string program = @"using System;
class Test {
public object M() {
System.Action<int> f = $(int i) => i++$;
}
}";
var rr = Resolve<LambdaResolveResult>(program);
Assert.IsInstanceOf<OperatorResolveResult>(rr.Body);
}
[Test]
public void NoConversionInVoidImplicitlyTypedLambdaBody() {
string program = @"using System;
class Test {
public object M() {
System.Action<int> f = $i => i++$;
}
}";
var rr = Resolve<LambdaResolveResult>(program);
Assert.IsInstanceOf<OperatorResolveResult>(rr.Body);
}
}
}

Loading…
Cancel
Save