mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1397 lines
51 KiB
1397 lines
51 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
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; |
|
|
|
namespace ICSharpCode.NRefactory.CSharp |
|
{ |
|
/// <summary> |
|
/// Converts from C# AST to CodeDom. |
|
/// </summary> |
|
/// <remarks> |
|
/// The conversion is intended for use in the SharpDevelop forms designer. |
|
/// </remarks> |
|
public class CodeDomConvertVisitor : IAstVisitor<CodeObject> |
|
{ |
|
//ICompilation compilation = MinimalResolveContext.Instance; |
|
CSharpAstResolver resolver; |
|
|
|
/// <summary> |
|
/// Gets/Sets whether the visitor should use fully-qualified type references. |
|
/// </summary> |
|
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> |
|
/// Converts a syntax tree to CodeDom. |
|
/// </summary> |
|
/// <param name="syntaxTree">The input syntax tree.</param> |
|
/// <param name="compilation">The current compilation.</param> |
|
/// <param name="unresolvedFile">CSharpUnresolvedFile, used for resolving.</param> |
|
/// <returns>Converted CodeCompileUnit</returns> |
|
/// <remarks> |
|
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. |
|
/// </remarks> |
|
public CodeCompileUnit Convert(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile) |
|
{ |
|
if (syntaxTree == null) |
|
throw new ArgumentNullException("syntaxTree"); |
|
if (compilation == null) |
|
throw new ArgumentNullException("compilation"); |
|
|
|
CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile); |
|
return (CodeCompileUnit)Convert(syntaxTree, resolver); |
|
} |
|
|
|
/// <summary> |
|
/// Converts a C# AST node to CodeDom. |
|
/// </summary> |
|
/// <param name="node">The input node.</param> |
|
/// <param name="resolver">The AST resolver.</param> |
|
/// <returns>The node converted into CodeDom</returns> |
|
/// <remarks> |
|
/// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. |
|
/// </remarks> |
|
public CodeObject Convert(AstNode node, CSharpAstResolver resolver) |
|
{ |
|
if (node == null) |
|
throw new ArgumentNullException("node"); |
|
if (resolver == null) |
|
throw new ArgumentNullException("resolver"); |
|
try { |
|
this.resolver = resolver; |
|
return node.AcceptVisitor(this); |
|
} finally { |
|
this.resolver = null; |
|
} |
|
} |
|
|
|
ResolveResult Resolve(AstNode node) |
|
{ |
|
if (resolver == null) |
|
return ErrorResolveResult.UnknownError; |
|
else |
|
return resolver.Resolve(node); |
|
} |
|
|
|
CodeExpression Convert(Expression expr) |
|
{ |
|
return (CodeExpression)expr.AcceptVisitor(this); |
|
} |
|
|
|
CodeExpression[] Convert(IEnumerable<Expression> expressions) |
|
{ |
|
List<CodeExpression> result = new List<CodeExpression>(); |
|
foreach (Expression expr in expressions) { |
|
CodeExpression e = Convert(expr); |
|
if (e != null) |
|
result.Add(e); |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeTypeReference Convert(AstType type) |
|
{ |
|
return (CodeTypeReference)type.AcceptVisitor(this); |
|
} |
|
|
|
CodeTypeReference[] Convert(IEnumerable<AstType> types) |
|
{ |
|
List<CodeTypeReference> result = new List<CodeTypeReference>(); |
|
foreach (AstType type in types) { |
|
CodeTypeReference e = Convert(type); |
|
if (e != null) |
|
result.Add(e); |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeTypeReference Convert(IType type) |
|
{ |
|
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) |
|
{ |
|
return (CodeStatement)stmt.AcceptVisitor(this); |
|
} |
|
|
|
CodeStatement[] ConvertBlock(BlockStatement block) |
|
{ |
|
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); |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeStatement[] ConvertEmbeddedStatement(Statement embeddedStatement) |
|
{ |
|
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) |
|
return new CodeStatement[] { s }; |
|
else |
|
return new CodeStatement[0]; |
|
} |
|
|
|
string MakeSnippet(AstNode node) |
|
{ |
|
if (!AllowSnippetNodes) |
|
throw new NotSupportedException(); |
|
StringWriter w = new StringWriter(); |
|
CSharpOutputVisitor v = new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ()); |
|
node.AcceptVisitor(v); |
|
return w.ToString(); |
|
} |
|
|
|
/// <summary> |
|
/// Converts an expression by storing it as C# snippet. |
|
/// This is used for expressions that cannot be represented in CodeDom. |
|
/// </summary> |
|
CodeSnippetExpression MakeSnippetExpression(Expression expr) |
|
{ |
|
return new CodeSnippetExpression(MakeSnippet(expr)); |
|
} |
|
|
|
CodeSnippetStatement MakeSnippetStatement(Statement stmt) |
|
{ |
|
return new CodeSnippetStatement(MakeSnippet(stmt)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) |
|
{ |
|
return MakeSnippetExpression(anonymousMethodExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression) |
|
{ |
|
return MakeSnippetExpression(undocumentedExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression) |
|
{ |
|
CodeArrayCreateExpression ace = new CodeArrayCreateExpression(); |
|
int dimensions = arrayCreateExpression.Arguments.Count; |
|
int nestingDepth = arrayCreateExpression.AdditionalArraySpecifiers.Count; |
|
if (dimensions > 0) |
|
nestingDepth++; |
|
if (nestingDepth > 1 || dimensions > 1) { |
|
// CodeDom does not support jagged or multi-dimensional arrays |
|
return MakeSnippetExpression(arrayCreateExpression); |
|
} |
|
if (arrayCreateExpression.Type.IsNull) { |
|
ace.CreateType = Convert(Resolve(arrayCreateExpression).Type); |
|
} else { |
|
ace.CreateType = Convert(arrayCreateExpression.Type); |
|
} |
|
if (arrayCreateExpression.Arguments.Count == 1) { |
|
ace.SizeExpression = Convert(arrayCreateExpression.Arguments.Single()); |
|
} |
|
ace.Initializers.AddRange(Convert(arrayCreateExpression.Initializer.Elements)); |
|
return ace; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression) |
|
{ |
|
// Array initializers should be handled by the parent node |
|
return MakeSnippetExpression(arrayInitializerExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAsExpression(AsExpression asExpression) |
|
{ |
|
return MakeSnippetExpression(asExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAssignmentExpression(AssignmentExpression assignmentExpression) |
|
{ |
|
// assignments are only supported as statements, not as expressions |
|
return MakeSnippetExpression(assignmentExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression) |
|
{ |
|
return new CodeBaseReferenceExpression(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) |
|
{ |
|
CodeBinaryOperatorType op; |
|
switch (binaryOperatorExpression.Operator) { |
|
case BinaryOperatorType.BitwiseAnd: |
|
op = CodeBinaryOperatorType.BitwiseAnd; |
|
break; |
|
case BinaryOperatorType.BitwiseOr: |
|
op = CodeBinaryOperatorType.BitwiseOr; |
|
break; |
|
case BinaryOperatorType.ConditionalAnd: |
|
op = CodeBinaryOperatorType.BooleanAnd; |
|
break; |
|
case BinaryOperatorType.ConditionalOr: |
|
op = CodeBinaryOperatorType.BooleanOr; |
|
break; |
|
case BinaryOperatorType.GreaterThan: |
|
op = CodeBinaryOperatorType.GreaterThan; |
|
break; |
|
case BinaryOperatorType.GreaterThanOrEqual: |
|
op = CodeBinaryOperatorType.GreaterThanOrEqual; |
|
break; |
|
case BinaryOperatorType.LessThan: |
|
op = CodeBinaryOperatorType.LessThan; |
|
break; |
|
case BinaryOperatorType.LessThanOrEqual: |
|
op = CodeBinaryOperatorType.LessThanOrEqual; |
|
break; |
|
case BinaryOperatorType.Add: |
|
op = CodeBinaryOperatorType.Add; |
|
break; |
|
case BinaryOperatorType.Subtract: |
|
op = CodeBinaryOperatorType.Subtract; |
|
break; |
|
case BinaryOperatorType.Multiply: |
|
op = CodeBinaryOperatorType.Multiply; |
|
break; |
|
case BinaryOperatorType.Divide: |
|
op = CodeBinaryOperatorType.Divide; |
|
break; |
|
case BinaryOperatorType.Modulus: |
|
op = CodeBinaryOperatorType.Modulus; |
|
break; |
|
case BinaryOperatorType.Equality: |
|
case BinaryOperatorType.InEquality: |
|
OperatorResolveResult rr = Resolve(binaryOperatorExpression) as OperatorResolveResult; |
|
if (rr != null && rr.GetChildResults().Any(cr => cr.Type.IsReferenceType == true)) { |
|
if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) |
|
op = CodeBinaryOperatorType.IdentityEquality; |
|
else |
|
op = CodeBinaryOperatorType.IdentityInequality; |
|
} else { |
|
if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { |
|
op = CodeBinaryOperatorType.ValueEquality; |
|
} else { |
|
// CodeDom is retarded and does not support ValueInequality, so we'll simulate it using |
|
// ValueEquality and Not... but CodeDom doesn't have Not either, so we use |
|
// '(a == b) == false' |
|
return new CodeBinaryOperatorExpression( |
|
new CodeBinaryOperatorExpression( |
|
Convert(binaryOperatorExpression.Left), |
|
CodeBinaryOperatorType.ValueEquality, |
|
Convert(binaryOperatorExpression.Right) |
|
), |
|
CodeBinaryOperatorType.ValueEquality, |
|
new CodePrimitiveExpression(false) |
|
); |
|
} |
|
} |
|
break; |
|
default: |
|
// not supported: xor, shift, null coalescing |
|
return MakeSnippetExpression(binaryOperatorExpression); |
|
} |
|
return new CodeBinaryOperatorExpression(Convert(binaryOperatorExpression.Left), op, Convert(binaryOperatorExpression.Right)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCastExpression(CastExpression castExpression) |
|
{ |
|
return new CodeCastExpression(Convert(castExpression.Type), Convert(castExpression.Expression)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCheckedExpression(CheckedExpression checkedExpression) |
|
{ |
|
return MakeSnippetExpression(checkedExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitConditionalExpression(ConditionalExpression conditionalExpression) |
|
{ |
|
return MakeSnippetExpression(conditionalExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression) |
|
{ |
|
return new CodeDefaultValueExpression(Convert(defaultValueExpression.Type)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDirectionExpression(DirectionExpression directionExpression) |
|
{ |
|
System.CodeDom.FieldDirection direction; |
|
if (directionExpression.FieldDirection == FieldDirection.Out) { |
|
direction = System.CodeDom.FieldDirection.Out; |
|
} else { |
|
direction = System.CodeDom.FieldDirection.Ref; |
|
} |
|
return new CodeDirectionExpression(direction, Convert(directionExpression.Expression)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIdentifierExpression(IdentifierExpression identifierExpression) |
|
{ |
|
ResolveResult rr = Resolve(identifierExpression); |
|
LocalResolveResult lrr = rr as LocalResolveResult; |
|
if (lrr != null && lrr.IsParameter) { |
|
if (lrr.Variable.Name == "value" && identifierExpression.Ancestors.Any(a => a is Accessor)) { |
|
return new CodePropertySetValueReferenceExpression(); |
|
} else { |
|
return new CodeArgumentReferenceExpression(lrr.Variable.Name); |
|
} |
|
} |
|
MemberResolveResult mrr = rr as MemberResolveResult; |
|
if (mrr != null) { |
|
return HandleMemberReference(null, identifierExpression.Identifier, identifierExpression.TypeArguments, mrr); |
|
} |
|
TypeResolveResult trr = rr as TypeResolveResult; |
|
if (trr != null) { |
|
CodeTypeReference typeRef; |
|
if (UseFullyQualifiedTypeNames) { |
|
typeRef = Convert(trr.Type); |
|
} else { |
|
typeRef = new CodeTypeReference(identifierExpression.Identifier); |
|
typeRef.TypeArguments.AddRange(Convert(identifierExpression.TypeArguments)); |
|
} |
|
return new CodeTypeReferenceExpression(typeRef); |
|
} |
|
MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; |
|
if (mgrr != null || identifierExpression.TypeArguments.Any()) { |
|
return new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), identifierExpression.Identifier, Convert(identifierExpression.TypeArguments)); |
|
} |
|
return new CodeVariableReferenceExpression(identifierExpression.Identifier); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIndexerExpression(IndexerExpression indexerExpression) |
|
{ |
|
if (Resolve(indexerExpression) is ArrayAccessResolveResult) |
|
return new CodeArrayIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments)); |
|
else |
|
return new CodeIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitInvocationExpression(InvocationExpression invocationExpression) |
|
{ |
|
MemberResolveResult rr = Resolve(invocationExpression) as MemberResolveResult; |
|
CSharpInvocationResolveResult csRR = rr as CSharpInvocationResolveResult; |
|
if (csRR != null && csRR.IsDelegateInvocation) { |
|
return new CodeDelegateInvokeExpression(Convert(invocationExpression.Target), Convert(invocationExpression.Arguments)); |
|
} |
|
|
|
Expression methodExpr = invocationExpression.Target; |
|
while (methodExpr is ParenthesizedExpression) |
|
methodExpr = ((ParenthesizedExpression)methodExpr).Expression; |
|
CodeMethodReferenceExpression mr = null; |
|
MemberReferenceExpression mre = methodExpr as MemberReferenceExpression; |
|
if (mre != null) { |
|
mr = new CodeMethodReferenceExpression(Convert(mre.Target), mre.MemberName, Convert(mre.TypeArguments)); |
|
} |
|
IdentifierExpression id = methodExpr as IdentifierExpression; |
|
if (id != null) { |
|
CodeExpression target; |
|
if (rr != null && rr.Member.IsStatic) |
|
target = new CodeTypeReferenceExpression(Convert(rr.Member.DeclaringType)); |
|
else |
|
target = new CodeThisReferenceExpression(); |
|
|
|
mr = new CodeMethodReferenceExpression(target, id.Identifier, Convert(id.TypeArguments)); |
|
} |
|
if (mr != null) |
|
return new CodeMethodInvokeExpression(mr, Convert(invocationExpression.Arguments)); |
|
else |
|
return MakeSnippetExpression(invocationExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIsExpression(IsExpression isExpression) |
|
{ |
|
return MakeSnippetExpression(isExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitLambdaExpression(LambdaExpression lambdaExpression) |
|
{ |
|
return MakeSnippetExpression(lambdaExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) |
|
{ |
|
CodeExpression target = Convert(memberReferenceExpression.Target); |
|
ResolveResult rr = Resolve(memberReferenceExpression); |
|
MemberResolveResult mrr = rr as MemberResolveResult; |
|
if (mrr != null) { |
|
return HandleMemberReference(target, memberReferenceExpression.MemberName, memberReferenceExpression.TypeArguments, mrr); |
|
} else { |
|
if (memberReferenceExpression.TypeArguments.Any() || rr is MethodGroupResolveResult) { |
|
return new CodeMethodReferenceExpression(target, memberReferenceExpression.MemberName, Convert(memberReferenceExpression.TypeArguments)); |
|
} else { |
|
return new CodePropertyReferenceExpression(target, memberReferenceExpression.MemberName); |
|
} |
|
} |
|
} |
|
|
|
CodeExpression HandleMemberReference(CodeExpression target, string identifier, AstNodeCollection<AstType> typeArguments, MemberResolveResult mrr) |
|
{ |
|
if (target == null) { |
|
if (mrr.Member.IsStatic) |
|
target = new CodeTypeReferenceExpression(Convert(mrr.Member.DeclaringType)); |
|
else |
|
target = new CodeThisReferenceExpression(); |
|
} |
|
if (mrr.Member is IField) { |
|
return new CodeFieldReferenceExpression(target, identifier); |
|
} else if (mrr.Member is IMethod) { |
|
return new CodeMethodReferenceExpression(target, identifier, Convert(typeArguments)); |
|
} else if (mrr.Member is IEvent) { |
|
return new CodeEventReferenceExpression(target, identifier); |
|
} else { |
|
return new CodePropertyReferenceExpression(target, identifier); |
|
} |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression) |
|
{ |
|
return MakeSnippetExpression(namedArgumentExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitNamedExpression(NamedExpression namedExpression) |
|
{ |
|
return MakeSnippetExpression(namedExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression) |
|
{ |
|
return new CodePrimitiveExpression(null); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) |
|
{ |
|
if (!objectCreateExpression.Initializer.IsNull) |
|
return MakeSnippetExpression(objectCreateExpression); |
|
return new CodeObjectCreateExpression(Convert(objectCreateExpression.Type), Convert(objectCreateExpression.Arguments)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression) |
|
{ |
|
return MakeSnippetExpression(anonymousTypeCreateExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression) |
|
{ |
|
// CodeDom generators will insert parentheses where necessary |
|
return Convert(parenthesizedExpression.Expression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) |
|
{ |
|
return MakeSnippetExpression(pointerReferenceExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression) |
|
{ |
|
return new CodePrimitiveExpression(primitiveExpression.Value); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitSizeOfExpression(SizeOfExpression sizeOfExpression) |
|
{ |
|
return MakeSnippetExpression(sizeOfExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitStackAllocExpression(StackAllocExpression stackAllocExpression) |
|
{ |
|
return MakeSnippetExpression(stackAllocExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression) |
|
{ |
|
return new CodeThisReferenceExpression(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitTypeOfExpression(TypeOfExpression typeOfExpression) |
|
{ |
|
return new CodeTypeOfExpression(Convert(typeOfExpression.Type)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression) |
|
{ |
|
return new CodeTypeReferenceExpression(Convert(typeReferenceExpression.Type)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) |
|
{ |
|
switch (unaryOperatorExpression.Operator) { |
|
case UnaryOperatorType.Not: |
|
return new CodeBinaryOperatorExpression( |
|
Convert(unaryOperatorExpression.Expression), |
|
CodeBinaryOperatorType.ValueEquality, |
|
new CodePrimitiveExpression(false)); |
|
case UnaryOperatorType.Minus: |
|
return new CodeBinaryOperatorExpression( |
|
new CodePrimitiveExpression(0), |
|
CodeBinaryOperatorType.Subtract, |
|
Convert(unaryOperatorExpression.Expression)); |
|
case UnaryOperatorType.Plus: |
|
return Convert(unaryOperatorExpression.Expression); |
|
default: |
|
return MakeSnippetExpression(unaryOperatorExpression); |
|
} |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUncheckedExpression(UncheckedExpression uncheckedExpression) |
|
{ |
|
return MakeSnippetExpression(uncheckedExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitEmptyExpression(EmptyExpression emptyExpression) |
|
{ |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryExpression(QueryExpression queryExpression) |
|
{ |
|
return MakeSnippetExpression(queryExpression); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryFromClause(QueryFromClause queryFromClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryLetClause(QueryLetClause queryLetClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryWhereClause(QueryWhereClause queryWhereClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryJoinClause(QueryJoinClause queryJoinClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryOrderClause(QueryOrderClause queryOrderClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryOrdering(QueryOrdering queryOrdering) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQuerySelectClause(QuerySelectClause querySelectClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitQueryGroupClause(QueryGroupClause queryGroupClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAttribute(Attribute attribute) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAttributeSection(AttributeSection attributeSection) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeAttributeDeclaration Convert(Attribute attribute) |
|
{ |
|
var attr = new CodeAttributeDeclaration(Convert(attribute.Type)); |
|
foreach (Expression expr in attribute.Arguments) { |
|
NamedExpression ne = expr as NamedExpression; |
|
if (ne != null) |
|
attr.Arguments.Add(new CodeAttributeArgument(ne.Name, Convert(ne.Expression))); |
|
else |
|
attr.Arguments.Add(new CodeAttributeArgument(Convert(expr))); |
|
} |
|
return attr; |
|
} |
|
|
|
CodeAttributeDeclaration[] Convert(IEnumerable<AttributeSection> attributeSections) |
|
{ |
|
List<CodeAttributeDeclaration> result = new List<CodeAttributeDeclaration>(); |
|
foreach (AttributeSection section in attributeSections) { |
|
foreach (Attribute attr in section.Attributes) { |
|
CodeAttributeDeclaration attrDecl = Convert(attr); |
|
if (attrDecl != null) |
|
result.Add(attrDecl); |
|
} |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) |
|
{ |
|
CodeTypeDelegate d = new CodeTypeDelegate(delegateDeclaration.Name); |
|
d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers, EntityType.TypeDefinition); |
|
d.CustomAttributes.AddRange(Convert(delegateDeclaration.Attributes)); |
|
d.ReturnType = Convert(delegateDeclaration.ReturnType); |
|
d.Parameters.AddRange(Convert(delegateDeclaration.Parameters)); |
|
d.TypeParameters.AddRange(ConvertTypeParameters(delegateDeclaration.TypeParameters, delegateDeclaration.Constraints)); |
|
return d; |
|
} |
|
|
|
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) |
|
a |= MemberAttributes.Override; |
|
if ((modifiers & Modifiers.Const) != 0) |
|
a |= MemberAttributes.Const; |
|
if ((modifiers & Modifiers.New) != 0) |
|
a |= MemberAttributes.New; |
|
|
|
if ((modifiers & Modifiers.Public) != 0) |
|
a |= MemberAttributes.Public; |
|
else if ((modifiers & (Modifiers.Protected | Modifiers.Internal)) == (Modifiers.Protected | Modifiers.Internal)) |
|
a |= MemberAttributes.FamilyOrAssembly; |
|
else if ((modifiers & Modifiers.Protected) != 0) |
|
a |= MemberAttributes.Family; |
|
else if ((modifiers & Modifiers.Internal) != 0) |
|
a |= MemberAttributes.Assembly; |
|
else if ((modifiers & Modifiers.Private) != 0) |
|
a |= MemberAttributes.Private; |
|
|
|
return a; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) |
|
{ |
|
CodeNamespace ns = new CodeNamespace(namespaceDeclaration.Name); |
|
foreach (AstNode node in namespaceDeclaration.Members) { |
|
CodeObject r = node.AcceptVisitor(this); |
|
|
|
CodeNamespaceImport import = r as CodeNamespaceImport; |
|
if (import != null) |
|
ns.Imports.Add(import); |
|
|
|
CodeTypeDeclaration typeDecl = r as CodeTypeDeclaration; |
|
if (typeDecl != null) |
|
ns.Types.Add(typeDecl); |
|
} |
|
return ns; |
|
} |
|
|
|
Stack<CodeTypeDeclaration> typeStack = new Stack<CodeTypeDeclaration>(); |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitTypeDeclaration(TypeDeclaration typeDeclaration) |
|
{ |
|
//bool isNestedType = typeStack.Count > 0; |
|
CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name); |
|
typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers, EntityType.TypeDefinition); |
|
typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes)); |
|
|
|
switch (typeDeclaration.ClassType) { |
|
case ClassType.Struct: |
|
typeDecl.IsStruct = true; |
|
break; |
|
case ClassType.Interface: |
|
typeDecl.IsInterface = true; |
|
break; |
|
case ClassType.Enum: |
|
typeDecl.IsEnum = true; |
|
break; |
|
default: |
|
typeDecl.IsClass = true; |
|
break; |
|
} |
|
typeDecl.IsPartial = (typeDeclaration.Modifiers & Modifiers.Partial) == Modifiers.Partial; |
|
|
|
typeDecl.BaseTypes.AddRange(Convert(typeDeclaration.BaseTypes)); |
|
typeDecl.TypeParameters.AddRange(ConvertTypeParameters(typeDeclaration.TypeParameters, typeDeclaration.Constraints)); |
|
|
|
typeStack.Push(typeDecl); |
|
foreach (var member in typeDeclaration.Members) { |
|
CodeTypeMember m = member.AcceptVisitor(this) as CodeTypeMember; |
|
if (m != null) |
|
typeDecl.Members.Add(m); |
|
} |
|
typeStack.Pop(); |
|
return typeDecl; |
|
} |
|
|
|
void AddTypeMember(CodeTypeMember member) |
|
{ |
|
if (typeStack.Count != 0) |
|
typeStack.Peek().Members.Add(member); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration) |
|
{ |
|
return new CodeSnippetTypeMember(MakeSnippet(usingAliasDeclaration)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUsingDeclaration(UsingDeclaration usingDeclaration) |
|
{ |
|
return new CodeNamespaceImport(usingDeclaration.Namespace); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration) |
|
{ |
|
return new CodeSnippetTypeMember(MakeSnippet(externAliasDeclaration)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitBlockStatement(BlockStatement blockStatement) |
|
{ |
|
return new CodeConditionStatement(new CodePrimitiveExpression(true), ConvertBlock(blockStatement)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitBreakStatement(BreakStatement breakStatement) |
|
{ |
|
return MakeSnippetStatement(breakStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCheckedStatement(CheckedStatement checkedStatement) |
|
{ |
|
return MakeSnippetStatement(checkedStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitContinueStatement(ContinueStatement continueStatement) |
|
{ |
|
return MakeSnippetStatement(continueStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDoWhileStatement(DoWhileStatement doWhileStatement) |
|
{ |
|
// do { } while (expr); |
|
// |
|
// emulate with: |
|
// for (bool _do = true; _do; _do = expr) {} |
|
string varName = "_do" + doWhileStatement.Ancestors.OfType<DoWhileStatement>().Count(); |
|
return new CodeIterationStatement( |
|
new CodeVariableDeclarationStatement(typeof(bool), varName, new CodePrimitiveExpression(true)), |
|
new CodeVariableReferenceExpression(varName), |
|
new CodeAssignStatement(new CodeVariableReferenceExpression(varName), Convert(doWhileStatement.Condition)), |
|
ConvertEmbeddedStatement(doWhileStatement.EmbeddedStatement) |
|
); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitEmptyStatement(EmptyStatement emptyStatement) |
|
{ |
|
return EmptyStatement(); |
|
} |
|
|
|
CodeStatement EmptyStatement() |
|
{ |
|
return new CodeExpressionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(object)))); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitExpressionStatement(ExpressionStatement expressionStatement) |
|
{ |
|
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); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitForeachStatement(ForeachStatement foreachStatement) |
|
{ |
|
return MakeSnippetStatement(foreachStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitForStatement(ForStatement forStatement) |
|
{ |
|
if (forStatement.Initializers.Count != 1 || forStatement.Iterators.Count != 1) |
|
return MakeSnippetStatement(forStatement); |
|
return new CodeIterationStatement( |
|
Convert(forStatement.Initializers.Single()), |
|
Convert(forStatement.Condition), |
|
Convert(forStatement.Iterators.Single()), |
|
ConvertEmbeddedStatement(forStatement.EmbeddedStatement) |
|
); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement) |
|
{ |
|
return MakeSnippetStatement(gotoCaseStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement) |
|
{ |
|
return MakeSnippetStatement(gotoDefaultStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitGotoStatement(GotoStatement gotoStatement) |
|
{ |
|
return new CodeGotoStatement(gotoStatement.Label); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIfElseStatement(IfElseStatement ifElseStatement) |
|
{ |
|
return new CodeConditionStatement( |
|
Convert(ifElseStatement.Condition), |
|
ConvertEmbeddedStatement(ifElseStatement.TrueStatement), |
|
ConvertEmbeddedStatement(ifElseStatement.FalseStatement)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitLabelStatement(LabelStatement labelStatement) |
|
{ |
|
return new CodeLabeledStatement(labelStatement.Label); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitLockStatement(LockStatement lockStatement) |
|
{ |
|
return MakeSnippetStatement(lockStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitReturnStatement(ReturnStatement returnStatement) |
|
{ |
|
return new CodeMethodReturnStatement(Convert(returnStatement.Expression)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitSwitchStatement(SwitchStatement switchStatement) |
|
{ |
|
return MakeSnippetStatement(switchStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitSwitchSection(SwitchSection switchSection) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCaseLabel(CaseLabel caseLabel) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitThrowStatement(ThrowStatement throwStatement) |
|
{ |
|
return new CodeThrowExceptionStatement(Convert(throwStatement.Expression)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitTryCatchStatement(TryCatchStatement tryCatchStatement) |
|
{ |
|
List<CodeCatchClause> catchClauses = new List<CodeCatchClause>(); |
|
foreach (var catchClause in tryCatchStatement.CatchClauses) { |
|
catchClauses.Add(new CodeCatchClause(catchClause.VariableName, Convert(catchClause.Type), ConvertBlock(catchClause.Body))); |
|
} |
|
return new CodeTryCatchFinallyStatement( |
|
ConvertBlock(tryCatchStatement.TryBlock), |
|
catchClauses.ToArray(), |
|
ConvertBlock(tryCatchStatement.FinallyBlock)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCatchClause(CatchClause catchClause) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUncheckedStatement(UncheckedStatement uncheckedStatement) |
|
{ |
|
return MakeSnippetStatement(uncheckedStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUnsafeStatement(UnsafeStatement unsafeStatement) |
|
{ |
|
return MakeSnippetStatement(unsafeStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitUsingStatement(UsingStatement usingStatement) |
|
{ |
|
return MakeSnippetStatement(usingStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement) |
|
{ |
|
if (variableDeclarationStatement.Variables.Count != 1) |
|
return MakeSnippetStatement(variableDeclarationStatement); |
|
VariableInitializer vi = variableDeclarationStatement.Variables.Single(); |
|
return new CodeVariableDeclarationStatement( |
|
Convert(variableDeclarationStatement.Type), |
|
vi.Name, |
|
ConvertVariableInitializer(vi.Initializer, variableDeclarationStatement.Type)); |
|
} |
|
|
|
CodeExpression ConvertVariableInitializer(Expression expr, AstType type) |
|
{ |
|
ArrayInitializerExpression aie = expr as ArrayInitializerExpression; |
|
if (aie != null) { |
|
return new CodeArrayCreateExpression(Convert(type), Convert(aie.Elements)); |
|
} else { |
|
return Convert(expr); |
|
} |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitWhileStatement(WhileStatement whileStatement) |
|
{ |
|
return new CodeIterationStatement(EmptyStatement(), Convert(whileStatement.Condition), EmptyStatement(), ConvertEmbeddedStatement(whileStatement.EmbeddedStatement)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement) |
|
{ |
|
return MakeSnippetStatement(yieldBreakStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitYieldReturnStatement(YieldReturnStatement yieldStatement) |
|
{ |
|
return MakeSnippetStatement(yieldStatement); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitAccessor(Accessor accessor) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) |
|
{ |
|
CodeConstructor ctor = new CodeConstructor(); |
|
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)); |
|
} else { |
|
ctor.BaseConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments)); |
|
} |
|
ctor.Parameters.AddRange(Convert(constructorDeclaration.Parameters)); |
|
|
|
ctor.Statements.AddRange(ConvertBlock(constructorDeclaration.Body)); |
|
return ctor; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitConstructorInitializer(ConstructorInitializer constructorInitializer) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) |
|
{ |
|
return new CodeSnippetTypeMember(MakeSnippet(destructorDeclaration)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) |
|
{ |
|
TypeDeclaration td = enumMemberDeclaration.Parent as TypeDeclaration; |
|
CodeMemberField f = new CodeMemberField(td != null ? td.Name : "Enum", enumMemberDeclaration.Name); |
|
f.Attributes = MemberAttributes.Public | MemberAttributes.Static; |
|
f.CustomAttributes.AddRange(Convert(enumMemberDeclaration.Attributes)); |
|
f.InitExpression = Convert(enumMemberDeclaration.Initializer); |
|
return f; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitEventDeclaration(EventDeclaration eventDeclaration) |
|
{ |
|
foreach (VariableInitializer vi in eventDeclaration.Variables) { |
|
if (!vi.Initializer.IsNull) { |
|
AddTypeMember(new CodeSnippetTypeMember(MakeSnippet(eventDeclaration))); |
|
continue; |
|
} |
|
|
|
CodeMemberEvent e = new CodeMemberEvent(); |
|
e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers, EntityType.Event); |
|
e.CustomAttributes.AddRange(Convert(eventDeclaration.Attributes)); |
|
e.Name = vi.Name; |
|
e.Type = Convert(eventDeclaration.ReturnType); |
|
AddTypeMember(e); |
|
} |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration) |
|
{ |
|
return new CodeSnippetTypeMember(MakeSnippet(customEventDeclaration)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitFieldDeclaration(FieldDeclaration fieldDeclaration) |
|
{ |
|
foreach (VariableInitializer vi in fieldDeclaration.Variables) { |
|
CodeMemberField f = new CodeMemberField(Convert(fieldDeclaration.ReturnType), vi.Name); |
|
f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers, EntityType.Field); |
|
f.CustomAttributes.AddRange(Convert(fieldDeclaration.Attributes)); |
|
f.InitExpression = ConvertVariableInitializer(vi.Initializer, fieldDeclaration.ReturnType); |
|
AddTypeMember(f); |
|
} |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) |
|
{ |
|
CodeMemberProperty p = new CodeMemberProperty(); |
|
p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers, EntityType.Indexer); |
|
p.CustomAttributes.AddRange(Convert(indexerDeclaration.Attributes)); |
|
p.Name = "Items"; |
|
p.PrivateImplementationType = Convert(indexerDeclaration.PrivateImplementationType); |
|
p.Parameters.AddRange(Convert(indexerDeclaration.Parameters)); |
|
p.Type = Convert(indexerDeclaration.ReturnType); |
|
|
|
if (!indexerDeclaration.Getter.IsNull) { |
|
p.HasGet = true; |
|
p.GetStatements.AddRange(ConvertBlock(indexerDeclaration.Getter.Body)); |
|
} |
|
if (!indexerDeclaration.Setter.IsNull) { |
|
p.HasSet = true; |
|
p.SetStatements.AddRange(ConvertBlock(indexerDeclaration.Setter.Body)); |
|
} |
|
return p; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitMethodDeclaration(MethodDeclaration methodDeclaration) |
|
{ |
|
CodeMemberMethod m = new CodeMemberMethod(); |
|
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"))); |
|
|
|
m.ReturnType = Convert(methodDeclaration.ReturnType); |
|
m.PrivateImplementationType = Convert(methodDeclaration.PrivateImplementationType); |
|
m.Name = methodDeclaration.Name; |
|
m.TypeParameters.AddRange(ConvertTypeParameters(methodDeclaration.TypeParameters, methodDeclaration.Constraints)); |
|
m.Parameters.AddRange(Convert(methodDeclaration.Parameters)); |
|
|
|
m.Statements.AddRange(ConvertBlock(methodDeclaration.Body)); |
|
return m; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) |
|
{ |
|
CodeMemberMethod m = new CodeMemberMethod(); |
|
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"))); |
|
|
|
m.ReturnType = Convert(operatorDeclaration.ReturnType); |
|
m.Name = operatorDeclaration.Name; |
|
m.Parameters.AddRange(Convert(operatorDeclaration.Parameters)); |
|
|
|
m.Statements.AddRange(ConvertBlock(operatorDeclaration.Body)); |
|
return m; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration) |
|
{ |
|
var p = new CodeParameterDeclarationExpression(Convert(parameterDeclaration.Type), parameterDeclaration.Name); |
|
p.CustomAttributes.AddRange(Convert(parameterDeclaration.Attributes)); |
|
switch (parameterDeclaration.ParameterModifier) { |
|
case ParameterModifier.Ref: |
|
p.Direction = System.CodeDom.FieldDirection.Ref; |
|
break; |
|
case ParameterModifier.Out: |
|
p.Direction = System.CodeDom.FieldDirection.Out; |
|
break; |
|
} |
|
return p; |
|
} |
|
|
|
CodeParameterDeclarationExpression[] Convert(IEnumerable<ParameterDeclaration> parameters) |
|
{ |
|
List<CodeParameterDeclarationExpression> result = new List<CodeParameterDeclarationExpression>(); |
|
foreach (ParameterDeclaration pd in parameters) { |
|
CodeParameterDeclarationExpression pde = pd.AcceptVisitor(this) as CodeParameterDeclarationExpression; |
|
if (pde != null) |
|
result.Add(pde); |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) |
|
{ |
|
CodeMemberProperty p = new CodeMemberProperty(); |
|
p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers, EntityType.Property); |
|
p.CustomAttributes.AddRange(Convert(propertyDeclaration.Attributes)); |
|
p.Name = propertyDeclaration.Name; |
|
p.PrivateImplementationType = Convert(propertyDeclaration.PrivateImplementationType); |
|
p.Type = Convert(propertyDeclaration.ReturnType); |
|
|
|
if (!propertyDeclaration.Getter.IsNull) { |
|
p.HasGet = true; |
|
p.GetStatements.AddRange(ConvertBlock(propertyDeclaration.Getter.Body)); |
|
} |
|
if (!propertyDeclaration.Setter.IsNull) { |
|
p.HasSet = true; |
|
p.SetStatements.AddRange(ConvertBlock(propertyDeclaration.Setter.Body)); |
|
} |
|
return p; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitVariableInitializer(VariableInitializer variableInitializer) |
|
{ |
|
throw new NotSupportedException(); // should be handled by the parent node |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) |
|
{ |
|
return new CodeSnippetTypeMember(MakeSnippet(fixedFieldDeclaration)); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer) |
|
{ |
|
throw new NotSupportedException(); // should be handled by the parent node |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitSyntaxTree(SyntaxTree syntaxTree) |
|
{ |
|
CodeCompileUnit cu = new CodeCompileUnit(); |
|
foreach (AstNode node in syntaxTree.Children) { |
|
CodeObject o = node.AcceptVisitor(this); |
|
|
|
CodeNamespace ns = o as CodeNamespace; |
|
if (ns != null) { |
|
cu.Namespaces.Add(ns); |
|
} |
|
CodeTypeDeclaration td = o as CodeTypeDeclaration; |
|
if (td != null) { |
|
cu.Namespaces.Add(new CodeNamespace() { Types = { td } }); |
|
} |
|
} |
|
return cu; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitSimpleType(SimpleType simpleType) |
|
{ |
|
if (UseFullyQualifiedTypeNames) { |
|
IType type = Resolve(simpleType).Type; |
|
if (type.Kind != TypeKind.Unknown) |
|
return Convert(type); |
|
} |
|
var tr = new CodeTypeReference(simpleType.Identifier); |
|
tr.TypeArguments.AddRange(Convert(simpleType.TypeArguments)); |
|
return tr; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitMemberType(MemberType memberType) |
|
{ |
|
if (memberType.IsDoubleColon && new SimpleType("global").IsMatch(memberType.Target)) { |
|
var tr = new CodeTypeReference(memberType.MemberName, CodeTypeReferenceOptions.GlobalReference); |
|
tr.TypeArguments.AddRange(Convert(memberType.TypeArguments)); |
|
return tr; |
|
} |
|
if (UseFullyQualifiedTypeNames || memberType.IsDoubleColon) { |
|
IType type = Resolve(memberType).Type; |
|
if (type.Kind != TypeKind.Unknown) |
|
return Convert(type); |
|
} |
|
CodeTypeReference target = Convert(memberType.Target); |
|
if (target == null) |
|
return null; |
|
target.BaseType = target.BaseType + "." + memberType.MemberName; |
|
target.TypeArguments.AddRange(Convert(memberType.TypeArguments)); |
|
return target; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitComposedType(ComposedType composedType) |
|
{ |
|
CodeTypeReference typeRef = Convert(composedType.BaseType); |
|
if (typeRef == null) |
|
return null; |
|
if (composedType.HasNullableSpecifier) { |
|
typeRef = new CodeTypeReference("System.Nullable") { TypeArguments = { typeRef } }; |
|
} |
|
foreach (ArraySpecifier s in composedType.ArraySpecifiers.Reverse()) { |
|
typeRef = new CodeTypeReference(typeRef, s.Dimensions); |
|
} |
|
return typeRef; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitArraySpecifier(ArraySpecifier arraySpecifier) |
|
{ |
|
throw new NotSupportedException(); // handled by parent node |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPrimitiveType(PrimitiveType primitiveType) |
|
{ |
|
KnownTypeCode typeCode = primitiveType.KnownTypeCode; |
|
if (typeCode != KnownTypeCode.None) { |
|
KnownTypeReference ktr = KnownTypeReference.Get(typeCode); |
|
return new CodeTypeReference(ktr.Namespace + "." + ktr.Name); |
|
} |
|
return new CodeTypeReference(primitiveType.Keyword); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitComment (Comment comment) |
|
{ |
|
return new CodeComment (comment.Content, comment.CommentType == CommentType.Documentation); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitNewLine(NewLineNode newLineNode) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitWhitespace(WhitespaceNode whitespaceNode) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitText(TextNode textNode) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective) |
|
{ |
|
return new CodeComment ("#" + preProcessorDirective.Type.ToString ().ToLower ()); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration) |
|
{ |
|
throw new NotSupportedException(); // type parameters and constraints are handled together |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitConstraint(Constraint constraint) |
|
{ |
|
throw new NotSupportedException(); |
|
} |
|
|
|
CodeTypeParameter[] ConvertTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters, IEnumerable<Constraint> constraints) |
|
{ |
|
List<CodeTypeParameter> result = new List<CodeTypeParameter>(); |
|
foreach (TypeParameterDeclaration tpDecl in typeParameters) { |
|
CodeTypeParameter tp = new CodeTypeParameter(tpDecl.Name); |
|
tp.CustomAttributes.AddRange(Convert(tpDecl.Attributes)); |
|
foreach (Constraint constraint in constraints) { |
|
if (constraint.TypeParameter.Identifier == tp.Name) { |
|
foreach (AstType baseType in constraint.BaseTypes) { |
|
if (baseType is PrimitiveType && ((PrimitiveType)baseType).Keyword == "new") { |
|
tp.HasConstructorConstraint = true; |
|
} else { |
|
CodeTypeReference tr = Convert(baseType); |
|
if (tr != null) |
|
tp.Constraints.Add(tr); |
|
} |
|
} |
|
} |
|
} |
|
result.Add(tp); |
|
} |
|
return result.ToArray(); |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode) |
|
{ |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitIdentifier(Identifier identifier) |
|
{ |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, Pattern pattern) |
|
{ |
|
return null; |
|
} |
|
|
|
CodeObject IAstVisitor<CodeObject>.VisitDocumentationReference(DocumentationReference documentationReference) |
|
{ |
|
return null; |
|
} |
|
} |
|
}
|
|
|