Browse Source

Improved CodeDomConvertVisitor.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
bf6217d038
  1. 121
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  2. 4
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  3. 376
      ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs

121
ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -21,12 +21,12 @@ using System.CodeDom; @@ -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 @@ -40,14 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp
{
//ICompilation compilation = MinimalResolveContext.Instance;
CSharpAstResolver resolver;
bool useFullyQualifiedTypeNames;
/// <summary>
/// Gets/Sets whether the visitor should use fully-qualified type references.
/// </summary>
public bool UseFullyQualifiedTypeNames {
get { return useFullyQualifiedTypeNames; }
set { useFullyQualifiedTypeNames = value; }
public bool UseFullyQualifiedTypeNames { get; set; }
/// <summary>
/// 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.
/// </summary>
public bool AllowSnippetNodes { get; set; }
public CodeDomConvertVisitor()
{
this.AllowSnippetNodes = true;
}
/// <summary>
@ -136,7 +145,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -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 @@ -148,6 +165,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
List<CodeStatement> result = new List<CodeStatement>();
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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -658,7 +681,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -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 @@ -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 @@ -809,7 +834,12 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitEmptyStatement(EmptyStatement emptyStatement)
{
return null;
return EmptyStatement();
}
CodeStatement EmptyStatement()
{
return new CodeExpressionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(object))));
}
CodeObject IAstVisitor<CodeObject>.VisitExpressionStatement(ExpressionStatement expressionStatement)
@ -817,10 +847,55 @@ namespace ICSharpCode.NRefactory.CSharp @@ -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<CodeObject>.VisitFixedStatement(FixedStatement fixedStatement)
{
return MakeSnippetStatement(fixedStatement);
@ -956,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -956,7 +1031,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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<CodeObject>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
@ -977,7 +1052,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -977,7 +1052,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -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 @@ -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 @@ -1048,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -1069,7 +1144,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -1087,7 +1162,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -1129,7 +1204,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -1181,7 +1256,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.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 @@ -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 @@ -1309,7 +1384,7 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, Pattern pattern)
{
return null;
}

4
ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -3750,7 +3750,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -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 @@ -3758,7 +3758,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (ae != null)
return ae.Right;
}
return null;
return Expression.Null;
}
/// <summary>

376
ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs

@ -20,11 +20,11 @@ using System; @@ -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 @@ -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<CSharpCodeProvider, CodeObject, TextWriter, CodeGeneratorOptions> 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<string>.Enumerator)",
ConvertExpression("default(List<string>.Enumerator)"));
convertVisitor.UseFullyQualifiedTypeNames = false;
Assert.AreEqual("default(List<string>.Enumerator)",
ConvertExpression("default(List<string>.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<string>[] { new System.Collections.Generic.List<string>()}",
ConvertExpression("new [] { new List<string>() }"));
}
[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<string>", ConvertExpression("this.Stuff<string>"));
Assert.AreEqual("this.Stuff<string>", ConvertExpression("Stuff<string>"));
}
[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
}
}

Loading…
Cancel
Save