// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.AstBuilder;
using ICSharpCode.NRefactory.Visitors;
namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
///
/// This class converts C# constructs to their VB.NET equivalents.
///
public class VBNetToCSharpConvertVisitor : VBNetConstructsConvertVisitor
{
// Fixes identifier casing
// Adds using statements for the default usings
// Convert "ReDim" statement
// Convert "WithEvents" fields/"Handles" clauses
// Insert InitializeComponents() call into default constructor
public string NamespacePrefixToAdd { get; set; }
protected readonly IProjectContent projectContent;
protected readonly NRefactoryResolver resolver;
protected readonly ParseInformation parseInformation;
public VBNetToCSharpConvertVisitor(IProjectContent pc, ParseInformation parseInfo)
{
this.resolver = new NRefactoryResolver(LanguageProperties.VBNet);
this.projectContent = pc;
this.parseInformation = parseInfo;
}
public override object VisitCompilationUnit(CompilationUnit compilationUnit, object data)
{
base.VisitCompilationUnit(compilationUnit, data);
if (!string.IsNullOrEmpty(NamespacePrefixToAdd)) {
for (int i = 0; i < compilationUnit.Children.Count; i++) {
NamespaceDeclaration ns = compilationUnit.Children[i] as NamespaceDeclaration;
if (ns != null) {
ns.Name = NamespacePrefixToAdd + "." + ns.Name;
}
if (compilationUnit.Children[i] is TypeDeclaration || compilationUnit.Children[i] is DelegateDeclaration) {
ns = new NamespaceDeclaration(NamespacePrefixToAdd);
ns.AddChild(compilationUnit.Children[i]);
compilationUnit.Children[i] = ns;
}
}
}
ToCSharpConvertVisitor v = new ToCSharpConvertVisitor();
compilationUnit.AcceptVisitor(v, data);
if (projectContent != null && projectContent.DefaultImports != null) {
int index = 0;
foreach (string u in projectContent.DefaultImports.Usings) {
compilationUnit.Children.Insert(index++, new UsingDeclaration(u));
}
}
return null;
}
public override object VisitUsing(Using @using, object data)
{
base.VisitUsing(@using, data);
if (projectContent != null && projectContent.DefaultImports != null) {
if (!@using.IsAlias) {
// remove using if it is already part of the project-wide imports
foreach (string defaultImport in projectContent.DefaultImports.Usings) {
if (resolver.IsSameName(defaultImport, @using.Name)) {
RemoveCurrentNode();
break;
}
}
}
}
return null;
}
public override object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
{
base.VisitUsingDeclaration(usingDeclaration, data);
if (usingDeclaration.Usings.Count == 0) {
RemoveCurrentNode();
}
return null;
}
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
resolver.Initialize(parseInformation, typeDeclaration.BodyStartLocation.Line, typeDeclaration.BodyStartLocation.Column);
if (resolver.CallingClass != null) {
// add Partial modifier to all parts of the class
IClass callingClass = resolver.CallingClass.GetCompoundClass();
if (callingClass.IsPartial) {
typeDeclaration.Modifier |= Modifiers.Partial;
}
// determine if the type contains handles clauses referring to the current type
bool containsClassHandlesClauses = false;
bool hasConstructors = false;
foreach (IMethod method in callingClass.Methods) {
// do not count compiler-generated constructors
if (method.IsSynthetic) continue;
hasConstructors |= method.IsConstructor;
foreach (string handles in method.HandlesClauses) {
containsClassHandlesClauses |= !handles.Contains(".");
}
}
// ensure the type has at least one constructor to which the AddHandlerStatements can be added
CompoundClass compoundClass = callingClass as CompoundClass;
if (!hasConstructors) {
// add constructor only to one part
if (compoundClass == null || compoundClass.Parts[0] == resolver.CallingClass) {
if (containsClassHandlesClauses || RequiresConstructor(callingClass)) {
AddDefaultConstructor(callingClass, typeDeclaration);
}
}
}
}
base.VisitTypeDeclaration(typeDeclaration, data);
return null;
}
///
/// Gets if the converter should add a default constructor to the current class if the
/// class does not have any constructors.
///
protected virtual bool RequiresConstructor(IClass currentClass)
{
// the VB compiler automatically adds the InitializeComponents() call to the
// default constructor, so the converter has to an explicit constructor
// and place the call there
return IsAutomaticallyCallingInitializeComponent(currentClass);
}
bool IsAutomaticallyCallingInitializeComponent(IClass currentClass)
{
if (currentClass != null) {
if (currentClass.SearchMember("InitializeComponent", LanguageProperties.VBNet) is IMethod) {
foreach (IAttribute at in currentClass.Attributes) {
if (at.AttributeType.FullyQualifiedName == "Microsoft.VisualBasic.CompilerServices.DesignerGeneratedAttribute") {
return true;
}
}
}
}
return false;
}
///
/// Adds a default constructor to the type.
///
protected virtual ConstructorDeclaration AddDefaultConstructor(IClass currentClass, TypeDeclaration typeDeclaration)
{
ConstructorDeclaration cd = new ConstructorDeclaration(typeDeclaration.Name, Modifiers.Public, null, null);
cd.Body = new BlockStatement();
// location is required to make Resolve() work in the constructor
cd.StartLocation = cd.Body.StartLocation = cd.EndLocation = cd.Body.EndLocation = typeDeclaration.BodyStartLocation;
typeDeclaration.AddChild(cd);
if (IsAutomaticallyCallingInitializeComponent(currentClass)) {
// the VB compiler automatically adds the InitializeComponents() call to the
// default constructor, so the converter has to add the call when creating an explicit
// constructor
cd.Body.AddStatement(new IdentifierExpression("InitializeComponent").Call());
}
return cd;
}
public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
{
// Initialize resolver for method:
if (!methodDeclaration.Body.IsNull) {
if (resolver.Initialize(parseInformation, methodDeclaration.Body.StartLocation.Line, methodDeclaration.Body.StartLocation.Column)) {
resolver.RunLookupTableVisitor(methodDeclaration);
}
}
methodDeclaration.HandlesClause.Clear();
return base.VisitMethodDeclaration(methodDeclaration, data);
}
public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
{
resolver.Initialize(parseInformation, fieldDeclaration.StartLocation.Line, fieldDeclaration.StartLocation.Column);
base.VisitFieldDeclaration(fieldDeclaration, data);
if ((fieldDeclaration.Modifier & Modifiers.WithEvents) == Modifiers.WithEvents) {
TransformWithEventsField(fieldDeclaration);
if (fieldDeclaration.Fields.Count == 0) {
RemoveCurrentNode();
}
}
return null;
}
void TransformWithEventsField(FieldDeclaration fieldDeclaration)
{
if (resolver.CallingClass == null)
return;
INode insertAfter = fieldDeclaration;
for (int i = 0; i < fieldDeclaration.Fields.Count;) {
VariableDeclaration field = fieldDeclaration.Fields[i];
IdentifierExpression backingFieldNameExpression = null;
PropertyDeclaration createdProperty = null;
foreach (IMethod m in resolver.CallingClass.GetCompoundClass().Methods) {
foreach (string handlesClause in m.HandlesClauses) {
int pos = handlesClause.IndexOf('.');
if (pos > 0) {
string fieldName = handlesClause.Substring(0, pos);
string eventName = handlesClause.Substring(pos + 1);
if (resolver.IsSameName(fieldName, field.Name)) {
if (createdProperty == null) {
FieldDeclaration backingField = new FieldDeclaration(null);
backingField.Fields.Add(new VariableDeclaration(
"withEventsField_" + field.Name, field.Initializer, fieldDeclaration.GetTypeForField(i)));
backingField.Modifier = Modifiers.Private;
InsertAfterSibling(insertAfter, backingField);
createdProperty = new PropertyDeclaration(fieldDeclaration.Modifier, null, field.Name, null);
createdProperty.TypeReference = fieldDeclaration.GetTypeForField(i);
createdProperty.StartLocation = fieldDeclaration.StartLocation;
createdProperty.EndLocation = fieldDeclaration.EndLocation;
backingFieldNameExpression = new IdentifierExpression(backingField.Fields[0].Name);
createdProperty.GetRegion = new PropertyGetRegion(new BlockStatement(), null);
createdProperty.GetRegion.Block.AddChild(new ReturnStatement(
backingFieldNameExpression));
Expression backingFieldNotNullTest = new BinaryOperatorExpression(
backingFieldNameExpression,
BinaryOperatorType.InEquality,
new PrimitiveExpression(null, "null"));
createdProperty.SetRegion = new PropertySetRegion(new BlockStatement(), null);
createdProperty.SetRegion.Block.AddChild(new IfElseStatement(
backingFieldNotNullTest, new BlockStatement()
));
createdProperty.SetRegion.Block.AddChild(new ExpressionStatement(
new AssignmentExpression(
backingFieldNameExpression,
AssignmentOperatorType.Assign,
new IdentifierExpression("value"))));
createdProperty.SetRegion.Block.AddChild(new IfElseStatement(
backingFieldNotNullTest, new BlockStatement()
));
InsertAfterSibling(backingField, createdProperty);
insertAfter = createdProperty;
}
// insert code to remove the event handler
IfElseStatement ies = (IfElseStatement)createdProperty.SetRegion.Block.Children[0];
ies.TrueStatement[0].AddChild(new RemoveHandlerStatement(
new MemberReferenceExpression(backingFieldNameExpression, eventName),
new AddressOfExpression(new IdentifierExpression(m.Name))));
// insert code to add the event handler
ies = (IfElseStatement)createdProperty.SetRegion.Block.Children[2];
ies.TrueStatement[0].AddChild(new AddHandlerStatement(
new MemberReferenceExpression(backingFieldNameExpression, eventName),
new AddressOfExpression(new IdentifierExpression(m.Name))));
}
}
}
}
if (createdProperty != null) {
// field replaced with property
fieldDeclaration.Fields.RemoveAt(i);
} else {
i++;
}
}
}
public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
{
if (!constructorDeclaration.Body.IsNull) {
if (resolver.Initialize(parseInformation, constructorDeclaration.Body.StartLocation.Line, constructorDeclaration.Body.StartLocation.Column)) {
resolver.RunLookupTableVisitor(constructorDeclaration);
}
}
base.VisitConstructorDeclaration(constructorDeclaration, data);
if (resolver.CallingClass != null) {
if (constructorDeclaration.ConstructorInitializer.IsNull
|| constructorDeclaration.ConstructorInitializer.ConstructorInitializerType != ConstructorInitializerType.This)
{
AddClassEventHandlersToConstructor(constructorDeclaration);
}
}
return null;
}
void AddClassEventHandlersToConstructor(ConstructorDeclaration constructorDeclaration)
{
foreach (IMethod method in resolver.CallingClass.GetCompoundClass().Methods) {
foreach (string handles in method.HandlesClauses) {
if (!handles.Contains(".")) {
AddHandlerStatement ahs = new AddHandlerStatement(
new IdentifierExpression(handles),
new AddressOfExpression(new IdentifierExpression(method.Name))
);
constructorDeclaration.Body.Children.Insert(0, ahs);
ahs.Parent = constructorDeclaration.Body;
}
}
}
}
public override object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
{
if (resolver.Initialize(parseInformation, propertyDeclaration.BodyStart.Line, propertyDeclaration.BodyStart.Column)) {
resolver.RunLookupTableVisitor(propertyDeclaration);
}
return base.VisitPropertyDeclaration(propertyDeclaration, data);
}
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
base.VisitIdentifierExpression(identifierExpression, data);
if (resolver.CompilationUnit == null)
return null;
ResolveResult rr = resolver.ResolveInternal(identifierExpression, ExpressionContext.Default);
string ident = GetIdentifierFromResult(rr);
if (ident != null) {
identifierExpression.Identifier = ident;
}
if (ReplaceWithInvocation(identifierExpression, rr)) {}
else if (FullyQualifyModuleMemberReference(identifierExpression, rr)) {}
else if (FullyQualifyNamespaceReference(identifierExpression, rr)) {}
return null;
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
base.VisitMemberReferenceExpression(memberReferenceExpression, data);
if (resolver.CompilationUnit == null)
return null;
ResolveResult rr = Resolve(memberReferenceExpression);
string ident = GetIdentifierFromResult(rr);
if (ident != null) {
memberReferenceExpression.MemberName = ident;
}
if (ReplaceWithInvocation(memberReferenceExpression, rr)) {}
else if (FullyQualifyModuleMemberReference(memberReferenceExpression, rr)) {}
return rr;
}
protected bool IsReferenceToInstanceMember(ResolveResult rr)
{
MemberResolveResult memberRR = rr as MemberResolveResult;
if (memberRR != null)
return memberRR.ResolvedMember.IsStatic == false;
MethodGroupResolveResult methodRR = rr as MethodGroupResolveResult;
if (methodRR != null && methodRR.ContainingType != null) {
foreach (IMethod m in methodRR.ContainingType.GetMethods()) {
if (resolver.IsSameName(m.Name, methodRR.Name)) {
return !m.IsStatic;
}
}
}
return false;
}
bool ReplaceWithInvocation(Expression expression, ResolveResult rr)
{
// replace with invocation if rr is a method
// and were not taking the address and it's not already being invoked
MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
if (mgrr != null
&& mgrr.Methods.Any(g=>g.Count>0)
&& !(expression.Parent is AddressOfExpression)
&& !(NRefactoryResolver.IsInvoked(expression)))
{
InvocationExpression ie = new InvocationExpression(expression);
ReplaceCurrentNode(ie);
return true;
}
return false;
}
IReturnType GetContainingTypeOfStaticMember(ResolveResult rr)
{
MethodGroupResolveResult methodRR = rr as MethodGroupResolveResult;
if (methodRR != null) {
return methodRR.ContainingType;
}
MemberResolveResult memberRR = rr as MemberResolveResult;
if (memberRR != null && memberRR.ResolvedMember.IsStatic) {
return memberRR.ResolvedMember.DeclaringTypeReference;
}
return null;
}
bool FullyQualifyModuleMemberReference(IdentifierExpression ident, ResolveResult rr)
{
IReturnType containingType = GetContainingTypeOfStaticMember(rr);
if (containingType == null)
return false;
if (resolver.CallingClass != null) {
if (resolver.CallingClass.IsTypeInInheritanceTree(containingType.GetUnderlyingClass()))
return false;
}
ReplaceCurrentNode(new MemberReferenceExpression(
new TypeReferenceExpression(ConvertType(containingType)),
ident.Identifier
));
return true;
}
bool FullyQualifyNamespaceReference(IdentifierExpression ident, ResolveResult rr)
{
NamespaceResolveResult nrr = rr as NamespaceResolveResult;
if (nrr == null)
return false;
if (nrr.Name.IndexOf('.') >= 0) {
// simple identifier points to complex namespace
ReplaceCurrentNode(MakeFieldReferenceExpression(nrr.Name));
} else {
ident.Identifier = nrr.Name;
}
return true;
}
TypeReference ConvertType(IReturnType type)
{
return Refactoring.CodeGenerator.ConvertType(type, CreateContext());
}
bool FullyQualifyModuleMemberReference(MemberReferenceExpression mre, ResolveResult rr)
{
IReturnType containingType = GetContainingTypeOfStaticMember(rr);
if (containingType == null)
return false;
ResolveResult targetRR = resolver.ResolveInternal(mre.TargetObject, ExpressionContext.Default);
if (targetRR is NamespaceResolveResult) {
mre.TargetObject = new TypeReferenceExpression(ConvertType(containingType));
return true;
}
return false;
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
base.VisitInvocationExpression(invocationExpression, data);
if (resolver.CompilationUnit == null)
return null;
if (!(invocationExpression.Parent is ReDimStatement))
{
ProcessInvocationExpression(invocationExpression);
}
return null;
}
protected ResolveResult Resolve(Expression expression)
{
if (resolver.CompilationUnit == null) {
return null;
} else {
return resolver.ResolveInternal(expression, ExpressionContext.Default);
}
}
void ProcessInvocationExpression(InvocationExpression invocationExpression)
{
MemberResolveResult rr = Resolve(invocationExpression) as MemberResolveResult;
if (rr != null) {
IProperty p = rr.ResolvedMember as IProperty;
if (p != null && invocationExpression.Arguments.Count > 0) {
// col(i) -> col[i] or col.Items(i) -> col[i] ?
Expression targetObject = invocationExpression.TargetObject;
MemberReferenceExpression targetObjectFre = targetObject as MemberReferenceExpression;
if (p.IsIndexer && targetObjectFre != null) {
MemberResolveResult rr2 = Resolve(targetObjectFre) as MemberResolveResult;
if (rr2 != null && rr2.ResolvedMember.FullyQualifiedName == rr.ResolvedMember.FullyQualifiedName) {
// remove ".Items"
targetObject = targetObjectFre.TargetObject;
}
}
ReplaceCurrentNode(new IndexerExpression(targetObject, invocationExpression.Arguments));
}
IMethod m = rr.ResolvedMember as IMethod;
if (m != null && invocationExpression.Arguments.Count == m.Parameters.Count) {
for (int i = 0; i < m.Parameters.Count; i++) {
if (m.Parameters[i].IsOut) {
invocationExpression.Arguments[i] = new DirectionExpression(
FieldDirection.Out, invocationExpression.Arguments[i]);
} else if (m.Parameters[i].IsRef) {
invocationExpression.Arguments[i] = new DirectionExpression(
FieldDirection.Ref, invocationExpression.Arguments[i]);
}
}
}
}
}
ClassFinder CreateContext()
{
return new ClassFinder(resolver.CallingClass, resolver.CallingMember, resolver.CaretLine, resolver.CaretColumn);
}
public override object VisitReDimStatement(ReDimStatement reDimStatement, object data)
{
base.VisitReDimStatement(reDimStatement, data);
if (resolver.CompilationUnit == null)
return null;
if (reDimStatement.ReDimClauses.Count != 1)
return null;
if (reDimStatement.IsPreserve) {
if (reDimStatement.ReDimClauses[0].Arguments.Count > 1) {
// multidimensional Redim Preserve
// replace with:
// MyArray = (int[,])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray(MyArray, new int[dim1+1, dim2+1]);
ResolveResult rr = Resolve(reDimStatement.ReDimClauses[0].TargetObject);
if (rr != null && rr.ResolvedType != null && rr.ResolvedType.IsArrayReturnType) {
ArrayCreateExpression ace = new ArrayCreateExpression(ConvertType(rr.ResolvedType));
foreach (Expression arg in reDimStatement.ReDimClauses[0].Arguments) {
ace.Arguments.Add(Expression.AddInteger(arg, 1));
}
ReplaceCurrentNode(new ExpressionStatement(
new AssignmentExpression(
reDimStatement.ReDimClauses[0].TargetObject,
AssignmentOperatorType.Assign,
new CastExpression(
ace.CreateType,
new InvocationExpression(
MakeFieldReferenceExpression("Microsoft.VisualBasic.CompilerServices.Utils.CopyArray"),
new List {
reDimStatement.ReDimClauses[0].TargetObject,
ace
}
),
CastType.Cast
)
)));
}
}
} else {
// replace with array create expression
ResolveResult rr = Resolve(reDimStatement.ReDimClauses[0].TargetObject);
if (rr != null && rr.ResolvedType != null && rr.ResolvedType.IsArrayReturnType) {
ArrayCreateExpression ace = new ArrayCreateExpression(ConvertType(rr.ResolvedType));
foreach (Expression arg in reDimStatement.ReDimClauses[0].Arguments) {
ace.Arguments.Add(Expression.AddInteger(arg, 1));
}
ReplaceCurrentNode(new ExpressionStatement(
new AssignmentExpression(reDimStatement.ReDimClauses[0].TargetObject, AssignmentOperatorType.Assign, ace)));
}
}
return null;
}
protected Expression MakeFieldReferenceExpression(string name)
{
Expression e = null;
foreach (string n in name.Split('.')) {
if (e == null)
e = new IdentifierExpression(n);
else
e = new MemberReferenceExpression(e, n);
}
return e;
}
public override object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
{
base.VisitDefaultValueExpression(defaultValueExpression, data);
IReturnType type = FixTypeReferenceCasing(defaultValueExpression.TypeReference, defaultValueExpression.StartLocation);
// the VBNetConstructsConvertVisitor will initialize local variables to
// default(TypeReference).
// MyType m = null; looks nicer than MyType m = default(MyType))
// so we replace default(ReferenceType) with null
if (type != null && type.IsReferenceType == true) {
ReplaceCurrentNode(new PrimitiveExpression(null, "null"));
}
return null;
}
public override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data)
{
FixTypeReferenceCasing(variableDeclaration.TypeReference, variableDeclaration.StartLocation);
return base.VisitVariableDeclaration(variableDeclaration, data);
}
public override object VisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data)
{
FixTypeReferenceCasing(parameterDeclarationExpression.TypeReference, parameterDeclarationExpression.StartLocation);
return base.VisitParameterDeclarationExpression(parameterDeclarationExpression, data);
}
public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
{
FixTypeReferenceCasing(objectCreateExpression.CreateType, objectCreateExpression.StartLocation);
return base.VisitObjectCreateExpression(objectCreateExpression, data);
}
IReturnType FixTypeReferenceCasing(TypeReference tr, Location loc)
{
if (resolver.CompilationUnit == null) return null;
if (tr.IsNull) return null;
var searchTypeResult = resolver.SearchType(tr.Type, tr.GenericTypes.Count, loc);
IReturnType rt = searchTypeResult.Result;
if (rt != null) {
IClass c = rt.GetUnderlyingClass();
if (c != null) {
if (string.Equals(tr.Type, c.Name, StringComparison.OrdinalIgnoreCase)) {
tr.Type = c.Name;
} else if (string.Equals(tr.Type, c.FullyQualifiedName, StringComparison.OrdinalIgnoreCase)) {
tr.Type = c.FullyQualifiedName;
} else if (searchTypeResult.UsedUsing != null && !searchTypeResult.UsedUsing.HasAliases) {
tr.Type = c.FullyQualifiedName;
}
}
}
foreach (TypeReference arg in tr.GenericTypes) {
FixTypeReferenceCasing(arg, loc);
}
return rt;
}
string GetIdentifierFromResult(ResolveResult rr)
{
LocalResolveResult lrr = rr as LocalResolveResult;
if (lrr != null)
return lrr.VariableName;
MemberResolveResult mrr = rr as MemberResolveResult;
if (mrr != null)
return mrr.ResolvedMember.Name;
MethodGroupResolveResult mtrr = rr as MethodGroupResolveResult;
if (mtrr != null)
return mtrr.Name;
TypeResolveResult trr = rr as TypeResolveResult;
if (trr != null && trr.ResolvedClass != null)
return trr.ResolvedClass.Name;
return null;
}
public override object VisitForeachStatement(ForeachStatement foreachStatement, object data)
{
base.VisitForeachStatement(foreachStatement, data);
FixTypeReferenceCasing(foreachStatement.TypeReference, foreachStatement.StartLocation);
if (resolver.CompilationUnit == null)
return null;
if (foreachStatement.TypeReference.IsNull) {
ResolveResult rr = resolver.ResolveIdentifier(foreachStatement.VariableName, foreachStatement.StartLocation, ExpressionContext.Default);
if (rr != null && rr.ResolvedType != null) {
BlockStatement blockStatement = foreachStatement.EmbeddedStatement as BlockStatement;
if (blockStatement == null) {
blockStatement = new BlockStatement();
blockStatement.AddChild(foreachStatement.EmbeddedStatement);
foreachStatement.EmbeddedStatement = blockStatement;
}
string newVariableName = foreachStatement.VariableName + "_loopVariable";
ExpressionStatement st = new ExpressionStatement(
new AssignmentExpression(
new IdentifierExpression(foreachStatement.VariableName),
AssignmentOperatorType.Assign,
new IdentifierExpression(newVariableName)));
blockStatement.Children.Insert(0, st);
st.Parent = blockStatement;
foreachStatement.VariableName = newVariableName;
foreachStatement.TypeReference = ConvertType(rr.ResolvedType);
}
}
return null;
}
}
}