Browse Source

Fixed type inference for methods with expression tree parameters.

Use the return type of .Select() or .GroupBy() as type of query expressions.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3661 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
ce64b86579
  1. 8
      src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs
  2. 2
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs
  3. 62
      src/Main/Base/Test/NRefactoryResolverTests.cs
  4. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/LambdaReturnType.cs
  5. 42
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs

8
src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands
public override void GenerateCode(List<AbstractNode> nodes, IList items) public override void GenerateCode(List<AbstractNode> nodes, IList items)
{ {
TypeReference intReference = new TypeReference("System.Int32"); TypeReference intReference = new TypeReference("System.Int32", true);
MethodDeclaration method = new MethodDeclaration { MethodDeclaration method = new MethodDeclaration {
Name = "GetHashCode", Name = "GetHashCode",
Modifier = Modifiers.Public | Modifiers.Override, Modifier = Modifiers.Public | Modifiers.Override,
@ -90,8 +90,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands
method.Body.AddChild(new ReturnStatement(new IdentifierExpression(var.Name))); method.Body.AddChild(new ReturnStatement(new IdentifierExpression(var.Name)));
nodes.Add(method); nodes.Add(method);
TypeReference boolReference = new TypeReference("System.Boolean"); TypeReference boolReference = new TypeReference("System.Boolean", true);
TypeReference objectReference = new TypeReference("System.Object"); TypeReference objectReference = new TypeReference("System.Object", true);
method = new MethodDeclaration { method = new MethodDeclaration {
Name = "Equals", Name = "Equals",
@ -186,7 +186,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands
new MemberReferenceExpression(new IdentifierExpression(other), field.Name)); new MemberReferenceExpression(new IdentifierExpression(other), field.Name));
} else { } else {
InvocationExpression ie = new InvocationExpression( InvocationExpression ie = new InvocationExpression(
new MemberReferenceExpression(new TypeReferenceExpression("System.Object"), "Equals") new MemberReferenceExpression(new TypeReferenceExpression(new TypeReference("System.Object", true)), "Equals")
); );
ie.Arguments.Add(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name)); ie.Arguments.Add(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name));
ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), field.Name)); ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), field.Name));

2
src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs

