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;
        public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
        {
            var stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;

            if (stmt == null)
            {
                return;
            }
            if (!(stmt.Expression is InvocationExpression invocation))
            {
                return;
            }
            if (invocation.Target is MemberReferenceExpression mre && mre.MemberName == ".ctor")
            {
                ConstructorInitializer 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();
            }
        }
예제 #3
0
        public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
        {
            ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;

            if (stmt == null)
            {
                return;
            }
            InvocationExpression invocation = stmt.Expression as InvocationExpression;

            if (invocation == null)
            {
                return;
            }
            MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;

            if (mre != null && mre.MemberName == ".ctor")
            {
                ConstructorInitializer ci = new ConstructorInitializer();
                if (mre.Target is ThisReferenceExpression)
                {
                    ci.ConstructorInitializerType = ConstructorInitializerType.This;
                }
                else if (mre.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();
            }
        }
        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();
            }
        }