Browse Source

Adjust AST for async/await.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
fd8f8cf6cb
  1. 11
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs
  2. 11
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs
  3. 15
      ICSharpCode.NRefactory.CSharp/Ast/Modifiers.cs
  4. 29
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  5. 13
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs
  6. 24
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs
  7. 26
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs
  8. 28
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs
  9. 2
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

11
ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs

@ -30,11 +30,15 @@ using System.Linq; @@ -30,11 +30,15 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// delegate(Parameters) {Body}
/// [async] delegate(Parameters) {Body}
/// </summary>
public class AnonymousMethodExpression : Expression
{
// used to make a difference between delegate {} and delegate () {}
public readonly static Role<CSharpTokenNode> AsyncModifierRole = LambdaExpression.AsyncModifierRole;
public bool IsAsync { get; set; }
// used to tell the difference between delegate {} and delegate () {}
public bool HasParameterList {
get; set;
}
@ -86,7 +90,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -86,7 +90,8 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
AnonymousMethodExpression o = other as AnonymousMethodExpression;
return o != null && this.HasParameterList == o.HasParameterList && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
return o != null && this.IsAsync == o.IsAsync && this.HasParameterList == o.HasParameterList
&& this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
}
}
}

11
ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
// LambdaExpression.cs
//
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
@ -29,14 +29,17 @@ using System.Linq; @@ -29,14 +29,17 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// Parameters => Body
/// [async] Parameters => Body
/// </summary>
public class LambdaExpression : Expression
{
public readonly static Role<CSharpTokenNode> AsyncModifierRole = new Role<CSharpTokenNode>("AsyncModifier", CSharpTokenNode.Null);
public readonly static Role<CSharpTokenNode> ArrowRole = new Role<CSharpTokenNode>("Arrow", CSharpTokenNode.Null);
public static readonly Role<AstNode> BodyRole = new Role<AstNode>("Body", AstNode.Null);
public AstNodeCollection<ParameterDeclaration> Parameters {
public bool IsAsync { get; set; }
public AstNodeCollection<ParameterDeclaration> Parameters {
get { return GetChildrenByRole (Roles.Parameter); }
}
@ -57,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -57,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
LambdaExpression o = other as LambdaExpression;
return o != null && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
return o != null && this.IsAsync == o.IsAsync && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
}
}
}

15
ICSharpCode.NRefactory.CSharp/Ast/Modifiers.cs

@ -30,7 +30,6 @@ using System; @@ -30,7 +30,6 @@ using System;
namespace ICSharpCode.NRefactory.CSharp
{
// For compatibility with old nrefactory - same flags.
[Flags]
public enum Modifiers
{
@ -54,21 +53,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -54,21 +53,13 @@ namespace ICSharpCode.NRefactory.CSharp
Extern = 0x2000,
Volatile = 0x4000,
Unsafe = 0x8000,
Async = 0x10000,
//Overloads = 0x10000,
//WithEvents = 0x20000,
//Default = 0x40000,
//Fixed = 0x80000,
//ProtectedOrInternal = Internal | Protected,
//ProtectedAndInternal = 0x100000, (not supported in C#)
//SpecialName = 0x200000,
//Final = 0x400000,
//Literal = 0x800000,
VisibilityMask = Private | Internal | Protected | Public,
/// <summary>
/// Special value used to match any modifiers during pattern matching.
/// </summary>
Any = unchecked((int)0x80000000)
}}
}
}

29
ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -23,7 +23,7 @@ using System.Globalization; @@ -23,7 +23,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.TypeSystem;
@ -414,13 +414,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -414,13 +414,21 @@ namespace ICSharpCode.NRefactory.CSharp
{
if (unconditionalKeywords.Contains (identifier))
return true;
if (context.Ancestors.Any (a => a is QueryExpression)) {
if (queryKeywords.Contains (identifier))
foreach (AstNode ancestor in context.Ancestors) {
if (ancestor is QueryExpression && queryKeywords.Contains (identifier))
return true;
if (identifier == "await") {
// with lambdas/anonymous methods,
if (ancestor is LambdaExpression)
return ((LambdaExpression)ancestor).IsAsync;
if (ancestor is AnonymousMethodExpression)
return ((AnonymousMethodExpression)ancestor).IsAsync;
if (ancestor is AttributedNode)
return (((AttributedNode)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async;
}
}
return false;
}
#endregion
#region Write constructs
@ -512,6 +520,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -512,6 +520,10 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, object data)
{
StartNode (anonymousMethodExpression);
if (anonymousMethodExpression.IsAsync) {
WriteKeyword ("async", AnonymousMethodExpression.AsyncModifierRole);
Space ();
}
WriteKeyword ("delegate");
if (anonymousMethodExpression.HasParameterList) {
Space (policy.SpaceBeforeMethodDeclarationParentheses);
@ -786,6 +798,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -786,6 +798,10 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitLambdaExpression (LambdaExpression lambdaExpression, object data)
{
StartNode (lambdaExpression);
if (lambdaExpression.IsAsync) {
WriteKeyword ("async", LambdaExpression.AsyncModifierRole);
Space ();
}
if (LambdaNeedsParenthesis (lambdaExpression)) {
WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
} else {
@ -1112,8 +1128,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1112,8 +1128,11 @@ namespace ICSharpCode.NRefactory.CSharp
StartNode (unaryOperatorExpression);
UnaryOperatorType opType = unaryOperatorExpression.Operator;
string opSymbol = UnaryOperatorExpression.GetOperatorSymbol (opType);
if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement))
if (opType == UnaryOperatorType.Await) {
WriteKeyword (opSymbol, UnaryOperatorExpression.OperatorRole);
} else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole);
}
unaryOperatorExpression.Expression.AcceptVisitor (this, data);
if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)
WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole);

