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) { bool ctorIsUnsafe = staticCtor.HasModifier(Modifiers.Unsafe); 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; } var fieldOrPropertyDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrProperty) as EntityDeclaration; if (fieldOrPropertyDecl == null) { break; } if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(assignment.Right)) { fieldOrPropertyDecl.Modifiers |= Modifiers.Unsafe; } 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(); } } } } }
internal void HandleInstanceFieldInitializers(IEnumerable <AstNode> members) { var instanceCtors = members.OfType <ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray(); if (instanceCtorsNotChainingWithThis.Length > 0) { var ctorMethodDef = instanceCtorsNotChainingWithThis[0].GetSymbol() as IMethod; if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsReferenceType == false) { return; } bool ctorIsUnsafe = instanceCtorsNotChainingWithThis.All(c => c.HasModifier(Modifiers.Unsafe)); // Recognize field or property initializers: // Translate first statement in all ctors (if all ctors have the same statement) into an initializer. bool allSame; do { Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault()); if (!m.Success) { break; } IMember fieldOrPropertyOrEvent = (m.Get <AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition; if (!(fieldOrPropertyOrEvent is IField) && !(fieldOrPropertyOrEvent is IProperty) && !(fieldOrPropertyOrEvent is IEvent)) { break; } var fieldOrPropertyOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrPropertyOrEvent) as EntityDeclaration; // Cannot transform if member is not found or if it is a custom event. if (fieldOrPropertyOrEventDecl == null || fieldOrPropertyOrEventDecl is CustomEventDeclaration) { break; } Expression initializer = m.Get <Expression>("initializer").Single(); // 'this'/'base' cannot be used in initializers if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression)) { break; } allSame = true; for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++) { var otherMatch = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()); if (!otherMatch.Success) { allSame = false; break; } var otherMember = (otherMatch.Get <AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition; if (!otherMember.Equals(fieldOrPropertyOrEvent)) { allSame = false; } if (!initializer.IsMatch(otherMatch.Get <AstNode>("initializer").Single())) { allSame = false; } } if (allSame) { foreach (var ctor in instanceCtorsNotChainingWithThis) { ctor.Body.First().Remove(); } if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(initializer)) { fieldOrPropertyOrEventDecl.Modifiers |= Modifiers.Unsafe; } if (fieldOrPropertyOrEventDecl is PropertyDeclaration pd) { pd.Initializer = initializer.Detach(); } else { fieldOrPropertyOrEventDecl.GetChildrenByRole(Roles.Variable).Single().Initializer = initializer.Detach(); } } } while (allSame); } }