internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) { var F = new SyntheticBoundNodeFactory(this, ContainingType.GetNonNullSyntaxNode(), compilationState, diagnostics); try { ImmutableArray <Symbol> printableMembers = ContainingType.GetMembers().WhereAsArray(m => isPrintable(m)); if (ReturnType.IsErrorType() || printableMembers.Any(static m => m.GetTypeOrReturnType().Type.IsErrorType()))
internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) { var F = new SyntheticBoundNodeFactory(this, ContainingType.GetNonNullSyntaxNode(), compilationState, diagnostics); try { ImmutableArray <Symbol> printableMembers = ContainingType.GetMembers().WhereAsArray(m => isPrintable(m)); if (ReturnType.IsErrorType() || printableMembers.Any(m => m.GetTypeOrReturnType().Type.IsErrorType())) { F.CloseMethod(F.ThrowNull()); return; } ArrayBuilder <BoundStatement> block; BoundParameter builder = F.Parameter(this.Parameters[0]); if (ContainingType.BaseTypeNoUseSiteDiagnostics.IsObjectType() || ContainingType.IsRecordStruct) { if (printableMembers.IsEmpty) { // return false; F.CloseMethod(F.Return(F.Literal(false))); return; } block = ArrayBuilder <BoundStatement> .GetInstance(); if (!ContainingType.IsRecordStruct) { var ensureStackMethod = F.WellKnownMethod( WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__EnsureSufficientExecutionStack, isOptional: true); if (ensureStackMethod is not null) { block.Add(F.ExpressionStatement( F.Call(receiver: null, ensureStackMethod))); } } } else { MethodSymbol?basePrintMethod = OverriddenMethod; if (basePrintMethod is null || basePrintMethod.ReturnType.SpecialType != SpecialType.System_Boolean) { F.CloseMethod(F.ThrowNull()); // an error was reported in base checks already return; } var basePrintCall = F.Call(receiver: F.Base(ContainingType.BaseTypeNoUseSiteDiagnostics), basePrintMethod, builder); if (printableMembers.IsEmpty) { // return base.PrintMembers(builder); F.CloseMethod(F.Return(basePrintCall)); return; } else { block = ArrayBuilder <BoundStatement> .GetInstance(); // if (base.PrintMembers(builder)) // builder.Append(", ") block.Add(F.If(basePrintCall, makeAppendString(F, builder, ", "))); } } Debug.Assert(!printableMembers.IsEmpty); for (var i = 0; i < printableMembers.Length; i++) { // builder.Append(", <name> = "); // if previous members exist // builder.Append("<name> = "); // if it is the first member // The only printable members are fields and properties, // which cannot be generic so as to have variant names var member = printableMembers[i]; var memberHeader = $"{member.Name} = "; if (i > 0) { memberHeader = ", " + memberHeader; } block.Add(makeAppendString(F, builder, memberHeader)); var value = member.Kind switch { SymbolKind.Field => F.Field(F.This(), (FieldSymbol)member), SymbolKind.Property => F.Property(F.This(), (PropertySymbol)member), _ => throw ExceptionUtilities.UnexpectedValue(member.Kind) }; // builder.Append((object)<value>); OR builder.Append(<value>.ToString()); for value types Debug.Assert(value.Type is not null); if (value.Type.IsValueType) { block.Add(F.ExpressionStatement( F.Call(receiver: builder, F.WellKnownMethod(WellKnownMember.System_Text_StringBuilder__AppendString), F.Call(value, F.SpecialMethod(SpecialMember.System_Object__ToString))))); } else { block.Add(F.ExpressionStatement( F.Call(receiver: builder, F.WellKnownMethod(WellKnownMember.System_Text_StringBuilder__AppendObject), F.Convert(F.SpecialType(SpecialType.System_Object), value)))); } } block.Add(F.Return(F.Literal(true))); F.CloseMethod(F.Block(block.ToImmutableAndFree())); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); F.CloseMethod(F.ThrowNull()); }