Exemplo n.º 1
0
 public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
 {
     Debug.Assert(currentMethod == null);
     try {
         currentMethod = constructorDeclaration.GetSymbol() as IMethod;
         return(base.VisitConstructorDeclaration(constructorDeclaration));
     } finally {
         currentMethod = null;
     }
 }
        public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
        {
            if (!(constructorDeclaration.Body.Statements.FirstOrDefault() is ExpressionStatement stmt))
            {
                return;
            }
            var currentCtor = (IMethod)constructorDeclaration.GetSymbol();
            ConstructorInitializer ci;

            switch (stmt.Expression)
            {
            // Pattern for reference types:
            // this..ctor(...);
            case InvocationExpression invocation:
                if (!(invocation.Target is MemberReferenceExpression mre) || mre.MemberName != ".ctor")
                {
                    return;
                }
                if (!(invocation.GetSymbol() is IMethod ctor && ctor.IsConstructor))
                {
                    return;
                }
                ci = new ConstructorInitializer();
                var target = mre.Target;
                // Ignore casts, those might be added if references are missing.
                if (target is CastExpression cast)
                {
                    target = cast.Expression;
                }
                if (target is ThisReferenceExpression or BaseReferenceExpression)
                {
                    if (ctor.DeclaringTypeDefinition == currentCtor.DeclaringTypeDefinition)
                    {
                        ci.ConstructorInitializerType = ConstructorInitializerType.This;
                    }
                    else
                    {
                        ci.ConstructorInitializerType = ConstructorInitializerType.Base;
                    }
                }
                else
                {
                    return;
                }
                // Move arguments from invocation to initializer:
                invocation.Arguments.MoveTo(ci.Arguments);
                // Add the initializer: (unless it is the default 'base()')
                if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0))
                {
                    constructorDeclaration.Initializer = ci.CopyAnnotationsFrom(invocation);
                }
                // Remove the statement:
                stmt.Remove();
                break;
Exemplo n.º 3
0
 public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
 {
     currentMember = constructorDeclaration.GetSymbol() as IMember;
     if (currentMember == null)
     {
         return;
     }
     SetContext();
     base.VisitConstructorDeclaration(constructorDeclaration);
     currentMember = null;
 }
Exemplo n.º 4
0
        public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
        {
            var oldMethod = currentMethod;

            try {
                currentMethod = constructorDeclaration.GetSymbol() as IMethod;
                return(base.VisitConstructorDeclaration(constructorDeclaration));
            } finally {
                currentMethod = oldMethod;
            }
        }
        public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
        {
            if (!(constructorDeclaration.Body.Statements.FirstOrDefault() is ExpressionStatement stmt))
            {
                return;
            }
            var currentCtor = (IMethod)constructorDeclaration.GetSymbol();
            ConstructorInitializer ci;

            switch (stmt.Expression)
            {
            // Pattern for reference types:
            // this..ctor(...);
            case InvocationExpression invocation:
                if (!(invocation.Target is MemberReferenceExpression mre) || mre.MemberName != ".ctor")
                {
                    return;
                }
                if (!(invocation.GetSymbol() is IMethod ctor && ctor.IsConstructor))
                {
                    return;
                }
                ci = new ConstructorInitializer();
                var target = mre.Target;
                // Ignore casts, those might be added if references are missing.
                if (target is CastExpression cast)
                {
                    target = cast.Expression;
                }
                if (target is ThisReferenceExpression)
                {
                    ci.ConstructorInitializerType = ConstructorInitializerType.This;
                }
                else if (target is BaseReferenceExpression)
                {
                    ci.ConstructorInitializerType = ConstructorInitializerType.Base;
                }
                else
                {
                    return;
                }
                // Move arguments from invocation to initializer:
                invocation.Arguments.MoveTo(ci.Arguments);
                // Add the initializer: (unless it is the default 'base()')
                if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0))
                {
                    constructorDeclaration.Initializer = ci.CopyAnnotationsFrom(invocation);
                }
                // Remove the statement:
                stmt.Remove();
                break;

            // Pattern for value types:
            // this = new TSelf(...);
            case AssignmentExpression assignment:
                if (!(assignment.Right is ObjectCreateExpression oce && oce.GetSymbol() is IMethod ctor2 && ctor2.DeclaringTypeDefinition == currentCtor.DeclaringTypeDefinition))
                {
                    return;
                }
                ci = new ConstructorInitializer();
                if (assignment.Left is ThisReferenceExpression)
                {
                    ci.ConstructorInitializerType = ConstructorInitializerType.This;
                }
                else
                {
                    return;
                }
                // Move arguments from invocation to initializer:
                oce.Arguments.MoveTo(ci.Arguments);
                // Add the initializer: (unless it is the default 'base()')
                if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0))
                {
                    constructorDeclaration.Initializer = ci.CopyAnnotationsFrom(oce);
                }
                // Remove the statement:
                stmt.Remove();
                break;

            default:
                return;
            }
            if (context.DecompileRun.RecordDecompilers.TryGetValue(currentCtor.DeclaringTypeDefinition, out var record) &&
                currentCtor.Equals(record.PrimaryConstructor) &&
                ci.ConstructorInitializerType == ConstructorInitializerType.Base)
            {
                if (constructorDeclaration.Parent is TypeDeclaration {
                    BaseTypes : { Count : >= 1 }
                } typeDecl)
                {
                    var baseType    = typeDecl.BaseTypes.First();
                    var newBaseType = new InvocationAstType();
                    baseType.ReplaceWith(newBaseType);
                    newBaseType.BaseType = baseType;
                    ci.Arguments.MoveTo(newBaseType.Arguments);
                }
                constructorDeclaration.Remove();
            }
        }