internal override void GenerateMethodBody(
            TypeCompilationState compilationState,
            BindingDiagnosticBag diagnostics
            )
        {
            var F = new SyntheticBoundNodeFactory(
                this,
                ContainingType.GetNonNullSyntaxNode(),
                compilationState,
                diagnostics
                );

            try
            {
                // => (object)left == right || ((object)left != null && left.Equals(right));
                MethodSymbol?equals = null;
                foreach (var member in ContainingType.GetMembers(WellKnownMemberNames.ObjectEquals))
                {
                    if (
                        member is MethodSymbol candidate &&
                        candidate.ParameterCount == 1 &&
                        candidate.Parameters[0].RefKind == RefKind.None &&
                        candidate.ReturnType.SpecialType == SpecialType.System_Boolean &&
                        !candidate.IsStatic &&
                        candidate.Parameters[0].Type.Equals(
                            ContainingType,
                            TypeCompareKind.AllIgnoreOptions
                            )
                        )
                    {
                        equals = candidate;
                        break;
                    }
                }

                if (equals is null)
                {
                    // Unable to locate expected method, an error was reported elsewhere
                    F.CloseMethod(F.ThrowNull());
                    return;
                }

                var left  = F.Parameter(Parameters[0]);
                var right = F.Parameter(Parameters[1]);

                BoundExpression objectEqual  = F.ObjectEqual(left, right);
                BoundExpression recordEquals = F.LogicalAnd(
                    F.ObjectNotEqual(left, F.Null(F.SpecialType(SpecialType.System_Object))),
                    F.Call(left, equals, right)
                    );

                F.CloseMethod(F.Block(F.Return(F.LogicalOr(objectEqual, recordEquals))));
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
            {
                diagnostics.Add(ex.Diagnostic);
                F.CloseMethod(F.ThrowNull());
            }
        }
        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()))
Exemple #3
0
        private FieldSymbol GetAutoField(BindContext context)
        {
            PropertySymbol containingProperty = (PropertySymbol)context.GetSymbol(RoslynSymbol.AssociatedSymbol);

            foreach (var field in ContainingType.GetMembers <FieldSymbol>(context))
            {
                if (field.RoslynSymbol.AssociatedSymbol != null &&
                    field.RoslynSymbol.AssociatedSymbol.Equals(containingProperty.RoslynSymbol))
                {
                    return(field);
                }
            }

            return(null);
        }
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            var F = new SyntheticBoundNodeFactory(this, ContainingType.GetNonNullSyntaxNode(), compilationState, diagnostics);

            try
            {
                // => !(r1 == r2);
                F.CloseMethod(F.Block(F.Return(F.Not(F.Call(receiver: null, ContainingType.GetMembers(WellKnownMemberNames.EqualityOperatorName).OfType <SynthesizedRecordEqualityOperator>().Single(),
                                                            F.Parameter(Parameters[0]), F.Parameter(Parameters[1]))))));
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
            {
                diagnostics.Add(ex.Diagnostic);
                F.CloseMethod(F.ThrowNull());
            }
        }
        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());
            }