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(); } }
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(); } }