Browse Source

Fixed some issues with code round-tripping; and added unit tests for some parser failures.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
a71670f2bc
  1. 64
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  2. 14
      ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs
  3. 13
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs
  4. 1
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs
  5. 36
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/PreprocessorDirectiveTests.cs
  6. 45
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs
  7. 1
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs
  8. 2
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs
  9. 2
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  10. 0
      ICSharpCode.NRefactory/TypeSystem/SpecialType.cs

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

@ -211,20 +211,29 @@ namespace ICSharpCode.NRefactory.CSharp @@ -211,20 +211,29 @@ namespace ICSharpCode.NRefactory.CSharp
}
/// <summary>
/// Writes an optional comma, e.g. at the end of an enum declaration
/// Writes an optional comma, e.g. at the end of an enum declaration or in an array initializer
/// </summary>
void OptionalComma()
{
// Look for the role between the current position and the nextNode.
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) {
if (pos.Role == AstNode.Roles.Comma) {
Comma(null, noSpaceAfterComma: true);
break;
} else if (pos.NodeType != NodeType.Whitespace) {
// only skip over whitespace and comma nodes
break;
}
}
// Look if there's a comma after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == AstNode.Roles.Comma)
Comma(null, noSpaceAfterComma: true);
}
/// <summary>
/// Writes an optional semicolon, e.g. at the end of a type or namespace declaration.
/// </summary>
void OptionalSemicolon()
{
// Look if there's a semicolon after the current node, and insert it if it exists.
AstNode pos = positionStack.Peek();
while (pos != null && pos.NodeType == NodeType.Whitespace)
pos = pos.NextSibling;
if (pos != null && pos.Role == AstNode.Roles.Semicolon)
Semicolon();
}
void WriteCommaSeparatedList (IEnumerable<AstNode> list)
@ -362,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -362,7 +371,7 @@ namespace ICSharpCode.NRefactory.CSharp
void RPar ()
{
WriteToken (")", AstNode.Roles.LPar);
WriteToken (")", AstNode.Roles.RPar);
}
/// <summary>
@ -595,10 +604,27 @@ namespace ICSharpCode.NRefactory.CSharp @@ -595,10 +604,27 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data)
{
StartNode (arrayInitializerExpression);
PrintInitializerElements(arrayInitializerExpression.Elements);
bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1
&& IsObjectInitializer(arrayInitializerExpression.Parent);
if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) {
arrayInitializerExpression.Elements.Single().AcceptVisitor(this, data);
} else {
PrintInitializerElements(arrayInitializerExpression.Elements);
}
return EndNode (arrayInitializerExpression);
}
bool IsObjectInitializer(AstNode node)
{
if (!(node is ArrayInitializerExpression))
return false;
if (node.Parent is ObjectCreateExpression)
return node.Role == ObjectCreateExpression.InitializerRole;
if (node.Parent is NamedExpression)
return node.Role == NamedExpression.Roles.Expression;
return false;
}
void PrintInitializerElements(AstNodeCollection<Expression> elements)
{
BraceStyle style;
@ -617,6 +643,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -617,6 +643,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
node.AcceptVisitor(this, null);
}
OptionalComma();
NewLine();
CloseBrace(style);
}
@ -902,7 +929,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -902,7 +929,6 @@ namespace ICSharpCode.NRefactory.CSharp
{
StartNode (anonymousTypeCreateExpression);
WriteKeyword ("new");
Space ();
PrintInitializerElements(anonymousTypeCreateExpression.Initializers);
return EndNode (anonymousTypeCreateExpression);
}
@ -1327,9 +1353,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1327,9 +1353,10 @@ namespace ICSharpCode.NRefactory.CSharp
{
StartNode (attribute);
attribute.Type.AcceptVisitor (this, data);
Space (policy.SpaceBeforeMethodCallParentheses);
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull)
if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull) {
Space (policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses);
}
return EndNode (attribute);
}
@ -1379,6 +1406,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1379,6 +1406,7 @@ namespace ICSharpCode.NRefactory.CSharp
foreach (var member in namespaceDeclaration.Members)
member.AcceptVisitor (this, data);
CloseBrace (policy.NamespaceBraceStyle);
OptionalSemicolon ();
NewLine ();
return EndNode (namespaceDeclaration);
}
@ -1438,6 +1466,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1438,6 +1466,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
CloseBrace (braceStyle);
OptionalSemicolon ();
NewLine ();
return EndNode (typeDeclaration);
}
@ -1867,6 +1896,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1867,6 +1896,7 @@ namespace ICSharpCode.NRefactory.CSharp
public object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data)
{
StartNode (variableDeclarationStatement);
WriteModifiers (variableDeclarationStatement.GetChildrenByRole (VariableDeclarationStatement.ModifierRole));
variableDeclarationStatement.Type.AcceptVisitor (this, data);
Space ();
WriteCommaSeparatedList (variableDeclarationStatement.Variables);

14
ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs

@ -65,5 +65,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -65,5 +65,19 @@ namespace ICSharpCode.NRefactory.CSharp
AssertOutput("enum DisplayFlags\n{\n$D = 4\n}\n", type);
}
[Test]
public void InlineCommentAtEndOfCondition()
{
IfElseStatement condition = new IfElseStatement();
condition.AddChild(new CSharpTokenNode(new TextLocation(1, 1), 2), IfElseStatement.IfKeywordRole);
condition.AddChild(new CSharpTokenNode(new TextLocation(1, 4), 1), IfElseStatement.Roles.LPar);
condition.AddChild(new IdentifierExpression("cond", new TextLocation(1, 5)), IfElseStatement.ConditionRole);
condition.AddChild(new Comment(CommentType.MultiLine, new TextLocation(1, 9), new TextLocation(1, 14)) { Content = "a" }, IfElseStatement.Roles.Comment);
condition.AddChild(new CSharpTokenNode(new TextLocation(1, 14), 1), IfElseStatement.Roles.RPar);
condition.AddChild(new ReturnStatement(), IfElseStatement.TrueRole);
AssertOutput("if (cond/*a*/)\n$return;\n", condition);
}
}
}

