From f5913a8d1d01f93092e856be1f25c262eee386fc Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 31 Mar 2008 02:42:24 +0000 Subject: [PATCH] Worked on lambda expression support. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3010 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/ConvertVisitorLINQ.cs | 6 + .../Src/NRefactoryToPythonConverter.cs | 5 + .../NRefactoryASTGenerator/AST/Expressions.cs | 7 +- .../Ast/General/LocalVariableDeclaration.cs | 2 +- .../NRefactory/Project/Src/Ast/Generated.cs | 52 ++++-- .../NRefactory/Project/Src/IAstVisitor.cs | 2 + .../Project/Src/Parser/CSharp/Parser.cs | 174 +++++++++--------- .../Project/Src/Parser/CSharp/cs.ATG | 38 ++-- .../CSharp/CSharpOutputVisitor.cs | 17 +- .../PrettyPrinter/VBNet/VBNetOutputVisitor.cs | 17 +- .../Src/Visitors/AbstractASTVisitor.cs | 19 +- .../Src/Visitors/AbstractAstTransformer.cs | 39 ++-- .../Src/Visitors/NodeTrackingAstVisitor.cs | 11 ++ .../Expressions/QueryExpressionTests.cs | 39 +++- src/Main/Base/Test/NRefactoryResolverTests.cs | 110 ++++++++++- .../NRefactoryResolver/NRefactoryResolver.cs | 55 +++++- .../Src/NRefactoryResolver/ResolveVisitor.cs | 10 +- .../Project/Src/ResolveResult.cs | 55 +++++- 18 files changed, 466 insertions(+), 192 deletions(-) diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs index 65599df846..870f684f32 100644 --- a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs @@ -40,6 +40,12 @@ namespace NRefactoryToBooConverter return null; } + public object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) + { + AddError(queryExpressionOrderClause, "QueryExpressionOrderClause is not supported."); + return null; + } + public object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { AddError(queryExpressionOrdering, "QueryExpressionOrdering is not supported."); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs index 4f73a9badc..7586b2e0dd 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/NRefactoryToPythonConverter.cs @@ -1187,6 +1187,11 @@ namespace ICSharpCode.PythonBinding return null; } + public object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) + { + return null; + } + public object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { return null; diff --git a/src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs b/src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs index e957e8e662..069989d1c2 100644 --- a/src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs +++ b/src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs @@ -250,8 +250,7 @@ namespace NRefactoryASTGenerator.Ast [ImplementNullable(NullableImplementation.Shadow)] class QueryExpression : Expression { QueryExpressionFromClause fromClause; - List fromLetWhereClauses; - List orderings; + List middleClauses; QueryExpressionClause selectOrGroupClause; QueryExpressionIntoClause intoClause; } @@ -286,6 +285,10 @@ namespace NRefactoryASTGenerator.Ast string intoIdentifier; } + class QueryExpressionOrderClause : QueryExpressionClause { + List orderings; + } + class QueryExpressionOrdering : AbstractNode { Expression criteria; QueryExpressionOrderingDirection direction; diff --git a/src/Libraries/NRefactory/Project/Src/Ast/General/LocalVariableDeclaration.cs b/src/Libraries/NRefactory/Project/Src/Ast/General/LocalVariableDeclaration.cs index e01db430d6..935a8866c8 100644 --- a/src/Libraries/NRefactory/Project/Src/Ast/General/LocalVariableDeclaration.cs +++ b/src/Libraries/NRefactory/Project/Src/Ast/General/LocalVariableDeclaration.cs @@ -14,7 +14,7 @@ namespace ICSharpCode.NRefactory.Ast { TypeReference typeReference; Modifiers modifier = Modifiers.None; - List variables = new List(1); + List variables = new List(); public TypeReference TypeReference { get { diff --git a/src/Libraries/NRefactory/Project/Src/Ast/Generated.cs b/src/Libraries/NRefactory/Project/Src/Ast/Generated.cs index 75d3d43279..f9983cc127 100644 --- a/src/Libraries/NRefactory/Project/Src/Ast/Generated.cs +++ b/src/Libraries/NRefactory/Project/Src/Ast/Generated.cs @@ -3433,9 +3433,7 @@ namespace ICSharpCode.NRefactory.Ast { QueryExpressionFromClause fromClause; - List fromLetWhereClauses; - - List orderings; + List middleClauses; QueryExpressionClause selectOrGroupClause; @@ -3451,21 +3449,12 @@ namespace ICSharpCode.NRefactory.Ast { } } - public List FromLetWhereClauses { + public List MiddleClauses { get { - return fromLetWhereClauses; + return middleClauses; } set { - fromLetWhereClauses = value ?? new List(); - } - } - - public List Orderings { - get { - return orderings; - } - set { - orderings = value ?? new List(); + middleClauses = value ?? new List(); } } @@ -3491,8 +3480,7 @@ namespace ICSharpCode.NRefactory.Ast { public QueryExpression() { fromClause = QueryExpressionFromClause.Null; - fromLetWhereClauses = new List(); - orderings = new List(); + middleClauses = new List(); selectOrGroupClause = QueryExpressionClause.Null; intoClause = QueryExpressionIntoClause.Null; } @@ -3508,8 +3496,8 @@ namespace ICSharpCode.NRefactory.Ast { } public override string ToString() { - return string.Format("[QueryExpression FromClause={0} FromLetWhereClauses={1} Orderings={2} SelectOrGro" + - "upClause={3} IntoClause={4}]", FromClause, GetCollectionString(FromLetWhereClauses), GetCollectionString(Orderings), SelectOrGroupClause, IntoClause); + return string.Format("[QueryExpression FromClause={0} MiddleClauses={1} SelectOrGroupClause={2} IntoCla" + + "use={3}]", FromClause, GetCollectionString(MiddleClauses), SelectOrGroupClause, IntoClause); } } @@ -3838,6 +3826,32 @@ namespace ICSharpCode.NRefactory.Ast { } } + public class QueryExpressionOrderClause : QueryExpressionClause { + + List orderings; + + public List Orderings { + get { + return orderings; + } + set { + orderings = value ?? new List(); + } + } + + public QueryExpressionOrderClause() { + orderings = new List(); + } + + public override object AcceptVisitor(IAstVisitor visitor, object data) { + return visitor.VisitQueryExpressionOrderClause(this, data); + } + + public override string ToString() { + return string.Format("[QueryExpressionOrderClause Orderings={0}]", GetCollectionString(Orderings)); + } + } + public class QueryExpressionOrdering : AbstractNode { Expression criteria; diff --git a/src/Libraries/NRefactory/Project/Src/IAstVisitor.cs b/src/Libraries/NRefactory/Project/Src/IAstVisitor.cs index a6b0dff461..52c770c9ff 100644 --- a/src/Libraries/NRefactory/Project/Src/IAstVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/IAstVisitor.cs @@ -173,6 +173,8 @@ namespace ICSharpCode.NRefactory { object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data); + object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data); + object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data); object VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data); diff --git a/src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs b/src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs index c57957ec56..b97768bf63 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs @@ -1605,7 +1605,7 @@ out type); FieldDeclaration fd = new FieldDeclaration(attributes, type, m.Modifier | Modifiers.Const); fd.StartLocation = m.GetDeclarationLocation(startPos); VariableDeclaration f = new VariableDeclaration(t.val); - fd.Fields.Add(f); + SafeAdd(fd, fd.Fields, f); Expect(3); Expr( @@ -1620,7 +1620,7 @@ out expr); #line 748 "cs.ATG" f = new VariableDeclaration(t.val); - fd.Fields.Add(f); + SafeAdd(fd, fd.Fields, f); Expect(3); Expr( @@ -3241,7 +3241,7 @@ out type); out expr); #line 1453 "cs.ATG" - var.Variables.Add(new VariableDeclaration(ident, expr)); + SafeAdd(var, var.Variables, new VariableDeclaration(ident, expr)); while (la.kind == 14) { lexer.NextToken(); Identifier(); @@ -3254,7 +3254,7 @@ out expr); out expr); #line 1454 "cs.ATG" - var.Variables.Add(new VariableDeclaration(ident, expr)); + SafeAdd(var, var.Variables, new VariableDeclaration(ident, expr)); } Expect(11); @@ -3518,7 +3518,7 @@ out type); out var); #line 1425 "cs.ATG" - localVariableDeclaration.Variables.Add(var); + SafeAdd(localVariableDeclaration, localVariableDeclaration.Variables, var); while (la.kind == 14) { lexer.NextToken(); LocalVariableDeclarator( @@ -3526,7 +3526,7 @@ out var); out var); #line 1426 "cs.ATG" - localVariableDeclaration.Variables.Add(var); + SafeAdd(localVariableDeclaration, localVariableDeclaration.Variables, var); } #line 1427 "cs.ATG" @@ -4892,7 +4892,7 @@ out type); out expr); #line 1976 "cs.ATG" - if (expr != null) { parameters.Add(expr); } + SafeAdd(oce, parameters, expr); while (la.kind == 14) { lexer.NextToken(); Argument( @@ -4900,7 +4900,7 @@ out expr); out expr); #line 1977 "cs.ATG" - if (expr != null) { parameters.Add(expr); } + SafeAdd(oce, parameters, expr); } } Expect(21); @@ -5537,66 +5537,69 @@ QueryExpression q) { #line 2391 "cs.ATG" QueryExpressionFromClause fromClause; QueryExpressionWhereClause whereClause; QueryExpressionLetClause letClause; QueryExpressionJoinClause joinClause; + QueryExpressionOrderClause orderClause; QueryExpressionSelectClause selectClause; QueryExpressionGroupClause groupClause; QueryExpressionIntoClause intoClause; while (StartOf(39)) { if (la.kind == 137) { QueryExpressionFromClause( -#line 2397 "cs.ATG" +#line 2398 "cs.ATG" out fromClause); -#line 2397 "cs.ATG" - SafeAdd(q, q.FromLetWhereClauses, fromClause); +#line 2398 "cs.ATG" + SafeAdd(q, q.MiddleClauses, fromClause); } else if (la.kind == 127) { QueryExpressionWhereClause( -#line 2398 "cs.ATG" +#line 2399 "cs.ATG" out whereClause); -#line 2398 "cs.ATG" - SafeAdd(q, q.FromLetWhereClauses, whereClause); +#line 2399 "cs.ATG" + SafeAdd(q, q.MiddleClauses, whereClause); } else if (la.kind == 141) { QueryExpressionLetClause( -#line 2399 "cs.ATG" +#line 2400 "cs.ATG" out letClause); -#line 2399 "cs.ATG" - SafeAdd(q, q.FromLetWhereClauses, letClause); - } else { - QueryExpressionJoinClause( #line 2400 "cs.ATG" + SafeAdd(q, q.MiddleClauses, letClause); + } else if (la.kind == 142) { + QueryExpressionJoinClause( +#line 2401 "cs.ATG" out joinClause); -#line 2400 "cs.ATG" - SafeAdd(q, q.FromLetWhereClauses, joinClause); - } - } - if (la.kind == 140) { - QueryExpressionOrderByClause( +#line 2401 "cs.ATG" + SafeAdd(q, q.MiddleClauses, joinClause); + } else { + QueryExpressionOrderByClause( #line 2402 "cs.ATG" -q); +out orderClause); + +#line 2402 "cs.ATG" + SafeAdd(q, q.MiddleClauses, orderClause); + } } if (la.kind == 133) { QueryExpressionSelectClause( -#line 2403 "cs.ATG" +#line 2404 "cs.ATG" out selectClause); -#line 2403 "cs.ATG" +#line 2404 "cs.ATG" q.SelectOrGroupClause = selectClause; } else if (la.kind == 134) { QueryExpressionGroupClause( -#line 2404 "cs.ATG" +#line 2405 "cs.ATG" out groupClause); -#line 2404 "cs.ATG" +#line 2405 "cs.ATG" q.SelectOrGroupClause = groupClause; } else SynErr(218); if (la.kind == 136) { QueryExpressionIntoClause( -#line 2406 "cs.ATG" +#line 2407 "cs.ATG" out intoClause); -#line 2406 "cs.ATG" +#line 2407 "cs.ATG" q.IntoClause = intoClause; } } @@ -5672,168 +5675,171 @@ out expr); } void QueryExpressionWhereClause( -#line 2409 "cs.ATG" +#line 2410 "cs.ATG" out QueryExpressionWhereClause wc) { -#line 2410 "cs.ATG" +#line 2411 "cs.ATG" Expression expr; wc = new QueryExpressionWhereClause(); wc.StartLocation = la.Location; Expect(127); Expr( -#line 2413 "cs.ATG" +#line 2414 "cs.ATG" out expr); -#line 2413 "cs.ATG" +#line 2414 "cs.ATG" wc.Condition = expr; -#line 2414 "cs.ATG" +#line 2415 "cs.ATG" wc.EndLocation = t.EndLocation; } void QueryExpressionLetClause( -#line 2417 "cs.ATG" +#line 2418 "cs.ATG" out QueryExpressionLetClause wc) { -#line 2418 "cs.ATG" +#line 2419 "cs.ATG" Expression expr; wc = new QueryExpressionLetClause(); wc.StartLocation = la.Location; Expect(141); Identifier(); -#line 2421 "cs.ATG" +#line 2422 "cs.ATG" wc.Identifier = t.val; Expect(3); Expr( -#line 2423 "cs.ATG" +#line 2424 "cs.ATG" out expr); -#line 2423 "cs.ATG" +#line 2424 "cs.ATG" wc.Expression = expr; -#line 2424 "cs.ATG" +#line 2425 "cs.ATG" wc.EndLocation = t.EndLocation; } void QueryExpressionOrderByClause( -#line 2427 "cs.ATG" -QueryExpression q) { - #line 2428 "cs.ATG" - QueryExpressionOrdering ordering; +out QueryExpressionOrderClause oc) { + +#line 2429 "cs.ATG" + QueryExpressionOrdering ordering; oc = new QueryExpressionOrderClause(); oc.StartLocation = la.Location; Expect(140); - QueryExpressionOrderingClause( -#line 2431 "cs.ATG" + QueryExpressionOrdering( +#line 2432 "cs.ATG" out ordering); -#line 2431 "cs.ATG" - SafeAdd(q, q.Orderings, ordering); +#line 2432 "cs.ATG" + SafeAdd(oc, oc.Orderings, ordering); while (la.kind == 14) { lexer.NextToken(); - QueryExpressionOrderingClause( -#line 2433 "cs.ATG" + QueryExpressionOrdering( +#line 2434 "cs.ATG" out ordering); -#line 2433 "cs.ATG" - SafeAdd(q, q.Orderings, ordering); +#line 2434 "cs.ATG" + SafeAdd(oc, oc.Orderings, ordering); } + +#line 2436 "cs.ATG" + oc.EndLocation = t.EndLocation; } void QueryExpressionSelectClause( -#line 2447 "cs.ATG" +#line 2449 "cs.ATG" out QueryExpressionSelectClause sc) { -#line 2448 "cs.ATG" +#line 2450 "cs.ATG" Expression expr; sc = new QueryExpressionSelectClause(); sc.StartLocation = la.Location; Expect(133); Expr( -#line 2451 "cs.ATG" +#line 2453 "cs.ATG" out expr); -#line 2451 "cs.ATG" +#line 2453 "cs.ATG" sc.Projection = expr; -#line 2452 "cs.ATG" +#line 2454 "cs.ATG" sc.EndLocation = t.EndLocation; } void QueryExpressionGroupClause( -#line 2455 "cs.ATG" +#line 2457 "cs.ATG" out QueryExpressionGroupClause gc) { -#line 2456 "cs.ATG" +#line 2458 "cs.ATG" Expression expr; gc = new QueryExpressionGroupClause(); gc.StartLocation = la.Location; Expect(134); Expr( -#line 2459 "cs.ATG" +#line 2461 "cs.ATG" out expr); -#line 2459 "cs.ATG" +#line 2461 "cs.ATG" gc.Projection = expr; Expect(135); Expr( -#line 2461 "cs.ATG" +#line 2463 "cs.ATG" out expr); -#line 2461 "cs.ATG" +#line 2463 "cs.ATG" gc.GroupBy = expr; -#line 2462 "cs.ATG" +#line 2464 "cs.ATG" gc.EndLocation = t.EndLocation; } void QueryExpressionIntoClause( -#line 2465 "cs.ATG" +#line 2467 "cs.ATG" out QueryExpressionIntoClause ic) { -#line 2466 "cs.ATG" +#line 2468 "cs.ATG" ic = new QueryExpressionIntoClause(); ic.StartLocation = la.Location; Expect(136); Identifier(); -#line 2469 "cs.ATG" +#line 2471 "cs.ATG" ic.IntoIdentifier = t.val; -#line 2470 "cs.ATG" +#line 2472 "cs.ATG" ic.ContinuedQuery = new QueryExpression(); -#line 2471 "cs.ATG" +#line 2473 "cs.ATG" ic.ContinuedQuery.StartLocation = la.Location; QueryExpressionBody( -#line 2472 "cs.ATG" +#line 2474 "cs.ATG" ic.ContinuedQuery); -#line 2473 "cs.ATG" +#line 2475 "cs.ATG" ic.ContinuedQuery.EndLocation = t.EndLocation; -#line 2474 "cs.ATG" +#line 2476 "cs.ATG" ic.EndLocation = t.EndLocation; } - void QueryExpressionOrderingClause( -#line 2437 "cs.ATG" + void QueryExpressionOrdering( +#line 2439 "cs.ATG" out QueryExpressionOrdering ordering) { -#line 2438 "cs.ATG" +#line 2440 "cs.ATG" Expression expr; ordering = new QueryExpressionOrdering(); ordering.StartLocation = la.Location; Expr( -#line 2440 "cs.ATG" +#line 2442 "cs.ATG" out expr); -#line 2440 "cs.ATG" +#line 2442 "cs.ATG" ordering.Criteria = expr; if (la.kind == 138 || la.kind == 139) { if (la.kind == 138) { lexer.NextToken(); -#line 2441 "cs.ATG" +#line 2443 "cs.ATG" ordering.Direction = QueryExpressionOrderingDirection.Ascending; } else { lexer.NextToken(); -#line 2442 "cs.ATG" +#line 2444 "cs.ATG" ordering.Direction = QueryExpressionOrderingDirection.Descending; } } -#line 2444 "cs.ATG" +#line 2446 "cs.ATG" ordering.EndLocation = t.EndLocation; } @@ -6119,7 +6125,7 @@ out expr); {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x} + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,T,x,x, T,T,T,x, x,x,x} }; } // end Parser diff --git a/src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG b/src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG index 4da5ecc728..0b0e6de991 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG +++ b/src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG @@ -742,11 +742,11 @@ StructMemberDecl attributes> Type Identifier (. FieldDeclaration fd = new FieldDeclaration(attributes, type, m.Modifier | Modifiers.Const); fd.StartLocation = m.GetDeclarationLocation(startPos); VariableDeclaration f = new VariableDeclaration(t.val); - fd.Fields.Add(f); + SafeAdd(fd, fd.Fields, f); .) "=" Expr (. f.Initializer = expr; .) { "," Identifier (. f = new VariableDeclaration(t.val); - fd.Fields.Add(f); + SafeAdd(fd, fd.Fields, f); .) "=" Expr (. f.Initializer = expr; .) } ";" (. fd.EndLocation = t.EndLocation; compilationUnit.AddChild(fd); .) @@ -1422,8 +1422,8 @@ LocalVariableDecl .) = Type (. localVariableDeclaration = new LocalVariableDeclaration(type); localVariableDeclaration.StartLocation = t.Location; .) - LocalVariableDeclarator (. localVariableDeclaration.Variables.Add(var); .) - { "," LocalVariableDeclarator (. localVariableDeclaration.Variables.Add(var); .) } + LocalVariableDeclarator (. SafeAdd(localVariableDeclaration, localVariableDeclaration.Variables, var); .) + { "," LocalVariableDeclarator (. SafeAdd(localVariableDeclaration, localVariableDeclaration.Variables, var); .) } (. stmt = localVariableDeclaration; .) . @@ -1450,8 +1450,8 @@ Statement /*--- local constant declaration: */ | "const" Type (. LocalVariableDeclaration var = new LocalVariableDeclaration(type, Modifiers.Const); string ident = null; var.StartLocation = t.Location; .) Identifier (. ident = t.val; .) - "=" Expr (. var.Variables.Add(new VariableDeclaration(ident, expr)); .) - { "," Identifier (. ident = t.val; .) "=" Expr (. var.Variables.Add(new VariableDeclaration(ident, expr)); .) } + "=" Expr (. SafeAdd(var, var.Variables, new VariableDeclaration(ident, expr)); .) + { "," Identifier (. ident = t.val; .) "=" Expr (. SafeAdd(var, var.Variables, new VariableDeclaration(ident, expr)); .) } ";" (. compilationUnit.AddChild(var); .) /*--- local variable declaration: */ @@ -1973,8 +1973,8 @@ NewExpression ( ( (. ObjectCreateExpression oce = new ObjectCreateExpression(type, parameters); .) "(" (. if (type == null) Error("Cannot use an anonymous type with arguments for the constructor"); .) - [ Argument (. if (expr != null) { parameters.Add(expr); } .) - { "," Argument (. if (expr != null) { parameters.Add(expr); } .) } + [ Argument (. SafeAdd(oce, parameters, expr); .) + { "," Argument (. SafeAdd(oce, parameters, expr); .) } ] ")" (. pexpr = oce; .) [ CollectionOrObjectInitializer (. oce.ObjectInitializer = (CollectionInitializerExpression)expr; .) ] @@ -2390,16 +2390,17 @@ QueryExpressionFromOrJoinClause QueryExpressionBody (. QueryExpressionFromClause fromClause; QueryExpressionWhereClause whereClause; QueryExpressionLetClause letClause; QueryExpressionJoinClause joinClause; + QueryExpressionOrderClause orderClause; QueryExpressionSelectClause selectClause; QueryExpressionGroupClause groupClause; QueryExpressionIntoClause intoClause; .) = - { ( QueryExpressionFromClause (. SafeAdd(q, q.FromLetWhereClauses, fromClause); .) - | QueryExpressionWhereClause (. SafeAdd(q, q.FromLetWhereClauses, whereClause); .) - | QueryExpressionLetClause (. SafeAdd(q, q.FromLetWhereClauses, letClause); .) - | QueryExpressionJoinClause (. SafeAdd(q, q.FromLetWhereClauses, joinClause); .) + { ( QueryExpressionFromClause (. SafeAdd(q, q.MiddleClauses, fromClause); .) + | QueryExpressionWhereClause (. SafeAdd(q, q.MiddleClauses, whereClause); .) + | QueryExpressionLetClause (. SafeAdd(q, q.MiddleClauses, letClause); .) + | QueryExpressionJoinClause (. SafeAdd(q, q.MiddleClauses, joinClause); .) + | QueryExpressionOrderByClause (. SafeAdd(q, q.MiddleClauses, orderClause); .) ) } - [ QueryExpressionOrderByClause ] ( QueryExpressionSelectClause (. q.SelectOrGroupClause = selectClause; .) | QueryExpressionGroupClause (. q.SelectOrGroupClause = groupClause; .) ) @@ -2424,17 +2425,18 @@ QueryExpressionLetClause (. wc.EndLocation = t.EndLocation; .) . -QueryExpressionOrderByClause -(. QueryExpressionOrdering ordering; .) +QueryExpressionOrderByClause +(. QueryExpressionOrdering ordering; oc = new QueryExpressionOrderClause(); oc.StartLocation = la.Location; .) = "orderby" - QueryExpressionOrderingClause (. SafeAdd(q, q.Orderings, ordering); .) + QueryExpressionOrdering (. SafeAdd(oc, oc.Orderings, ordering); .) { "," - QueryExpressionOrderingClause (. SafeAdd(q, q.Orderings, ordering); .) + QueryExpressionOrdering (. SafeAdd(oc, oc.Orderings, ordering); .) } + (. oc.EndLocation = t.EndLocation; .) . -QueryExpressionOrderingClause +QueryExpressionOrdering (. Expression expr; ordering = new QueryExpressionOrdering(); ordering.StartLocation = la.Location; .) = Expr (. ordering.Criteria = expr; .) diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs index f2175ade98..5b7a9d15db 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs @@ -2594,14 +2594,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter { outputFormatter.IndentationLevel++; queryExpression.FromClause.AcceptVisitor(this, data); - queryExpression.FromLetWhereClauses.ForEach(PrintClause); - if (queryExpression.Orderings.Count > 0) { - outputFormatter.NewLine(); - outputFormatter.Indent(); - outputFormatter.PrintToken(Tokens.Orderby); - outputFormatter.Space(); - AppendCommaSeparatedList(queryExpression.Orderings); - } + queryExpression.MiddleClauses.ForEach(PrintClause); PrintClause(queryExpression.SelectOrGroupClause); PrintClause(queryExpression.IntoClause); outputFormatter.IndentationLevel--; @@ -2687,6 +2680,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter return intoClause.ContinuedQuery.AcceptVisitor(this, data); } + public override object TrackedVisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) + { + outputFormatter.PrintToken(Tokens.Orderby); + outputFormatter.Space(); + AppendCommaSeparatedList(queryExpressionOrderClause.Orderings); + return null; + } + public override object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering ordering, object data) { ordering.Criteria.AcceptVisitor(this, data); diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs index eeeebe9fc2..82b1a682ac 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -2777,14 +2777,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter { outputFormatter.IndentationLevel++; queryExpression.FromClause.AcceptVisitor(this, data); - queryExpression.FromLetWhereClauses.ForEach(PrintClause); - if (queryExpression.Orderings.Count > 0) { - outputFormatter.NewLine(); - outputFormatter.Indent(); - outputFormatter.PrintText("Order By"); - outputFormatter.Space(); - AppendCommaSeparatedList(queryExpression.Orderings); - } + queryExpression.MiddleClauses.ForEach(PrintClause); PrintClause(queryExpression.SelectOrGroupClause); PrintClause(queryExpression.IntoClause); outputFormatter.IndentationLevel--; @@ -2870,6 +2863,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter return intoClause.ContinuedQuery.AcceptVisitor(this, data); } + public override object TrackedVisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) + { + outputFormatter.PrintText("Order By"); + outputFormatter.Space(); + AppendCommaSeparatedList(queryExpressionOrderClause.Orderings); + return null; + } + public override object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering ordering, object data) { ordering.Criteria.AcceptVisitor(this, data); diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs index fbbce97492..8abd0b6b57 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs @@ -834,16 +834,11 @@ namespace ICSharpCode.NRefactory.Visitors { public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) { Debug.Assert((queryExpression != null)); Debug.Assert((queryExpression.FromClause != null)); - Debug.Assert((queryExpression.FromLetWhereClauses != null)); - Debug.Assert((queryExpression.Orderings != null)); + Debug.Assert((queryExpression.MiddleClauses != null)); Debug.Assert((queryExpression.SelectOrGroupClause != null)); Debug.Assert((queryExpression.IntoClause != null)); queryExpression.FromClause.AcceptVisitor(this, data); - foreach (QueryExpressionClause o in queryExpression.FromLetWhereClauses) { - Debug.Assert(o != null); - o.AcceptVisitor(this, data); - } - foreach (QueryExpressionOrdering o in queryExpression.Orderings) { + foreach (QueryExpressionClause o in queryExpression.MiddleClauses) { Debug.Assert(o != null); o.AcceptVisitor(this, data); } @@ -891,6 +886,16 @@ namespace ICSharpCode.NRefactory.Visitors { return queryExpressionLetClause.Expression.AcceptVisitor(this, data); } + public virtual object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { + Debug.Assert((queryExpressionOrderClause != null)); + Debug.Assert((queryExpressionOrderClause.Orderings != null)); + foreach (QueryExpressionOrdering o in queryExpressionOrderClause.Orderings) { + Debug.Assert(o != null); + o.AcceptVisitor(this, data); + } + return null; + } + public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { Debug.Assert((queryExpressionOrdering != null)); Debug.Assert((queryExpressionOrdering.Criteria != null)); diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs b/src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs index ac9d80d410..1d977f03f7 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs @@ -1539,34 +1539,22 @@ namespace ICSharpCode.NRefactory.Visitors { public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) { Debug.Assert((queryExpression != null)); Debug.Assert((queryExpression.FromClause != null)); - Debug.Assert((queryExpression.FromLetWhereClauses != null)); - Debug.Assert((queryExpression.Orderings != null)); + Debug.Assert((queryExpression.MiddleClauses != null)); Debug.Assert((queryExpression.SelectOrGroupClause != null)); Debug.Assert((queryExpression.IntoClause != null)); nodeStack.Push(queryExpression.FromClause); queryExpression.FromClause.AcceptVisitor(this, data); queryExpression.FromClause = ((QueryExpressionFromClause)(nodeStack.Pop())); - for (int i = 0; i < queryExpression.FromLetWhereClauses.Count; i++) { - QueryExpressionClause o = queryExpression.FromLetWhereClauses[i]; + for (int i = 0; i < queryExpression.MiddleClauses.Count; i++) { + QueryExpressionClause o = queryExpression.MiddleClauses[i]; Debug.Assert(o != null); nodeStack.Push(o); o.AcceptVisitor(this, data); o = (QueryExpressionClause)nodeStack.Pop(); if (o == null) - queryExpression.FromLetWhereClauses.RemoveAt(i--); + queryExpression.MiddleClauses.RemoveAt(i--); else - queryExpression.FromLetWhereClauses[i] = o; - } - for (int i = 0; i < queryExpression.Orderings.Count; i++) { - QueryExpressionOrdering o = queryExpression.Orderings[i]; - Debug.Assert(o != null); - nodeStack.Push(o); - o.AcceptVisitor(this, data); - o = (QueryExpressionOrdering)nodeStack.Pop(); - if (o == null) - queryExpression.Orderings.RemoveAt(i--); - else - queryExpression.Orderings[i] = o; + queryExpression.MiddleClauses[i] = o; } nodeStack.Push(queryExpression.SelectOrGroupClause); queryExpression.SelectOrGroupClause.AcceptVisitor(this, data); @@ -1642,6 +1630,23 @@ namespace ICSharpCode.NRefactory.Visitors { return null; } + public virtual object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { + Debug.Assert((queryExpressionOrderClause != null)); + Debug.Assert((queryExpressionOrderClause.Orderings != null)); + for (int i = 0; i < queryExpressionOrderClause.Orderings.Count; i++) { + QueryExpressionOrdering o = queryExpressionOrderClause.Orderings[i]; + Debug.Assert(o != null); + nodeStack.Push(o); + o.AcceptVisitor(this, data); + o = (QueryExpressionOrdering)nodeStack.Pop(); + if (o == null) + queryExpressionOrderClause.Orderings.RemoveAt(i--); + else + queryExpressionOrderClause.Orderings[i] = o; + } + return null; + } + public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { Debug.Assert((queryExpressionOrdering != null)); Debug.Assert((queryExpressionOrdering.Criteria != null)); diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs index 782921ccf5..95b15cd735 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs @@ -584,6 +584,13 @@ namespace ICSharpCode.NRefactory.Visitors { return result; } + public sealed override object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { + this.BeginVisit(queryExpressionOrderClause); + object result = this.TrackedVisitQueryExpressionOrderClause(queryExpressionOrderClause, data); + this.EndVisit(queryExpressionOrderClause); + return result; + } + public sealed override object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { this.BeginVisit(queryExpressionOrdering); object result = this.TrackedVisitQueryExpressionOrdering(queryExpressionOrdering, data); @@ -1124,6 +1131,10 @@ namespace ICSharpCode.NRefactory.Visitors { return base.VisitQueryExpressionLetClause(queryExpressionLetClause, data); } + public virtual object TrackedVisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { + return base.VisitQueryExpressionOrderClause(queryExpressionOrderClause, data); + } + public virtual object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { return base.VisitQueryExpressionOrdering(queryExpressionOrdering, data); } diff --git a/src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs b/src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs index 43adf69900..5995591d34 100644 --- a/src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs +++ b/src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs @@ -24,9 +24,9 @@ namespace ICSharpCode.NRefactory.Tests.Ast ); Assert.AreEqual("c", qe.FromClause.Identifier); Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.InExpression).Identifier); - Assert.AreEqual(1, qe.FromLetWhereClauses.Count); - Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[0]); - QueryExpressionWhereClause wc = (QueryExpressionWhereClause)qe.FromLetWhereClauses[0]; + Assert.AreEqual(1, qe.MiddleClauses.Count); + Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.MiddleClauses[0]); + QueryExpressionWhereClause wc = (QueryExpressionWhereClause)qe.MiddleClauses[0]; Assert.IsInstanceOfType(typeof(BinaryOperatorExpression), wc.Condition); Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); } @@ -77,12 +77,37 @@ where c.City == ""London"" from o in c.Orders where o.OrderDate.Year == 2005 select new { c.Name, o.OrderID, o.Total }"); - Assert.AreEqual(3, qe.FromLetWhereClauses.Count); - Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[0]); - Assert.IsInstanceOfType(typeof(QueryExpressionFromClause), qe.FromLetWhereClauses[1]); - Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[2]); + Assert.AreEqual(3, qe.MiddleClauses.Count); + Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.MiddleClauses[0]); + Assert.IsInstanceOfType(typeof(QueryExpressionFromClause), qe.MiddleClauses[1]); + Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.MiddleClauses[2]); Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); } + + [Test] + public void ExpressionWithOrderBy() + { + QueryExpression qe = ParseUtilCSharp.ParseExpression( + "from c in customers orderby c.Name select c" + ); + Assert.AreEqual("c", qe.FromClause.Identifier); + Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.InExpression).Identifier); + Assert.IsInstanceOfType(typeof(QueryExpressionOrderClause), qe.MiddleClauses[0]); + Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + } + + [Test] + public void ExpressionWithOrderByAndLet() + { + QueryExpression qe = ParseUtilCSharp.ParseExpression( + "from c in customers orderby c.Name let x = c select x" + ); + Assert.AreEqual("c", qe.FromClause.Identifier); + Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.InExpression).Identifier); + Assert.IsInstanceOfType(typeof(QueryExpressionOrderClause), qe.MiddleClauses[0]); + Assert.IsInstanceOfType(typeof(QueryExpressionLetClause), qe.MiddleClauses[1]); + Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + } } } diff --git a/src/Main/Base/Test/NRefactoryResolverTests.cs b/src/Main/Base/Test/NRefactoryResolverTests.cs index 15fc36c399..18fe855de6 100644 --- a/src/Main/Base/Test/NRefactoryResolverTests.cs +++ b/src/Main/Base/Test/NRefactoryResolverTests.cs @@ -418,8 +418,8 @@ class A { public event EventHandler TestEvent; } "; - MemberResolveResult result = Resolve(program, "TestEvent(this, EventArgs.Empty)", 4); - Assert.AreEqual("A.TestEvent", result.ResolvedMember.FullyQualifiedName); + var result = Resolve(program, "TestEvent(this, EventArgs.Empty)", 4); + Assert.AreEqual("A.TestEvent", (result.Target as MemberResolveResult).ResolvedMember.FullyQualifiedName); } [Test] @@ -450,8 +450,8 @@ class A { public event EventHandler TestEvent; } "; - MemberResolveResult result = Resolve(program, "this.TestEvent(this, EventArgs.Empty)", 4); - Assert.AreEqual("A.TestEvent", result.ResolvedMember.FullyQualifiedName); + var result = Resolve(program, "this.TestEvent(this, EventArgs.Empty)", 4); + Assert.AreEqual("A.TestEvent", (result.Target as MemberResolveResult).ResolvedMember.FullyQualifiedName); } [Test] @@ -465,8 +465,8 @@ class A { } } "; - LocalResolveResult result = Resolve(program, "eh(this, new ResolveEventArgs())", 5); - Assert.AreEqual("eh", result.Field.Name); + var result = Resolve(program, "eh(this, new ResolveEventArgs())", 5); + Assert.AreEqual("eh", (result.Target as LocalResolveResult).Field.Name); MemberResolveResult mrr = Resolve(program, "eh(this, new ResolveEventArgs()).GetType(\"bla\")", 5); Assert.AreEqual("System.Reflection.Module.GetType", mrr.ResolvedMember.FullyQualifiedName); @@ -483,7 +483,7 @@ class A { abstract Predicate GetHandler(); } "; - ResolveResult result = Resolve(program, "GetHandler()(abc)", 4); + var result = Resolve(program, "GetHandler()(abc)", 4); Assert.AreEqual("System.Boolean", result.ResolvedType.FullyQualifiedName); MemberResolveResult mrr = Resolve(program, "GetHandler()(abc).ToString()", 4); @@ -1920,7 +1920,9 @@ public class MyCollectionType : System.Collections.IEnumerable class BaseClass { public static SomeDelegate Test; }"; - MemberResolveResult mrr = Resolve(program, "BaseClass.Test()", 4); + var dcrr = Resolve(program, "BaseClass.Test()", 4); + Assert.AreEqual("SomeDelegate.Invoke", dcrr.DelegateInvokeMethod.FullyQualifiedName); + var mrr = dcrr.Target as MemberResolveResult; Assert.AreEqual("BaseClass.Test", mrr.ResolvedMember.FullyQualifiedName); mrr = Resolve(program, "Test", 4); @@ -1930,7 +1932,8 @@ public class MyCollectionType : System.Collections.IEnumerable Assert.AreEqual("DerivedClass.Test", mrr.ResolvedMember.FullyQualifiedName); // returns BaseClass.Test because DerivedClass.Test is not invocable - mrr = Resolve(program, "DerivedClass.Test()", 4); + dcrr = Resolve(program, "DerivedClass.Test()", 4); + mrr = (MemberResolveResult)dcrr.Target; Assert.AreEqual("BaseClass.Test", mrr.ResolvedMember.FullyQualifiedName); } @@ -2092,6 +2095,20 @@ class TestClass { Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); } + [Test] + public void LambdaInConstructorTest() + { + string program = @"using System; +class TestClass { + static void Main() { + TestClass t = new TestClass(i => Console.WriteLine(i)); + } + public TestClass(Action ac) { ac(42); } +}"; + var lrr = Resolve(program, "i", 4, 54, ExpressionContext.Default); + Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); + } + [Test] public void IncompleteLambdaTest() { @@ -2121,5 +2138,80 @@ static class TestClass { var lrr = Resolve(program, "i", 5, 20, ExpressionContext.Default); Assert.AreEqual("System.String", lrr.ResolvedType.DotNetName); } + + [Test] + public void LambdaExpressionInCastExpression() + { + string program = @"using System; +static class TestClass { + static void Main(string[] args) { + var f = (Func) ( i => i ); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program, "i", 4, 38, ExpressionContext.Default); + Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); + } + + [Test] + public void CurriedLambdaExpressionInCastExpression() + { + string program = @"using System; +static class TestClass { + static void Main(string[] args) { + var f = (Func>) ( a => b => 0 ); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program, "a", 4, 45, ExpressionContext.Default); + Assert.AreEqual("System.Char", lrr.ResolvedType.DotNetName); + + lrr = Resolve(program, "b", 4, 50, ExpressionContext.Default); + Assert.AreEqual("System.String", lrr.ResolvedType.DotNetName); + } + + [Test] + public void LambdaExpressionInVariableInitializer() + { + string program = @"using System; +static class TestClass { + static void Main() { + Func f = i => i.ToString(); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program, "i", 4, 25, ExpressionContext.Default); + Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); + } + + [Test] + public void LambdaExpressionInVariableAssignment() + { + string program = @"using System; +static class TestClass { + static void Main() { + Func f; + f = i => i.ToString(); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program, "i", 5, 8, ExpressionContext.Default); + Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); + } + + [Test] + public void LambdaInDelegateCallTest() + { + string program = @"using System; +class TestClass { + static void Main() { + Func, char> f; + f(i => i.ToString()); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program, "i", 5, 5, ExpressionContext.Default); + Assert.AreEqual("System.Int32", lrr.ResolvedType.DotNetName); + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs index 772db38236..731739acd3 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs @@ -1215,16 +1215,63 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (index < 0) return null; - MemberResolveResult mrr = ResolveInternal(ie, ExpressionContext.Default) as MemberResolveResult; - if (mrr != null) { - if (mrr.IsExtensionMethodCall) + ResolveResult rr = ResolveInternal(ie, ExpressionContext.Default); + IMethod m; + if (rr is MemberResolveResult) { + m = (rr as MemberResolveResult).ResolvedMember as IMethod; + if ((rr as MemberResolveResult).IsExtensionMethodCall) index++; - + } else if (rr is DelegateCallResolveResult) { + m = (rr as DelegateCallResolveResult).DelegateInvokeMethod; + } else { + m = null; + } + if (m != null && index < m.Parameters.Count) + return m.Parameters[index].ReturnType; + } + + ObjectCreateExpression oce = expr.Parent as ObjectCreateExpression; + if (oce != null) { + int index = oce.Parameters.IndexOf(expr); + if (index < 0) + return null; + + MemberResolveResult mrr = ResolveInternal(oce, ExpressionContext.Default) as MemberResolveResult; + if (mrr != null) { IMethod m = mrr.ResolvedMember as IMethod; if (m != null && index < m.Parameters.Count) return m.Parameters[index].ReturnType; } } + + if (expr.Parent is CastExpression) { + ResolveResult rr = ResolveInternal((Expression)expr.Parent, ExpressionContext.Default); + if (rr != null) + return rr.ResolvedType; + } + if (expr.Parent is LambdaExpression) { + IReturnType delegateType = GetExpectedTypeFromContext(expr.Parent as Expression); + IMethod sig = CSharp.TypeInference.GetDelegateOrExpressionTreeSignature(delegateType, true); + if (sig != null) + return sig.ReturnType; + } + if (expr.Parent is ParenthesizedExpression) { + return GetExpectedTypeFromContext(expr.Parent as Expression); + } + if (expr.Parent is VariableDeclaration) { + TypeReference typeRef = (expr.Parent as VariableDeclaration).TypeReference; + if (typeRef == null || typeRef.IsNull) { + LocalVariableDeclaration lvd = expr.Parent.Parent as LocalVariableDeclaration; + if (lvd != null) + typeRef = lvd.TypeReference; + } + return TypeVisitor.CreateReturnType(typeRef, this); + } + if (expr.Parent is AssignmentExpression) { + ResolveResult rr = ResolveInternal((expr.Parent as AssignmentExpression).Left, ExpressionContext.Default); + if (rr != null) + return rr.ResolvedType; + } return null; } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs index 483ee5dbe1..ed6f484b93 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs @@ -202,7 +202,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) { return resolver.ResolveIdentifier(identifierExpression, ExpressionContext.Default); - } + } public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data) { @@ -304,14 +304,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (c != null && c.ClassType == ClassType.Delegate) { // We don't want to show "System.EventHandler.Invoke" in the tooltip // of "EventCall(this, EventArgs.Empty)", we just show the event/delegate for now - // but for DelegateCall(params).* completion, we use the delegate's // return type instead of the delegate type itself - IMethod method = c.Methods.FirstOrDefault(innerMethod => innerMethod.Name == "Invoke"); + + IMethod method = rr.ResolvedType.GetMethods().FirstOrDefault(innerMethod => innerMethod.Name == "Invoke"); if (method != null) { - rr = rr.Clone(); - rr.ResolvedType = method.ReturnType; - return rr; + return new DelegateCallResolveResult(rr, method); } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs index 88e9307510..fa92cd7ddd 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs @@ -493,9 +493,9 @@ namespace ICSharpCode.SharpDevelop.Dom public bool IsExtensionMethodCall { get { return isExtensionMethodCall; } - set { + set { CheckBeforeMutation(); - isExtensionMethodCall = value; + isExtensionMethodCall = value; } } @@ -800,6 +800,57 @@ namespace ICSharpCode.SharpDevelop.Dom } #endregion + #region DelegateCallResolveResult + /// + /// Is used for calls to delegates/events. + /// + public class DelegateCallResolveResult : ResolveResult + { + IMethod delegateInvokeMethod; + ResolveResult targetRR; + + protected override void FreezeInternal() + { + base.FreezeInternal(); + delegateInvokeMethod.Freeze(); + targetRR.Freeze(); + } + + public DelegateCallResolveResult(ResolveResult targetRR, IMethod delegateInvokeMethod) + : base(targetRR.CallingClass, targetRR.CallingMember, delegateInvokeMethod.ReturnType) + { + this.targetRR = targetRR; + this.delegateInvokeMethod = delegateInvokeMethod; + } + + /// + /// Gets the Invoke() method of the delegate. + /// + public IMethod DelegateInvokeMethod { + get { return delegateInvokeMethod; } + } + + /// + /// Gets the type of the delegate. + /// + public IReturnType DelegateType { + get { return targetRR.ResolvedType; } + } + + /// + /// Gets the resolve result referring to the delegate. + /// + public ResolveResult Target { + get { return targetRR; } + } + + public override ResolveResult Clone() + { + return new DelegateCallResolveResult(targetRR, delegateInvokeMethod); + } + } + #endregion + #region UnknownIdentifierResolveResult /// /// Used for unknown identifiers.