public UsingStatement TransformUsings(ExpressionStatement node) { Match m1 = variableAssignPattern.Match(node); if (m1 == null) { return(null); } AstNode tryCatch = node.NextSibling; Match m2 = usingTryCatchPattern.Match(tryCatch); if (m2 == null) { return(null); } string variableName = m1.Get <IdentifierExpression>("variable").Single().Identifier; if (variableName == m2.Get <IdentifierExpression>("ident").Single().Identifier) { if (m2.Has("valueType")) { // if there's no if(x!=null), then it must be a value type ILVariable v = m1.Get("variable").Single().Annotation <ILVariable>(); if (v == null || v.Type == null || !v.Type.IsValueType) { return(null); } } node.Remove(); BlockStatement body = m2.Get <BlockStatement>("body").Single(); UsingStatement usingStatement = new UsingStatement(); usingStatement.ResourceAcquisition = node.Expression.Detach(); usingStatement.EmbeddedStatement = body.Detach(); tryCatch.ReplaceWith(usingStatement); // Move the variable declaration into the resource acquisition, if possible // This is necessary for the foreach-pattern to work on the result of the using-pattern VariableDeclarationStatement varDecl = FindVariableDeclaration(usingStatement, variableName); if (varDecl != null && varDecl.Parent is BlockStatement) { Statement declarationPoint; if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint)) { Debug.Assert(declarationPoint == usingStatement); // Moving the variable into the UsingStatement is allowed: usingStatement.ResourceAcquisition = new VariableDeclarationStatement { Type = (AstType)varDecl.Type.Clone(), Variables = { new VariableInitializer { Name = variableName, Initializer = m1.Get <Expression>("initializer").Single().Detach() }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition) } }.CopyAnnotationsFrom(node); } } return(usingStatement); } return(null); }
internal void HandleStaticFieldInitializers(IEnumerable <AstNode> members) { // Translate static constructor into field initializers if the class is BeforeFieldInit var staticCtor = members.OfType <ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); if (staticCtor != null) { IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; if (!ctorMethod.MetadataToken.IsNil) { var metadata = context.TypeSystem.MainModule.PEFile.Metadata; SRM.MethodDefinition ctorMethodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)ctorMethod.MetadataToken); SRM.TypeDefinition declaringType = metadata.GetTypeDefinition(ctorMethodDef.GetDeclaringType()); if (declaringType.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)) { while (true) { ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; if (es == null) { break; } AssignmentExpression assignment = es.Expression as AssignmentExpression; if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign) { break; } IMember fieldOrProperty = (assignment.Left.GetSymbol() as IMember)?.MemberDefinition; if (!(fieldOrProperty is IField || fieldOrProperty is IProperty) || !fieldOrProperty.IsStatic) { break; } AstNode fieldOrPropertyDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrProperty); if (fieldOrPropertyDecl == null) { break; } if (fieldOrPropertyDecl is FieldDeclaration fd) { fd.Variables.Single().Initializer = assignment.Right.Detach(); } else if (fieldOrPropertyDecl is PropertyDeclaration pd) { pd.Initializer = assignment.Right.Detach(); } else { break; } es.Remove(); } if (staticCtor.Body.Statements.Count == 0) { staticCtor.Remove(); } } } } }
public ForStatement TransformFor(ExpressionStatement node) { Match m1 = variableAssignPattern.Match(node); if (!m1.Success) { return(null); } var variable = m1.Get <IdentifierExpression>("variable").Single().GetILVariable(); AstNode next = node.NextSibling; if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable)) { node.Remove(); next.InsertChildAfter(null, node, ForStatement.InitializerRole); return((ForStatement)next); } Match m3 = forPattern.Match(next); if (!m3.Success) { return(null); } // ensure the variable in the for pattern is the same as in the declaration if (variable != m3.Get <IdentifierExpression>("ident").Single().GetILVariable()) { return(null); } WhileStatement loop = (WhileStatement)next; node.Remove(); BlockStatement newBody = new BlockStatement(); foreach (Statement stmt in m3.Get <Statement>("statement")) { newBody.Add(stmt.Detach()); } forStatement = new ForStatement(); forStatement.CopyAnnotationsFrom(loop); forStatement.Initializers.Add(node); forStatement.Condition = loop.Condition.Detach(); forStatement.Iterators.Add(m3.Get <Statement>("increment").Single().Detach()); forStatement.EmbeddedStatement = newBody; loop.ReplaceWith(forStatement); return(forStatement); }
public LockStatement TransformLock(ExpressionStatement node) { Match m1 = lockFlagInitPattern.Match(node); if (m1 == null) { return(null); } AstNode tryCatch = node.NextSibling; Match m2 = lockTryCatchPattern.Match(tryCatch); if (m2 == null) { return(null); } if (m1.Get <IdentifierExpression>("variable").Single().Identifier == m2.Get <IdentifierExpression>("flag").Single().Identifier) { Expression enter = m2.Get <Expression>("enter").Single(); IdentifierExpression exit = m2.Get <IdentifierExpression>("exit").Single(); if (exit.Match(enter) == null) { // If exit and enter are not the same, then enter must be "exit = ..." AssignmentExpression assign = enter as AssignmentExpression; if (assign == null) { return(null); } if (exit.Match(assign.Left) == null) { return(null); } enter = assign.Right; // TODO: verify that 'obj' variable can be removed } // TODO: verify that 'flag' variable can be removed // transform the code into a lock statement: LockStatement l = new LockStatement(); l.Expression = enter.Detach(); l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach(); ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove(); // Remove 'Enter()' call tryCatch.ReplaceWith(l); node.Remove(); // remove flag variable return(l); } return(null); }
public ForStatement TransformFor(ExpressionStatement node) { Match m1 = variableAssignPattern.Match(node); if (m1 == null) { return(null); } AstNode next = node.NextSibling; Match m2 = forPattern.Match(next); if (m2 == null) { return(null); } // ensure the variable in the for pattern is the same as in the declaration if (m1.Get <IdentifierExpression>("variable").Single().Identifier != m2.Get <IdentifierExpression>("ident").Single().Identifier) { return(null); } WhileStatement loop = (WhileStatement)next; node.Remove(); BlockStatement newBody = new BlockStatement(); foreach (Statement stmt in m2.Get <Statement>("statement")) { newBody.Add(stmt.Detach()); } ForStatement forStatement = new ForStatement(); forStatement.Initializers.Add(node); forStatement.Condition = loop.Condition.Detach(); forStatement.Iterators.Add(m2.Get <Statement>("increment").Single().Detach()); forStatement.EmbeddedStatement = newBody; loop.ReplaceWith(forStatement); return(forStatement); }