13
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs → ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs

@ -24,7 +24,7 @@ using NUnit.Framework; @@ -24,7 +24,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
{
[TestFixture]
public class AnonymousMethodTests
public class AnonymousMethodExpressionTests
{
AnonymousMethodExpression Parse(string expression)
{
@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
AnonymousMethodExpression ame = Parse("delegate {}");
Assert.AreEqual(0, ame.Parameters.Count());
Assert.AreEqual(0, ame.Body.Statements.Count());
Assert.IsFalse(ame.IsAsync);
Assert.IsFalse(ame.HasParameterList);
}
@ -67,5 +68,15 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -67,5 +68,15 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
Assert.AreEqual(1, ame.Body.Statements.Count());
Assert.IsTrue(ame.Body.Statements.First() is ReturnStatement);
}
[Test, Ignore("async/await not yet supported")]
public void AsyncAnonymousMethod()
{
AnonymousMethodExpression ame = Parse("async delegate {}");
Assert.AreEqual(0, ame.Parameters.Count());
Assert.AreEqual(0, ame.Body.Statements.Count());
Assert.IsTrue(ame.IsAsync);
Assert.IsFalse(ame.HasParameterList);
}
}
}

24
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs

@ -119,5 +119,29 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -119,5 +119,29 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
FalseExpression = new NullReferenceExpression()
}});
}
[Test, Ignore("async/await not yet supported")]
public void AsyncLambdaExpression()
{
ParseUtilCSharp.AssertExpression(
"async x => x + 1",
new LambdaExpression {
IsAsync = true,
Parameters = { new ParameterDeclaration { Name = "x" } },
Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1))
});
}
[Test, Ignore("async/await not yet supported")]
public void AsyncLambdaExpressionWithMultipleParameters()
{
ParseUtilCSharp.AssertExpression(
"async (x,y) => x + 1",
new LambdaExpression {
IsAsync = true,
Parameters = { new ParameterDeclaration { Name = "x" }, new ParameterDeclaration { Name = "y" } },
Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1))
});
}
}
}

26
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs

@ -92,6 +92,32 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -92,6 +92,32 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
TestUnaryOperatorExpressionTest("&a", UnaryOperatorType.AddressOf);
}
[Test, Ignore("async/await not yet supported")]
public void Await()
{
ParseUtilCSharp.AssertExpression(
"async a => await a",
new LambdaExpression {
IsAsync = true,
Parameters = { new ParameterDeclaration { Name = "a" } },
Body = new UnaryOperatorExpression(UnaryOperatorType.Await, new IdentifierExpression("a"))
});
}
[Test, Ignore("async/await not yet supported")]
public void AwaitAwait()
{
ParseUtilCSharp.AssertExpression(
"async a => await await a",
new LambdaExpression {
IsAsync = true,
Parameters = { new ParameterDeclaration { Name = "a" } },
Body = new UnaryOperatorExpression(
UnaryOperatorType.Await,
new UnaryOperatorExpression(UnaryOperatorType.Await, new IdentifierExpression("a")))
});
}
[Test]
public void DereferenceAfterCast()
{

28
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs

@ -355,5 +355,33 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -355,5 +355,33 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
}
}});
}
[Test, Ignore("async/await not yet supported")]
public void AsyncMethod()
{
ParseUtilCSharp.AssertTypeMember(
"async void MyMethod() {}",
new MethodDeclaration {
Modifiers = Modifiers.Async,
ReturnType = new PrimitiveType("void"),
Name = "MyMethod",
Body = new BlockStatement()
});
}
[Test, Ignore("async/await not yet supported")]
public void AsyncAsyncAsync()
{
ParseUtilCSharp.AssertTypeMember(
"async async async(async async) {}",
new MethodDeclaration {
Modifiers = Modifiers.Async,
ReturnType = new SimpleType("async"),
Name = "async",
Body = new BlockStatement(),
Parameters = {
new ParameterDeclaration(new SimpleType("async"), "async")
}});
}
}
}

2
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -114,7 +114,7 @@ @@ -114,7 +114,7 @@
<Compile Include="CSharp\Parser\TypeMembers\OperatorDeclarationTests.cs" />
<Compile Include="CSharp\Parser\TypeMembers\PropertyDeclarationTests.cs" />
<Compile Include="CSharp\Parser\TypeSystemConvertVisitorTests.cs" />
<Compile Include="CSharp\Parser\Expression\AnonymousMethodTests.cs" />
<Compile Include="CSharp\Parser\Expression\AnonymousMethodExpressionTests.cs" />
<Compile Include="CSharp\Parser\Expression\ArrayCreateExpressionTests.cs" />
<Compile Include="CSharp\Parser\Expression\AssignmentExpressionTests.cs" />
<Compile Include="CSharp\Parser\Expression\BaseReferenceExpressionTests.cs" />

Loading…
Cancel
Save