13
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
@ -145,5 +146,17 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -145,5 +146,17 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
}
}});
}
[Test]
public void ArrayInitializerWithCommaAtEnd()
{
var ace = ParseUtilCSharp.ParseExpression<ArrayCreateExpression>("new [] { 1, }");
Assert.AreEqual(new Role[] {
AstNode.Roles.LBrace,
AstNode.Roles.Expression,
AstNode.Roles.Comma,
AstNode.Roles.RBrace
}, ace.Initializer.Children.Select(c => c.Role).ToArray());
}
}
}

1
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs

@ -67,6 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -67,6 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
"Namespace.Subnamespace.SomeClass<string>.myField",
new MemberReferenceExpression {
Target = new IdentifierExpression("Namespace").Member("Subnamespace"),
MemberName = "SomeClass",
TypeArguments = { new PrimitiveType("string") }
}.Member("myField")
);

36
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/PreprocessorDirectiveTests.cs

@ -35,15 +35,16 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope @@ -35,15 +35,16 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope
}";
NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal<NamespaceDeclaration>(program);
Assert.AreEqual(0, ns.Members.Count);
Assert.AreEqual(7, ns.Children.Count());
Assert.AreEqual(AstNode.Roles.Keyword, ns.Children.ElementAt(0).Role);
Assert.AreEqual(AstNode.Roles.Identifier, ns.Children.ElementAt(1).Role);
Assert.AreEqual(AstNode.Roles.LBrace, ns.Children.ElementAt(2).Role);
Assert.AreEqual(AstNode.Roles.PreProcessorDirective, ns.Children.ElementAt(3).Role);
Assert.AreEqual(AstNode.Roles.Comment, ns.Children.ElementAt(4).Role);
Assert.AreEqual(AstNode.Roles.PreProcessorDirective, ns.Children.ElementAt(5).Role);
Assert.AreEqual(AstNode.Roles.RBrace, ns.Children.ElementAt(6).Role);
Assert.AreEqual(new Role[] {
AstNode.Roles.Keyword,
AstNode.Roles.Identifier,
AstNode.Roles.LBrace,
AstNode.Roles.PreProcessorDirective,
AstNode.Roles.Comment,
AstNode.Roles.PreProcessorDirective,
AstNode.Roles.RBrace
}, ns.Children.Select(c => c.Role).ToArray());
var pp = ns.GetChildrenByRole(AstNode.Roles.PreProcessorDirective);
@ -53,16 +54,25 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope @@ -53,16 +54,25 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope
Assert.AreEqual(new TextLocation(2, 2), pp.First().StartLocation);
Assert.AreEqual(new TextLocation(2, 15), pp.First().EndLocation);
var c = ns.GetChildByRole(AstNode.Roles.Comment);
Assert.AreEqual(CommentType.InactiveCode, c.CommentType);
Assert.AreEqual(new TextLocation(3, 1), c.StartLocation);
Assert.AreEqual(new TextLocation(4, 2), c.EndLocation);
Assert.AreEqual("\tclass A {}\n\t", c.Content.Replace("\r", ""));
var comment = ns.GetChildByRole(AstNode.Roles.Comment);
Assert.AreEqual(CommentType.InactiveCode, comment.CommentType);
Assert.AreEqual(new TextLocation(3, 1), comment.StartLocation);
Assert.AreEqual(new TextLocation(4, 2), comment.EndLocation);
Assert.AreEqual("\tclass A {}\n\t", comment.Content.Replace("\r", ""));
Assert.AreEqual(PreProcessorDirectiveType.Endif, pp.Last().Type);
Assert.AreEqual(string.Empty, pp.Last().Argument);
Assert.AreEqual(new TextLocation(4, 2), pp.First().StartLocation);
Assert.AreEqual(new TextLocation(4, 8), pp.First().EndLocation);
}
[Test]
public void PragmaWarning()
{
string program = "#pragma warning disable 809";
var ppd = ParseUtilCSharp.ParseGlobal<PreProcessorDirective>(program);
Assert.AreEqual(PreProcessorDirectiveType.Pragma, ppd.Type);
Assert.AreEqual("warning disable 809", ppd.Argument);
}
}
}

