| File: Symbols\Synthesized\Records\SynthesizedRecordToString.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// <summary> /// The record includes a synthesized override of object.ToString(). /// For `record R(int I) { public int J; }` it prints `R { I = ..., J = ... }`. /// /// The method can be declared explicitly. It is an error if the explicit /// declaration does not match the expected signature or accessibility, or /// if the explicit declaration doesn't allow overriding it in a derived type and /// the record type is not sealed. /// It is an error if either synthesized or explicitly declared method doesn't /// override `object.ToString()` (for example, due to shadowing in intermediate base types, etc.). /// </summary> internal sealed class SynthesizedRecordToString : SynthesizedRecordObjectMethod { private readonly MethodSymbol _printMethod; public SynthesizedRecordToString(SourceMemberContainerTypeSymbol containingType, MethodSymbol printMethod, int memberOffset) : base( containingType, WellKnownMemberNames.ObjectToString, memberOffset, isReadOnly: printMethod.IsEffectivelyReadOnly) { Debug.Assert(printMethod is object); _printMethod = printMethod; } protected override SpecialMember OverriddenSpecialMember => SpecialMember.System_Object__ToString; protected override (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters) MakeParametersAndBindReturnType(BindingDiagnosticBag diagnostics) { var compilation = DeclaringCompilation; var location = ReturnTypeLocation; var annotation = ContainingType.IsRecordStruct ? NullableAnnotation.Oblivious : NullableAnnotation.NotAnnotated; return (ReturnType: TypeWithAnnotations.Create(Binder.GetSpecialType(compilation, SpecialType.System_String, location, diagnostics), annotation), Parameters: ImmutableArray<ParameterSymbol>.Empty); } protected override int GetParameterCountFromSyntax() => 0; internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) { var F = new SyntheticBoundNodeFactory(this, this.SyntaxNode, compilationState, diagnostics); try { CSharpCompilation compilation = ContainingType.DeclaringCompilation; var stringBuilder = F.WellKnownType(WellKnownType.System_Text_StringBuilder); var stringBuilderCtor = F.WellKnownMethod(WellKnownMember.System_Text_StringBuilder__ctor); var builderLocalSymbol = F.SynthesizedLocal(stringBuilder); BoundLocal builderLocal = F.Local(builderLocalSymbol); var block = ArrayBuilder<BoundStatement>.GetInstance(); // var builder = new StringBuilder(); block.Add(F.Assignment(builderLocal, F.New(stringBuilderCtor))); // builder.Append(<name>); block.Add(makeAppendString(F, builderLocal, ContainingType.Name)); // builder.Append(" { "); block.Add(makeAppendString(F, builderLocal, " { ")); // if (this.PrintMembers(builder)) builder.Append(' '); block.Add(F.If(F.Call(F.This(), _printMethod, builderLocal), makeAppendChar(F, builderLocal, ' '))); // builder.Append('}'); block.Add(makeAppendChar(F, builderLocal, '}')); // return builder.ToString(); block.Add(F.Return(F.Call(builderLocal, F.SpecialMethod(SpecialMember.System_Object__ToString)))); F.CloseMethod(F.Block(ImmutableArray.Create(builderLocalSymbol), block.ToImmutableAndFree())); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); F.CloseMethod(F.ThrowNull()); } static BoundStatement makeAppendString(SyntheticBoundNodeFactory F, BoundLocal builder, string value) { return F.ExpressionStatement(F.Call(receiver: builder, F.WellKnownMethod(WellKnownMember.System_Text_StringBuilder__AppendString), F.StringLiteral(value))); } static BoundStatement makeAppendChar(SyntheticBoundNodeFactory F, BoundLocal builder, char value) { return F.ExpressionStatement(F.Call(receiver: builder, F.WellKnownMethod(WellKnownMember.System_Text_StringBuilder__AppendChar), F.CharLiteral(value))); } } } }