@ -451,7 +451,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
void ComboBoxSelectedIndexChanged(object sender, System.EventArgs e) void ComboBoxSelectedIndexChanged(object sender, System.EventArgs e)
{ {
ComboBox comboBox = (ComboBox)sender; ComboBox comboBox = (ComboBox)sender;
if (autoselect) { if (autoselect && comboBox.SelectedIndex >= 0) {
ComboBoxItem item = (ComboBoxItem)comboBox.Items[comboBox.SelectedIndex]; ComboBoxItem item = (ComboBoxItem)comboBox.Items[comboBox.SelectedIndex];
if (item.IsInCurrentPart) { if (item.IsInCurrentPart) {
textAreaControl.ActiveTextAreaControl.CenterViewOn( textAreaControl.ActiveTextAreaControl.CenterViewOn(

62
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -31,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.Tests
p.Parse(); p.Parse();
DefaultProjectContent pc = new DefaultProjectContent(); DefaultProjectContent pc = new DefaultProjectContent();
pc.ReferencedContents.Add(projectContentRegistry.Mscorlib); pc.ReferencedContents.Add(projectContentRegistry.Mscorlib);
pc.ReferencedContents.Add(projectContentRegistry.GetProjectContentForReference("System.Core", "System.Core"));
pc.ReferencedContents.Add(projectContentRegistry.GetProjectContentForReference("System.Windows.Forms", "System.Windows.Forms")); pc.ReferencedContents.Add(projectContentRegistry.GetProjectContentForReference("System.Windows.Forms", "System.Windows.Forms"));
HostCallback.GetCurrentProjectContent = delegate { HostCallback.GetCurrentProjectContent = delegate {
return pc; return pc;
@ -1760,7 +1761,7 @@ public static class XC {
[Test] [Test]
public void SimpleLinqTest() public void SimpleLinqTest()
{ {
string program = @"using System; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
void Test(string[] input) { void Test(string[] input) {
var r = from e in input var r = from e in input
@ -1780,6 +1781,46 @@ class TestClass {
Assert.AreEqual("System.String", lrr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName); Assert.AreEqual("System.String", lrr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName);
} }
[Test]
public void LinqGroupTest()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
var r = from e in input
group e.ToUpper() by e.Length;
}
}
";
LocalResolveResult lrr = Resolve<LocalResolveResult>(program, "r", 7);
Assert.AreEqual("System.Collections.Generic.IEnumerable", lrr.ResolvedType.FullyQualifiedName);
ConstructedReturnType rt = lrr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].CastToConstructedReturnType();
Assert.AreEqual("System.Linq.IGrouping", rt.FullyQualifiedName);
Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullyQualifiedName);
Assert.AreEqual("System.String", rt.TypeArguments[1].FullyQualifiedName);
}
[Test]
public void LinqQueryableGroupTest()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(IQueryable<string> input) {
var r = from e in input
group e.ToUpper() by e.Length;
}
}
";
LocalResolveResult lrr = Resolve<LocalResolveResult>(program, "r", 7);
Assert.AreEqual("System.Linq.IQueryable", lrr.ResolvedType.FullyQualifiedName);
ConstructedReturnType rt = lrr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].CastToConstructedReturnType();
Assert.AreEqual("System.Linq.IGrouping", rt.FullyQualifiedName);
Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullyQualifiedName);
Assert.AreEqual("System.String", rt.TypeArguments[1].FullyQualifiedName);
}
[Test] [Test]
public void ParenthesizedLinqTest() public void ParenthesizedLinqTest()
{ {
@ -1798,6 +1839,23 @@ class TestClass {
Assert.AreEqual("System.Int32", rr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName); Assert.AreEqual("System.Int32", rr.ResolvedType.CastToConstructedReturnType().TypeArguments[0].FullyQualifiedName);
} }
[Test]
public void LinqSelectReturnTypeTest()
{
string program = @"using System;
class TestClass { static void M() {
(from a in new XYZ() select a.ToUpper())
}}
class XYZ {
public int Select<U>(Func<string, U> f) { return 42; }
}";
ResolveResult rr = Resolve(program,
"(from a in new XYZ() select a.ToUpper())",
3, 2, ExpressionContext.Default);
Assert.IsNotNull(rr);
Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName);
}
const string objectInitializerTestProgram = @"using System; using System.Threading; const string objectInitializerTestProgram = @"using System; using System.Threading;
class TestClass { class TestClass {
static void Test() { static void Test() {
@ -1890,7 +1948,7 @@ public class MyCollectionType : System.Collections.IEnumerable
[Test] [Test]
public void LinqQueryContinuationTest() public void LinqQueryContinuationTest()
{ {
string program = @"using System; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
void Test(string[] input) { void Test(string[] input) {
var r = from x in input var r = from x in input

4
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/LambdaReturnType.cs

@ -19,6 +19,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
LambdaExpression lambdaExpression; LambdaExpression lambdaExpression;
List<Expression> returnExpressions = new List<Expression>(); List<Expression> returnExpressions = new List<Expression>();
public override bool CanBeConvertedToExpressionTree {
get { return lambdaExpression != null; }
}
internal LambdaReturnType(LambdaExpression expression, NRefactoryResolver resolver) internal LambdaReturnType(LambdaExpression expression, NRefactoryResolver resolver)
: base(resolver.CompilationUnit) : base(resolver.CompilationUnit)
{ {

42
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs

@ -549,22 +549,40 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
public override object VisitQueryExpression(QueryExpression queryExpression, object data) public override object VisitQueryExpression(QueryExpression queryExpression, object data)
{ {
IReturnType type = null;
QueryExpressionSelectClause selectClause = queryExpression.SelectOrGroupClause as QueryExpressionSelectClause; QueryExpressionSelectClause selectClause = queryExpression.SelectOrGroupClause as QueryExpressionSelectClause;
QueryExpressionGroupClause groupClause = queryExpression.SelectOrGroupClause as QueryExpressionGroupClause; QueryExpressionGroupClause groupClause = queryExpression.SelectOrGroupClause as QueryExpressionGroupClause;
if (selectClause != null) { if (selectClause != null) {
type = ResolveType(selectClause.Projection); // Fake a call to 'Select'
var fakeInvocation = new InvocationExpression(new MemberReferenceExpression(
queryExpression.FromClause.InExpression, "Select"));
var selector = new LambdaExpression();
selector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
selector.ExpressionBody = selectClause.Projection;
selector.Parent = fakeInvocation;
fakeInvocation.Arguments.Add(selector);
return CreateResolveResult(ResolveType(fakeInvocation));
} else if (groupClause != null) { } else if (groupClause != null) {
type = new ConstructedReturnType( // Fake a call to 'GroupBy'
new GetClassReturnType(resolver.ProjectContent, "System.Linq.IGrouping", 2), var fakeInvocation = new InvocationExpression(new MemberReferenceExpression(
new IReturnType[] { ResolveType(groupClause.GroupBy), ResolveType(groupClause.Projection) } queryExpression.FromClause.InExpression, "GroupBy"));
);
} var keySelector = new LambdaExpression();
if (type != null) { keySelector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
return CreateResolveResult(new ConstructedReturnType( keySelector.ExpressionBody = groupClause.GroupBy;
new GetClassReturnType(resolver.ProjectContent, "System.Collections.Generic.IEnumerable", 1), keySelector.Parent = fakeInvocation;
new IReturnType[] { type }
)); var elementSelector = new LambdaExpression();
elementSelector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
elementSelector.ExpressionBody = groupClause.Projection;
elementSelector.Parent = fakeInvocation;
fakeInvocation.Arguments.Add(keySelector);
fakeInvocation.Arguments.Add(elementSelector);
return CreateResolveResult(ResolveType(fakeInvocation));
} else { } else {
return null; return null;
} }

Loading…
Cancel
Save