45
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs

@ -333,10 +333,47 @@ public abstract class MyClass : MyBase, Interface1, My.Test.Interface2 @@ -333,10 +333,47 @@ public abstract class MyClass : MyBase, Interface1, My.Test.Interface2
[Test]
public void EnumWithCommaAtEnd()
{
TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A, B, }");
Assert.AreEqual(2, td.Members.Count);
Assert.AreEqual(AstNode.Roles.RBrace, td.LastChild.Role);
Assert.AreEqual(AstNode.Roles.Comma, td.LastChild.PrevSibling.Role);
TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A, }");
Assert.AreEqual(
new Role[] {
AstNode.Roles.Keyword,
AstNode.Roles.Identifier,
AstNode.Roles.LBrace,
TypeDeclaration.MemberRole,
AstNode.Roles.Comma,
AstNode.Roles.RBrace
}, td.Children.Select(c => c.Role).ToArray());
}
[Test]
public void EnumWithCommaAndSemicolonAtEnd()
{
TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A, };");
Assert.AreEqual(
new Role[] {
AstNode.Roles.Keyword,
AstNode.Roles.Identifier,
AstNode.Roles.LBrace,
TypeDeclaration.MemberRole,
AstNode.Roles.Comma,
AstNode.Roles.RBrace,
AstNode.Roles.Semicolon
}, td.Children.Select(c => c.Role).ToArray());
}
[Test]
public void EnumWithSemicolonAtEnd()
{
TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A };");
Assert.AreEqual(
new Role[] {
AstNode.Roles.Keyword,
AstNode.Roles.Identifier,
AstNode.Roles.LBrace,
TypeDeclaration.MemberRole,
AstNode.Roles.RBrace,
AstNode.Roles.Semicolon
}, td.Children.Select(c => c.Role).ToArray());
}
}
}

1
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs

@ -59,6 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -59,6 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
Identifier = "MyInterface",
TypeArguments = { new PrimitiveType("string") }
},
Name = "this",
Parameters = {
new ParameterDeclaration(new PrimitiveType("int"), "a"),
new ParameterDeclaration(new PrimitiveType("string"), "b")

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

@ -167,6 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -167,6 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
",
new TypeDeclaration {
ClassType = ClassType.Interface,
Name = "MyInterface",
Members = {
new MethodDeclaration {
ReturnType = new SimpleType("T"),
@ -192,6 +193,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -192,6 +193,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
",
new TypeDeclaration {
ClassType = ClassType.Interface,
Name = "MyInterface",
Members = {
new MethodDeclaration {
ReturnType = new PrimitiveType("void"),

2
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -197,7 +197,7 @@ @@ -197,7 +197,7 @@
<Compile Include="TypeSystem\IVariable.cs" />
<Compile Include="TypeSystem\PointerType.cs" />
<Compile Include="TypeSystem\ReflectionHelper.cs" />
<Compile Include="TypeSystem\SharedTypes.cs" />
<Compile Include="TypeSystem\SpecialType.cs" />
<Compile Include="Utils\7BitEncodedInts.cs" />
<Compile Include="Utils\BitVector16.cs" />
<Compile Include="Utils\BusyManager.cs" />

0
ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs → ICSharpCode.NRefactory/TypeSystem/SpecialType.cs

Loading…
Cancel
Save