private void MoveOutOfClass(MethodDeclaration methodDeclaration) { var classDeclaration = (ClassDeclaration)methodDeclaration.Parent; if (!methodDeclaration.Modifiers.Contains(MemberModifier.Static)) { var thisParameter = new VariableDeclaration( methodDeclaration.Context, "this" + NumberWheel.Next(), new ReferenceType(methodDeclaration.Context, methodDeclaration.Parent).Yield() ); methodDeclaration.AddChildBefore(methodDeclaration.Variables.FirstOrDefault() ?? (INode)methodDeclaration.Body, thisParameter); ReplaceThisWithReferencesToVariable(methodDeclaration, thisParameter); } var classDeclarationParent = classDeclaration.Parent; methodDeclaration.Remove(); classDeclarationParent.AddChildAfter(classDeclaration, methodDeclaration); }
public override void ExitAssignmentExpression(AssignmentExpression assignmentExpression) { if (assignmentExpression.Operator.Value != "=") { var rightSide = assignmentExpression.Right; rightSide.Remove(); var leftClone = AstCloner.Clone(assignmentExpression.Left); switch (leftClone) { case SimpleNameExpression simpleNameExpression: if (simpleNameExpression.Declaration is SetterDeclaration) { var classDeclaration = (ClassDeclaration)simpleNameExpression.Declaration.Parent; var getterSetter = classDeclaration.GettersAndSetters.Single(x => x.Setter == simpleNameExpression.Declaration); simpleNameExpression.Declaration = getterSetter.Getter; } break; case MemberExpression memberExpression: if (memberExpression.Declaration is SetterDeclaration) { var classDeclaration = (ClassDeclaration)memberExpression.Declaration.Parent; var getterSetter = classDeclaration.GettersAndSetters.Single(x => x.Setter == memberExpression.Declaration); memberExpression.Declaration = getterSetter.Getter; } break; } assignmentExpression.AddChild( new BinaryExpression(assignmentExpression.Context, new INode[] { leftClone, new Token(assignmentExpression.Context, assignmentExpression.Operator.Value.Substring(0, assignmentExpression.Operator.Value.Length - 1)), rightSide })); assignmentExpression.Operator.Value = "="; } if (!(assignmentExpression.Parent is ExpressionStatement || assignmentExpression.Parent is ForStatement || assignmentExpression.Parent is ForeachStatement)) { var statement = assignmentExpression.NearestAncestorOfType <IStatement>(); var block = (BlockStatement)statement.Parent; var variable = new VariableDeclaration(assignmentExpression.Context, "var" + NumberWheel.Next(), new INode[] { assignmentExpression.Type.Wrap(assignmentExpression.Context), assignmentExpression.Right }) { VariableType = VariableType.Const }; block.VariableDeclarations.Add(variable); block.AddChildBefore(statement, new VariableDeclarationStatement(assignmentExpression.Context, variable)); block.AddChildBefore(statement, new ExpressionStatement(assignmentExpression.Context, new AssignmentExpression( assignmentExpression.Context, new INode[] { assignmentExpression.Left, assignmentExpression.Operator, new SimpleNameExpression(assignmentExpression.Context, variable.Name) { Declaration = variable, Type = variable.Type }, }) { Type = assignmentExpression.Type }) ); assignmentExpression.ReplaceWith( new SimpleNameExpression(assignmentExpression.Context, variable.Name) { Declaration = variable, Type = variable.Type }); } }
private void UnwrapMethodInvocation(MethodInvocationExpression invocation, MethodDeclaration declaration) { if (invocation.Parent == null) { return; } var context = invocation.Context; var parentStatement = invocation.NearestAncestorOfType <IStatement>(); var discardReturnValue = invocation.Parent is ExpressionStatement; var block = (BlockStatement)parentStatement.Parent; var addedStatements = new List <IStatement>(); VariableDeclaration returnValueVar = null; if (!discardReturnValue) { returnValueVar = new VariableDeclaration( context, declaration.Name + NumberWheel.Next(), new INode[] { AstCloner.Clone(declaration.ReturnType) }); var variableDeclarationStatement = new VariableDeclarationStatement(context, returnValueVar); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(returnValueVar); invocation.ReplaceWith(new SimpleNameExpression(context, returnValueVar.Name) { Type = returnValueVar.Type, Declaration = returnValueVar }); addedStatements.Add(variableDeclarationStatement); } else { invocation.Remove(); } var clonedDeclaration = AstCloner.Clone(declaration); var parameters = clonedDeclaration.Variables.ToList(); var arguments = invocation.Arguments.ToList(); for (int i = 0; i < parameters.Count; i++) { if (arguments.Count > i) { if (parameters[i].InitExpression != null) { parameters[i].InitExpression.ReplaceWith(arguments[i]); } else { parameters[i].AddChild(arguments[i]); } } parameters[i].Remove(); parameters[i].Name += NumberWheel.Next(); var variableDeclarationStatement = new VariableDeclarationStatement(parameters[i].Context, parameters[i]); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(parameters[i]); addedStatements.Add(variableDeclarationStatement); } foreach (var expression in clonedDeclaration.AllDescendantsAndSelf().OfType <SimpleNameExpression>()) { var index = parameters.IndexOf(expression.Declaration); if (index == -1) { continue; } expression.Name = parameters[index].Name; } var body = clonedDeclaration.Body; block.AddChildBefore(parentStatement, body); addedStatements.Add(body); var gotoTarget = new GotoTargetStatement(invocation.Context); block.AddChildBefore(parentStatement, gotoTarget); addedStatements.Add(gotoTarget); ReplaceReturnStatements(clonedDeclaration.Body, gotoTarget, returnValueVar); if (discardReturnValue) { parentStatement.Remove(); } foreach (var subInvocation in addedStatements.SelectMany(x => x.AllDescendantsAndSelf()).OfType <MethodInvocationExpression>().ToList()) { var subTarget = ((MethodReferenceType)subInvocation.Base.Type).Declaration; UnwrapMethodInvocation(subInvocation, subTarget); } BlockFlattener.FlattenAllSubBlocks(block); }
public override void EnterForeachStatement(ForeachStatement foreachStatement) { var listVariable = new VariableDeclaration( foreachStatement.Context, "list" + NumberWheel.Next(), new INode[] { AstCloner.Clone((GenericType)foreachStatement.List.Type), foreachStatement.List }); var indexVariable = new VariableDeclaration( foreachStatement.Context, "index" + NumberWheel.Next(), new INode[] { new NumberType(foreachStatement.Context), new NumberLiteral(foreachStatement.Context, "0") }); var condition = new BinaryExpression( foreachStatement.Context, new INode[] { new SimpleNameExpression(foreachStatement.Context, indexVariable.Name) { Declaration = indexVariable, Type = indexVariable.Type }, new Token(foreachStatement.Context, "<"), NativeMethods.ArrayCount( foreachStatement.Context, new SimpleNameExpression(foreachStatement.Context, listVariable.Name) { Declaration = listVariable, Type = listVariable.Type }) }); var update = new AssignmentExpression( foreachStatement.Context, new INode[] { new SimpleNameExpression(foreachStatement.Context, indexVariable.Name) { Declaration = indexVariable, Type = indexVariable.Type }, new AssignmentOperator(foreachStatement.Context, "="), new BinaryExpression( foreachStatement.Context, new INode[] { new SimpleNameExpression(foreachStatement.Context, indexVariable.Name) { Declaration = indexVariable, Type = indexVariable.Type }, new Token(foreachStatement.Context, "+"), new NumberLiteral(foreachStatement.Context, "1") }), }); var forStatement = new ForStatement( foreachStatement.Context, new[] { listVariable, indexVariable }, new IExpression[0], condition, update.Yield(), foreachStatement.Body); var elmVariable = foreachStatement.Variable; elmVariable.AddChild( NativeMethods.ArrayIndex( foreachStatement.Context, new SimpleNameExpression(foreachStatement.Context, listVariable.Name) { Declaration = listVariable, Type = listVariable.Type }, new SimpleNameExpression(foreachStatement.Context, indexVariable.Name) { Declaration = indexVariable, Type = indexVariable.Type }) ); forStatement.Body.AddChildFirst(new VariableDeclarationStatement(foreachStatement.Context, elmVariable)); foreachStatement.ReplaceWith(forStatement); Visit(forStatement); skipChildren = true; }