Пример #1
0
        public void TestReplaceBaseType()
        {
            var context = TestRefactoringContext.Create(@"
public class $Foo : System.IDisposable
{
}");

            using (var script = context.StartScript()) {
                var type = context.GetNode <TypeDeclaration>();
                script.ChangeBaseTypes(type, new AstType[] { AstType.Create("System.Test") });
            }

            Assert.AreEqual(@"
public class Foo : System.Test
{
}", context.Text);
        }
Пример #2
0
        /// <summary>
        /// Decompile the specified expression, given the network, process, method, and statement
        /// </summary>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to decompile</param>
        protected Expression Decompile(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            if (expression is ICSharpCode.Decompiler.CSharp.Syntax.AssignmentExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.AssignmentExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
            {
                var mr = expression as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression;

                if (mr.ToString() == "base.ShouldContinue")
                {
                    return new PrimitiveExpression(true, method.SourceMethod.Module.ImportReference(typeof(bool)))
                           {
                               SourceExpression = mr,
                               Parent           = statement,
                           }
                }
                ;

                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.BinaryOperatorExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.CastExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.CastExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ConditionalExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.ConditionalExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression)
            {
                var si = expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression;
                var mt = si.Target as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression;

                if (mt.ToString() == "base.PrintDebug" || mt.ToString() == "base.SimulationOnly")
                {
                    return new EmptyExpression()
                           {
                               SourceExpression = si,
                               Parent           = statement
                           }
                }
                ;

                if (mt.ToString() == "Console.WriteLine" || mt.ToString() == "Console.Write")
                {
                    return new EmptyExpression()
                           {
                               SourceExpression = si,
                               Parent           = statement
                           }
                }
                ;


                // Catch common translations
                if (mt != null && (expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression).Arguments.Count == 1)
                {
                    if (mt.MemberName == "op_Implicit" || mt.MemberName == "op_Explicit")
                    {
                        var mtm = Decompile(network, proc, method, statement, mt);
                        return(Decompile(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.CastExpression(AstType.Create(mtm.SourceResultType.FullName), si.Arguments.First().Clone())));
                    }
                    else if (mt.MemberName == "op_Increment")
                    {
                        return(Decompile(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression(UnaryOperatorType.Increment, si.Arguments.First().Clone())));
                    }
                    else if (mt.MemberName == "op_Decrement")
                    {
                        return(Decompile(network, proc, method, statement, new ICSharpCode.Decompiler.CSharp.Syntax.UnaryOperatorExpression(UnaryOperatorType.Decrement, si.Arguments.First().Clone())));
                    }
                }

                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ParenthesizedExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.ParenthesizedExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.NullReferenceExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.NullReferenceExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.ArrayCreateExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.ArrayCreateExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.CheckedExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.CheckedExpression));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.UncheckedExpression)
            {
                return(Decompile(network, proc, method, statement, expression as ICSharpCode.Decompiler.CSharp.Syntax.UncheckedExpression));
            }
            else if (expression == ICSharpCode.Decompiler.CSharp.Syntax.Expression.Null)
            {
                return new EmptyExpression()
                       {
                           SourceExpression = expression
                       }
            }
            ;
            else
            {
                throw new Exception(string.Format("Unsupported expression: {0} ({1})", expression, expression.GetType().FullName));
            }
        }
            void Fix(Script script, MethodDeclaration methodDeclaration, TypeDeclaration typeDeclaration)
            {
                var newTypeDeclaration = (TypeDeclaration)typeDeclaration.Clone();

                var resolver = ctx.GetResolverStateAfter(typeDeclaration.LBraceToken);

                var  typeResolve           = resolver.ResolveSimpleName("IDisposable", new List <IType>()) as TypeResolveResult;
                bool canShortenIDisposable = typeResolve != null && typeResolve.Type.FullName == "System.IDisposable";

                string interfaceName = (canShortenIDisposable ? string.Empty : "System.") + "IDisposable";

                newTypeDeclaration.BaseTypes.Add(new SimpleType(interfaceName));

                foreach (var method in DisposeMethods(newTypeDeclaration).ToList())
                {
                    if (typeDeclaration.ClassType == ClassType.Interface)
                    {
                        method.Remove();
                    }
                    else
                    {
                        method.Modifiers &= ~Modifiers.Private;
                        method.Modifiers &= ~Modifiers.Protected;
                        method.Modifiers &= ~Modifiers.Internal;
                        method.Modifiers |= Modifiers.Public;
                    }
                }

                if (typeDeclaration.ClassType == ClassType.Interface)
                {
                    var disposeMember = ((MemberResolveResult)ctx.Resolve(methodDeclaration)).Member;
                    script.DoGlobalOperationOn(new List <IEntity>()
                    {
                        disposeMember
                    }, (nCtx, nScript, nodes) =>
                    {
                        List <Tuple <AstType, AstType> > pendingChanges = new List <Tuple <AstType, AstType> >();
                        foreach (var node in nodes)
                        {
                            var method = node as MethodDeclaration;
                            if (method != null && !method.PrivateImplementationType.IsNull)
                            {
                                var nResolver = ctx.GetResolverStateAfter(typeDeclaration.LBraceToken);

                                var nTypeResolve            = nResolver.ResolveSimpleName("IDisposable", new List <IType>()) as TypeResolveResult;
                                bool nCanShortenIDisposable = nTypeResolve != null && nTypeResolve.Type.FullName == "System.IDisposable";

                                string nInterfaceName = (nCanShortenIDisposable ? string.Empty : "System.") + "IDisposable";

                                pendingChanges.Add(Tuple.Create(method.PrivateImplementationType, AstType.Create(nInterfaceName)));
                            }
                        }

                        foreach (var change in pendingChanges)
                        {
                            nScript.Replace(change.Item1, change.Item2);
                        }
                    }, "Fix explicitly implemented members");
                }

                script.Replace(typeDeclaration, newTypeDeclaration);
            }
Пример #4
0
 public IsExpression IsType(Type type)
 {
     return(new IsExpression {
         Type = AstType.Create(type), Expression = this
     });
 }
Пример #5
0
 public AsExpression CastAs(Type type)
 {
     return(new AsExpression {
         Type = AstType.Create(type), Expression = this
     });
 }
Пример #6
0
 public CastExpression CastTo(Type type)
 {
     return(new CastExpression {
         Type = AstType.Create(type), Expression = this
     });
 }
Пример #7
0
        public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
        {
            if (!methodDeclaration.Body.IsNull)
            {
                base.VisitMethodDeclaration(methodDeclaration);
                return;
            }

            if (methodDeclaration.Name == "ToString" && methodDeclaration.Parameters.Count == 0)
            {
                methodDeclaration.Modifiers |= Modifiers.Override;
            }

            methodDeclaration.Modifiers |= Modifiers.Public;
            methodDeclaration.Body       = new BlockStatement {
                BindMethodBody(methodDeclaration)
            };

            base.VisitMethodDeclaration(methodDeclaration);

            if (IsIgnored(methodDeclaration))
            {
                methodDeclaration.Remove();
            }

            RemoveAttributes(methodDeclaration.Attributes);

            var typeDeclaration = methodDeclaration.GetParent <TypeDeclaration> ();

            if (typeDeclaration == null ||
                !CurrentTypeData.IsReadOnlyList ||
                methodDeclaration.Name != "Item")
            {
                return;
            }

            var indexerDeclaration = new IndexerDeclaration {
                Modifiers  = Modifiers.Public,
                ReturnType = methodDeclaration.ReturnType.Clone(),
                Getter     = new Accessor {
                    Body = (BlockStatement)methodDeclaration.Body.Clone()
                }
            };

            foreach (var param in methodDeclaration.Parameters)
            {
                indexerDeclaration.Parameters.Add(param.Clone());
            }

            methodDeclaration.ReplaceWith(indexerDeclaration);

            typeDeclaration.BaseTypes.Add(
                new SimpleType("IReadOnlyList", methodDeclaration.ReturnType.Clone())
                );

            var forStatement = new ForStatement {
                Initializers =
                {
                    new VariableDeclarationStatement(
                        indexerDeclaration.Parameters.First().Type.Clone(),
                        "i",
                        new PrimitiveExpression(0)
                        ),
                    new ExpressionStatement(
                        new AssignmentExpression(
                            new IdentifierExpression("n"),
                            new IdentifierExpression("Count")
                            )
                        )
                },
                Condition = new BinaryOperatorExpression(
                    new IdentifierExpression("i"),
                    BinaryOperatorType.LessThan,
                    new IdentifierExpression("n")
                    ),
                Iterators =
                {
                    new ExpressionStatement(
                        new UnaryOperatorExpression(
                            UnaryOperatorType.PostIncrement,
                            new IdentifierExpression("i")
                            )
                        )
                },
                EmbeddedStatement = new YieldReturnStatement {
                    Expression = new IndexerExpression(
                        new ThisReferenceExpression(),
                        new IdentifierExpression("i")
                        )
                },
            };

            typeDeclaration.Members.Add(new MethodDeclaration {
                Modifiers  = Modifiers.Public,
                Name       = "GetEnumerator",
                ReturnType = new SimpleType("IEnumerator", methodDeclaration.ReturnType.Clone()),
                Body       = new BlockStatement {
                    forStatement
                }
            });

            typeDeclaration.Members.Add(new MethodDeclaration {
                Name       = "IEnumerable.GetEnumerator",
                ReturnType = AstType.Create("IEnumerator"),
                Body       = new BlockStatement {
                    new ReturnStatement(
                        new IdentifierExpression("GetEnumerator").Invoke()
                        )
                }
            });
        }