diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
index 53584eef08..b8e94dcfb5 100644
--- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
@@ -21,12 +21,12 @@ using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp
{
@@ -40,14 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp
{
//ICompilation compilation = MinimalResolveContext.Instance;
CSharpAstResolver resolver;
- bool useFullyQualifiedTypeNames;
///
/// Gets/Sets whether the visitor should use fully-qualified type references.
///
- public bool UseFullyQualifiedTypeNames {
- get { return useFullyQualifiedTypeNames; }
- set { useFullyQualifiedTypeNames = value; }
+ public bool UseFullyQualifiedTypeNames { get; set; }
+
+ ///
+ /// Gets whether the visitor is allowed to produce snippet nodes for
+ /// code that cannot be converted.
+ /// The default is true. If this property is set to false,
+ /// unconvertible code will throw a NotSupportedException.
+ ///
+ public bool AllowSnippetNodes { get; set; }
+
+ public CodeDomConvertVisitor()
+ {
+ this.AllowSnippetNodes = true;
}
///
@@ -136,7 +145,15 @@ namespace ICSharpCode.NRefactory.CSharp
CodeTypeReference Convert(IType type)
{
- return new CodeTypeReference(type.ReflectionName);
+ if (type.Kind == TypeKind.Array) {
+ ArrayType a = (ArrayType)type;
+ return new CodeTypeReference(Convert(a.ElementType), a.Dimensions);
+ } else if (type is ParameterizedType) {
+ var pt = (ParameterizedType)type;
+ return new CodeTypeReference(pt.GetDefinition().ReflectionName, pt.TypeArguments.Select(Convert).ToArray());
+ } else {
+ return new CodeTypeReference(type.ReflectionName);
+ }
}
CodeStatement Convert(Statement stmt)
@@ -148,6 +165,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
List result = new List();
foreach (Statement stmt in block.Statements) {
+ if (stmt is EmptyStatement)
+ continue;
CodeStatement s = Convert(stmt);
if (s != null)
result.Add(s);
@@ -160,6 +179,8 @@ namespace ICSharpCode.NRefactory.CSharp
BlockStatement block = embeddedStatement as BlockStatement;
if (block != null) {
return ConvertBlock(block);
+ } else if (embeddedStatement is EmptyStatement) {
+ return new CodeStatement[0];
}
CodeStatement s = Convert(embeddedStatement);
if (s != null)
@@ -170,6 +191,8 @@ namespace ICSharpCode.NRefactory.CSharp
string MakeSnippet(AstNode node)
{
+ if (!AllowSnippetNodes)
+ throw new NotSupportedException();
StringWriter w = new StringWriter();
CSharpOutputVisitor v = new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ());
node.AcceptVisitor(v);
@@ -371,7 +394,7 @@ namespace ICSharpCode.NRefactory.CSharp
TypeResolveResult trr = rr as TypeResolveResult;
if (trr != null) {
CodeTypeReference typeRef;
- if (useFullyQualifiedTypeNames) {
+ if (UseFullyQualifiedTypeNames) {
typeRef = Convert(trr.Type);
} else {
typeRef = new CodeTypeReference(identifierExpression.Identifier);
@@ -380,7 +403,7 @@ namespace ICSharpCode.NRefactory.CSharp
return new CodeTypeReferenceExpression(typeRef);
}
MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
- if (mgrr != null) {
+ if (mgrr != null || identifierExpression.TypeArguments.Any()) {
return new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), identifierExpression.Identifier, Convert(identifierExpression.TypeArguments));
}
return new CodeVariableReferenceExpression(identifierExpression.Identifier);
@@ -658,7 +681,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
{
CodeTypeDelegate d = new CodeTypeDelegate(delegateDeclaration.Name);
- d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers);
+ d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers, EntityType.TypeDefinition);
d.CustomAttributes.AddRange(Convert(delegateDeclaration.Attributes));
d.ReturnType = Convert(delegateDeclaration.ReturnType);
d.Parameters.AddRange(Convert(delegateDeclaration.Parameters));
@@ -666,13 +689,15 @@ namespace ICSharpCode.NRefactory.CSharp
return d;
}
- static MemberAttributes ConvertMemberAttributes(Modifiers modifiers)
+ MemberAttributes ConvertMemberAttributes(Modifiers modifiers, EntityType entityType)
{
MemberAttributes a = 0;
if ((modifiers & Modifiers.Abstract) != 0)
a |= MemberAttributes.Abstract;
if ((modifiers & Modifiers.Sealed) != 0)
a |= MemberAttributes.Final;
+ if (entityType != EntityType.TypeDefinition && (modifiers & (Modifiers.Abstract | Modifiers.Override | Modifiers.Virtual)) == 0)
+ a |= MemberAttributes.Final;
if ((modifiers & Modifiers.Static) != 0)
a |= MemberAttributes.Static;
if ((modifiers & Modifiers.Override) != 0)
@@ -719,7 +744,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
//bool isNestedType = typeStack.Count > 0;
CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name);
- typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers);
+ typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers, EntityType.TypeDefinition);
typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes));
switch (typeDeclaration.ClassType) {
@@ -809,7 +834,12 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitEmptyStatement(EmptyStatement emptyStatement)
{
- return null;
+ return EmptyStatement();
+ }
+
+ CodeStatement EmptyStatement()
+ {
+ return new CodeExpressionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(object))));
}
CodeObject IAstVisitor.VisitExpressionStatement(ExpressionStatement expressionStatement)
@@ -817,10 +847,55 @@ namespace ICSharpCode.NRefactory.CSharp
AssignmentExpression assignment = expressionStatement.Expression as AssignmentExpression;
if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign) {
return new CodeAssignStatement(Convert(assignment.Left), Convert(assignment.Right));
+ } else if (assignment != null && CanBeDuplicatedForCompoundAssignment(assignment.Left)) {
+ CodeBinaryOperatorType op;
+ switch (assignment.Operator) {
+ case AssignmentOperatorType.Add:
+ op = CodeBinaryOperatorType.Add;
+ break;
+ case AssignmentOperatorType.Subtract:
+ op = CodeBinaryOperatorType.Subtract;
+ break;
+ case AssignmentOperatorType.Multiply:
+ op = CodeBinaryOperatorType.Multiply;
+ break;
+ case AssignmentOperatorType.Divide:
+ op = CodeBinaryOperatorType.Divide;
+ break;
+ case AssignmentOperatorType.Modulus:
+ op = CodeBinaryOperatorType.Modulus;
+ break;
+ case AssignmentOperatorType.BitwiseAnd:
+ op = CodeBinaryOperatorType.BitwiseAnd;
+ break;
+ case AssignmentOperatorType.BitwiseOr:
+ op = CodeBinaryOperatorType.BitwiseOr;
+ break;
+ default:
+ return MakeSnippetStatement(expressionStatement);
+ }
+ var cboe = new CodeBinaryOperatorExpression(Convert(assignment.Left), op, Convert(assignment.Right));
+ return new CodeAssignStatement(Convert(assignment.Left), cboe);
+ }
+ UnaryOperatorExpression unary = expressionStatement.Expression as UnaryOperatorExpression;
+ if (unary != null && CanBeDuplicatedForCompoundAssignment(unary.Expression)) {
+ var op = unary.Operator;
+ if (op == UnaryOperatorType.Increment || op == UnaryOperatorType.PostIncrement) {
+ var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1));
+ return new CodeAssignStatement(Convert(unary.Expression), cboe);
+ } else if (op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostDecrement) {
+ var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Subtract, new CodePrimitiveExpression(1));
+ return new CodeAssignStatement(Convert(unary.Expression), cboe);
+ }
}
return new CodeExpressionStatement(Convert(expressionStatement.Expression));
}
+ bool CanBeDuplicatedForCompoundAssignment(Expression expr)
+ {
+ return expr is IdentifierExpression;
+ }
+
CodeObject IAstVisitor.VisitFixedStatement(FixedStatement fixedStatement)
{
return MakeSnippetStatement(fixedStatement);
@@ -956,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitWhileStatement(WhileStatement whileStatement)
{
- return new CodeIterationStatement(null, Convert(whileStatement.Condition), null, ConvertEmbeddedStatement(whileStatement.EmbeddedStatement));
+ return new CodeIterationStatement(EmptyStatement(), Convert(whileStatement.Condition), EmptyStatement(), ConvertEmbeddedStatement(whileStatement.EmbeddedStatement));
}
CodeObject IAstVisitor.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
@@ -977,7 +1052,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
CodeConstructor ctor = new CodeConstructor();
- ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers);
+ ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers, EntityType.Constructor);
ctor.CustomAttributes.AddRange(Convert(constructorDeclaration.Attributes));
if (constructorDeclaration.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) {
ctor.ChainedConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments));
@@ -1019,7 +1094,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
CodeMemberEvent e = new CodeMemberEvent();
- e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers);
+ e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers, EntityType.Event);
e.CustomAttributes.AddRange(Convert(eventDeclaration.Attributes));
e.Name = vi.Name;
e.Type = Convert(eventDeclaration.ReturnType);
@@ -1037,7 +1112,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
foreach (VariableInitializer vi in fieldDeclaration.Variables) {
CodeMemberField f = new CodeMemberField(Convert(fieldDeclaration.ReturnType), vi.Name);
- f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers);
+ f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers, EntityType.Field);
f.CustomAttributes.AddRange(Convert(fieldDeclaration.Attributes));
f.InitExpression = ConvertVariableInitializer(vi.Initializer, fieldDeclaration.ReturnType);
AddTypeMember(f);
@@ -1048,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
{
CodeMemberProperty p = new CodeMemberProperty();
- p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers);
+ p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers, EntityType.Indexer);
p.CustomAttributes.AddRange(Convert(indexerDeclaration.Attributes));
p.Name = "Items";
p.PrivateImplementationType = Convert(indexerDeclaration.PrivateImplementationType);
@@ -1069,7 +1144,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
CodeMemberMethod m = new CodeMemberMethod();
- m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers);
+ m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers, EntityType.Method);
m.CustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
m.ReturnTypeCustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
@@ -1087,7 +1162,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
{
CodeMemberMethod m = new CodeMemberMethod();
- m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers);
+ m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers, EntityType.Method);
m.CustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
m.ReturnTypeCustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
@@ -1129,7 +1204,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
CodeMemberProperty p = new CodeMemberProperty();
- p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers);
+ p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers, EntityType.Property);
p.CustomAttributes.AddRange(Convert(propertyDeclaration.Attributes));
p.Name = propertyDeclaration.Name;
p.PrivateImplementationType = Convert(propertyDeclaration.PrivateImplementationType);
@@ -1181,7 +1256,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor.VisitSimpleType(SimpleType simpleType)
{
- if (useFullyQualifiedTypeNames) {
+ if (UseFullyQualifiedTypeNames) {
IType type = Resolve(simpleType).Type;
if (type.Kind != TypeKind.Unknown)
return Convert(type);
@@ -1198,7 +1273,7 @@ namespace ICSharpCode.NRefactory.CSharp
tr.TypeArguments.AddRange(Convert(memberType.TypeArguments));
return tr;
}
- if (useFullyQualifiedTypeNames || memberType.IsDoubleColon) {
+ if (UseFullyQualifiedTypeNames || memberType.IsDoubleColon) {
IType type = Resolve(memberType).Type;
if (type.Kind != TypeKind.Unknown)
return Convert(type);
@@ -1309,7 +1384,7 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
- CodeObject IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
+ CodeObject IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, Pattern pattern)
{
return null;
}
diff --git a/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
index 8d750b714c..3f2c274438 100644
--- a/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
+++ b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
@@ -3750,7 +3750,7 @@ namespace ICSharpCode.NRefactory.CSharp
return AstType.Null;
}
- public AstNode ParseExpression (TextReader reader)
+ public Expression ParseExpression (TextReader reader)
{
var es = ParseStatements (new StringReader ("tmp = " + Environment.NewLine + reader.ReadToEnd () + ";"), -1).FirstOrDefault () as ExpressionStatement;
if (es != null) {
@@ -3758,7 +3758,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (ae != null)
return ae.Right;
}
- return null;
+ return Expression.Null;
}
///
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
index 92efb0f156..52d55315bd 100644
--- a/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
+++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
@@ -20,11 +20,11 @@ using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
+using System.Linq;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Microsoft.CSharp;
using NUnit.Framework;
@@ -45,138 +45,388 @@ namespace ICSharpCode.NRefactory.CSharp
parsedFile.RootUsingScope.Usings.Add(MakeReference("System.Linq"));
convertVisitor = new CodeDomConvertVisitor();
+ convertVisitor.AllowSnippetNodes = false;
convertVisitor.UseFullyQualifiedTypeNames = true;
}
- string Convert(Expression expr)
+ #region Helper methods
+ string ConvertHelper(AstNode node, Action action)
{
CSharpResolver resolver = new CSharpResolver(compilation);
resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(compilation));
resolver = resolver.WithCurrentTypeDefinition(compilation.FindType(KnownTypeCode.Object).GetDefinition());
- var codeExpr = (CodeExpression)convertVisitor.Convert(expr, new CSharpAstResolver(resolver, expr, parsedFile));
+ var codeObj = convertVisitor.Convert(node, new CSharpAstResolver(resolver, node));
StringWriter writer = new StringWriter();
writer.NewLine = " ";
- new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " });
- return Regex.Replace(writer.ToString(), @"\s+", " ");
+ action(new CSharpCodeProvider(), codeObj, writer, new CodeGeneratorOptions { IndentString = " " });
+ return Regex.Replace(writer.ToString(), @"\s+", " ").Trim();
}
+ string ConvertExpression(Expression expr)
+ {
+ return ConvertHelper(expr, (p,obj,w,opt) => p.GenerateCodeFromExpression((CodeExpression)obj, w, opt));
+ }
+
+ string ConvertExpression(string code)
+ {
+ CSharpParser parser = new CSharpParser();
+ var expr = parser.ParseExpression(new StringReader(code));
+ Assert.IsFalse(parser.HasErrors);
+ return ConvertExpression(expr);
+ }
+
+ string ConvertStatement(Statement statement)
+ {
+ return ConvertHelper(statement, (p,obj,w,opt) => p.GenerateCodeFromStatement((CodeStatement)obj, w, opt));
+ }
+
+ string ConvertStatement(string code)
+ {
+ CSharpParser parser = new CSharpParser();
+ var expr = parser.ParseStatements(new StringReader(code)).Single();
+ Assert.IsFalse(parser.HasErrors);
+ return ConvertStatement(expr);
+ }
+
+ string ConvertMember(EntityDeclaration entity)
+ {
+ return ConvertHelper(entity, (p,obj,w,opt) => p.GenerateCodeFromMember((CodeTypeMember)obj, w, opt));
+ }
+
+ string ConvertMember(string code)
+ {
+ CSharpParser parser = new CSharpParser();
+ var expr = parser.ParseTypeMembers(new StringReader(code)).Single();
+ Assert.IsFalse(parser.HasErrors);
+ return ConvertMember(expr);
+ }
+
+ string ConvertTypeDeclaration(EntityDeclaration decl)
+ {
+ return ConvertHelper(decl, (p,obj,w,opt) => p.GenerateCodeFromType((CodeTypeDeclaration)obj, w, opt));
+ }
+
+ string ConvertTypeDeclaration(string code)
+ {
+ CSharpParser parser = new CSharpParser();
+ var cu = parser.Parse(new StringReader(code), "program.cs");
+ Assert.IsFalse(parser.HasErrors);
+ return ConvertTypeDeclaration((EntityDeclaration)cu.Children.Single());
+ }
+ #endregion
+
+ #region Type References
[Test]
- public void CreateArray()
+ public void MultidimensionalArrayTypeReference()
{
- Assert.AreEqual("new int[10]", Convert(
- new ArrayCreateExpression {
- Type = new PrimitiveType("int"),
- Arguments = { new PrimitiveExpression(10) }
- }));
+ Assert.AreEqual("default(int[,][])", ConvertExpression("default(int[,][])"));
}
[Test]
- public void CreateJaggedArray()
+ public void NestedTypeInGenericType()
{
- Assert.AreEqual("new int[10][]", Convert(
- new ArrayCreateExpression {
- Type = new PrimitiveType("int"),
- Arguments = { new PrimitiveExpression(10) },
- AdditionalArraySpecifiers = { new ArraySpecifier() }
- }));
+ Assert.AreEqual("default(System.Collections.Generic.List.Enumerator)",
+ ConvertExpression("default(List.Enumerator)"));
+ convertVisitor.UseFullyQualifiedTypeNames = false;
+ Assert.AreEqual("default(List.Enumerator)",
+ ConvertExpression("default(List.Enumerator)"));
}
+ #endregion
+ #region Arrays
[Test]
+ public void CreateArray()
+ {
+ Assert.AreEqual("new int[10]", ConvertExpression("new int[10]"));
+ }
+
+ [Test, ExpectedException(typeof(NotSupportedException))]
+ public void CreateJaggedArray()
+ {
+ ConvertExpression("new int[10][]");
+ }
+
+ [Test, ExpectedException(typeof(NotSupportedException))]
public void Create2DArray()
{
- Assert.AreEqual("new int[10, 20]", Convert(
- new ArrayCreateExpression {
- Type = new PrimitiveType("int"),
- Arguments = { new PrimitiveExpression(10), new PrimitiveExpression(20) }
- }));
+ ConvertExpression("new int[10, 20]");
}
[Test]
public void CreateImplicitlyTypedArray()
{
// implicitly-typed array not supported in CodeDom, so the conversion should infer the type
- Assert.AreEqual("new int[] { 1, 2, 3}", Convert(
- new ArrayCreateExpression {
- AdditionalArraySpecifiers = { new ArraySpecifier() },
- Initializer = new ArrayInitializerExpression {
- Elements = {
- new PrimitiveExpression(1),
- new PrimitiveExpression(2),
- new PrimitiveExpression(3)
- }
- }
- }));
+ Assert.AreEqual("new int[] { 1, 2, 3}", ConvertExpression("new [] { 1, 2, 3 }"));
+ Assert.AreEqual("new System.Collections.Generic.List[] { new System.Collections.Generic.List()}",
+ ConvertExpression("new [] { new List() }"));
}
- [Test]
+ [Test, ExpectedException(typeof(NotSupportedException))]
public void Create2DImplicitlyTypedArray()
{
- Assert.AreEqual("new int[,] { { 1, 2 }, { 3, 4 }}", Convert(
- new ArrayCreateExpression {
- AdditionalArraySpecifiers = { new ArraySpecifier(2) },
- Initializer = new ArrayInitializerExpression {
- Elements = {
- new ArrayInitializerExpression(new PrimitiveExpression(1), new PrimitiveExpression(2)),
- new ArrayInitializerExpression(new PrimitiveExpression(3), new PrimitiveExpression(4))
- }
- }
- }));
+ ConvertExpression("new [,] { { 1, 2 }, { 3, 4 }}");
}
+ #endregion
+ #region Operators
[Test]
- public void AdditionOperator()
+ public void ArithmeticOperators()
{
- Assert.AreEqual("(0 + 1)", Convert(
- new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Add, new PrimitiveExpression(1))));
+ Assert.AreEqual("(0 + 1)", ConvertExpression("0 + 1"));
+ Assert.AreEqual("(0 - 1)", ConvertExpression("0 - 1"));
+ Assert.AreEqual("(0 * 1)", ConvertExpression("0 * 1"));
+ Assert.AreEqual("(0 / 1)", ConvertExpression("0 / 1"));
+ Assert.AreEqual("(0 % 1)", ConvertExpression("0 % 1"));
+ Assert.AreEqual("(0 & 1)", ConvertExpression("0 & 1"));
+ Assert.AreEqual("(0 | 1)", ConvertExpression("0 | 1"));
+ Assert.AreEqual("(0 < 1)", ConvertExpression("0 < 1"));
+ Assert.AreEqual("(0 > 1)", ConvertExpression("0 > 1"));
+ Assert.AreEqual("(0 <= 1)", ConvertExpression("0 <= 1"));
+ Assert.AreEqual("(0 >= 1)", ConvertExpression("0 >= 1"));
+ Assert.AreEqual("(true && false)", ConvertExpression("true && false"));
+ Assert.AreEqual("(true || false)", ConvertExpression("true || false"));
}
[Test]
public void EqualityOperator()
{
- Assert.AreEqual("(0 == 1)", Convert(
- new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Equality, new PrimitiveExpression(1))));
+ Assert.AreEqual("(0 == 1)", ConvertExpression("0 == 1"));
+ Assert.AreEqual("(default(object) == null)", ConvertExpression("default(object) == null"));
}
[Test]
public void InEqualityOperator()
{
- Assert.AreEqual("((0 == 1) == false)", Convert(
- new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.InEquality, new PrimitiveExpression(1))));
+ Assert.AreEqual("((0 == 1) == false)", ConvertExpression("0 != 1"));
+ Assert.AreEqual("(default(object) != null)", ConvertExpression("default(object) != null"));
}
[Test]
- public void ReferenceInEqualityOperator()
+ public void UnaryOperators()
{
- Assert.AreEqual("(default(object) != null)", Convert(
- new BinaryOperatorExpression(new DefaultValueExpression(new PrimitiveType("object")), BinaryOperatorType.InEquality, new NullReferenceExpression())));
+ Assert.AreEqual("(a == false)", ConvertExpression("!a"));
+ Assert.AreEqual("(0 - a)", ConvertExpression("-a"));
+ Assert.AreEqual("a", ConvertExpression("+a"));
}
+ [Test]
+ public void Cast()
+ {
+ Assert.AreEqual("((double)(0))", ConvertExpression("(double)0"));
+ }
+ #endregion
+
+ #region Member Access
[Test]
public void StaticProperty()
{
- Assert.AreEqual("System.Environment.TickCount", Convert(
- new IdentifierExpression("Environment").Member("TickCount")));
+ Assert.AreEqual("System.Environment.TickCount", ConvertExpression("Environment.TickCount"));
}
[Test]
public void InstanceMethodInvocation()
{
- Assert.AreEqual("this.Equals(null)",
- Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression())));
+ Assert.AreEqual("this.Equals(null)", ConvertExpression("Equals(null)"));
}
[Test]
public void StaticMethodInvocation()
{
- Assert.AreEqual("object.Equals(null, null)",
- Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression(), new NullReferenceExpression())));
+ Assert.AreEqual("object.Equals(null, null)", ConvertExpression("Equals(null, null)"));
+ }
+
+ [Test]
+ public void BaseMemberAccess()
+ {
+ Assert.AreEqual("base.X", ConvertExpression("base.X"));
+ Assert.AreEqual("base[i]", ConvertExpression("base[i]"));
+ }
+
+ [Test]
+ public void GenericMethodReference()
+ {
+ Assert.AreEqual("this.Stuff", ConvertExpression("this.Stuff"));
+ Assert.AreEqual("this.Stuff", ConvertExpression("Stuff"));
+ }
+
+ [Test]
+ public void ByReferenceCall()
+ {
+ Assert.AreEqual("a.Call(ref x, out y, z)", ConvertExpression("a.Call(ref x, out y, z)"));
+ }
+
+ [Test]
+ public void MemberAccessOnType()
+ {
+ Assert.AreEqual("string.Empty", ConvertExpression("string.Empty"));
+ }
+ #endregion
+
+ #region Statements
+ [Test]
+ public void MethodInvocationStatement()
+ {
+ Assert.AreEqual("a.SomeMethod();", ConvertStatement("a.SomeMethod();"));
+ }
+
+ [Test]
+ public void Assignment()
+ {
+ Assert.AreEqual("a = 1;", ConvertStatement("a = 1;"));
+ }
+
+ [Test, ExpectedException(typeof(NotSupportedException))]
+ public void AssignmentNotSupportedInExpression()
+ {
+ ConvertStatement("a = b = 1;");
+ }
+
+ [Test]
+ public void BlockStatement()
+ {
+ Assert.AreEqual("if (true) { a = 1; b = 2; }",
+ ConvertStatement("{ a = 1; b = 2; }"));
+ }
+
+ [Test]
+ public void CompoundAssign()
+ {
+ Assert.AreEqual("a = (a + 1);", ConvertStatement("a += 1;"));
+ Assert.AreEqual("a = (a - 1);", ConvertStatement("a -= 1;"));
+ Assert.AreEqual("a = (a * 1);", ConvertStatement("a *= 1;"));
+ Assert.AreEqual("a = (a / 1);", ConvertStatement("a /= 1;"));
+ Assert.AreEqual("a = (a % 1);", ConvertStatement("a %= 1;"));
+ Assert.AreEqual("a = (a & 1);", ConvertStatement("a &= 1;"));
+ Assert.AreEqual("a = (a | 1);", ConvertStatement("a |= 1;"));
+ }
+
+ [Test]
+ public void Increment()
+ {
+ Assert.AreEqual("a = (a + 1);", ConvertStatement("a++;"));
+ Assert.AreEqual("a = (a + 1);", ConvertStatement("++a;"));
+ Assert.AreEqual("a = (a - 1);", ConvertStatement("a--;"));
+ Assert.AreEqual("a = (a - 1);", ConvertStatement("--a;"));
+ }
+
+ [Test]
+ public void ForLoop()
+ {
+ Assert.AreEqual("for (int i = 0; (i < 10); i = (i + 1)) { }",
+ ConvertStatement("for (int i = 0; i < 10; i++) {}"));
+ }
+
+ [Test]
+ public void WhileLoop()
+ {
+ Assert.AreEqual("for (new object(); (i < 10); new object()) { }",
+ ConvertStatement("while (i < 10);"));
+ }
+
+ [Test]
+ public void VariableDeclarationWithArrayInitializer()
+ {
+ Assert.AreEqual("int[] nums = new int[] { 1, 2};",
+ ConvertStatement("int[] nums = { 1, 2 };"));
+ }
+
+ [Test]
+ public void TryCatch()
+ {
+ Assert.AreEqual("try { a = 1; } catch (System.Exception ex) { ex.ToString(); }",
+ ConvertStatement("try { a = 1; } catch (Exception ex) { ex.ToString(); }"));
+ }
+
+ [Test]
+ public void TryEmptyCatch()
+ {
+ Assert.AreEqual("try { a = 1; } catch (System.Exception ) { }",
+ ConvertStatement("try { a = 1; } catch (Exception) { }"));
+ }
+
+ [Test]
+ public void TryFinally()
+ {
+ Assert.AreEqual("try { a = 1; } finally { a = 0; }",
+ ConvertStatement("try { a = 1; } finally { a = 0; }"));
+ }
+ #endregion
+
+ #region Type Members
+ [Test]
+ public void MethodParameterNamedValue()
+ {
+ Assert.AreEqual("void M(string value) { System.Console.WriteLine(value); }",
+ ConvertMember("void M(string value) { Console.WriteLine(value); }"));
+ }
+
+ [Test]
+ public void ValueInProperty()
+ {
+ Assert.AreEqual("string P { set { System.Console.WriteLine(value); } }",
+ ConvertMember("string P { set { Console.WriteLine(value); } }"));
+ }
+
+ [Test]
+ public void MethodWithAttribute()
+ {
+ Assert.AreEqual("[Test()] void MethodWithAttribute() { }",
+ ConvertMember("[Test] void MethodWithAttribute() { }"));
+ }
+
+ [Test]
+ public void PublicNonVirtualMethod()
+ {
+ Assert.AreEqual("public void Method() { }",
+ ConvertMember("public void Method() { }"));
+ }
+
+ [Test]
+ public void PublicVirtualMethod()
+ {
+ Assert.AreEqual("public virtual void Method() { }",
+ ConvertMember("public virtual void Method() { }"));
+ }
+
+ [Test]
+ public void NestedClass()
+ {
+ Assert.AreEqual("public class Outer { public class Inner { } }",
+ ConvertTypeDeclaration("class Outer { class Inner { } }"));
+ }
+
+ [Test]
+ public void Constructor()
+ {
+ string code = "public class Test : Base { public Test(string x) : base(x) { } }";
+ Assert.AreEqual(code, ConvertTypeDeclaration(code));
+ }
+
+ [Test]
+ public void Enum()
+ {
+ string code = "public enum E { [Description(\"Text\")] None, B = 2, }";
+ Assert.AreEqual(code, ConvertTypeDeclaration(code));
+ }
+
+ [Test]
+ public void Field()
+ {
+ Assert.AreEqual("public class X {" +
+ " int A;" +
+ " int B; }",
+ ConvertMember("public class X { int A, B; }"));
}
[Test]
- public void NotOperator()
+ public void Event()
{
- Assert.AreEqual("(a == false)", Convert(new UnaryOperatorExpression(UnaryOperatorType.Not, new IdentifierExpression("a"))));
+ Assert.AreEqual("public class X {" +
+ " protected event System.EventHandler A;" +
+ " protected event System.EventHandler B; }",
+ ConvertMember("public class X { protected event EventHandler A, B; }"));
}
+ #endregion
}
}