Exemplo n.º 1
0
        public sealed override ImmutableArray <Symbol> GetMembers()
        {
            //   Not making this lazy results in new symbols being created every
            //   time we call GetMembers(), which is not only inefficient but
            //   breaks reference equality.
            if (_members.IsDefault)
            {
                var mb = ArrayBuilder <Symbol> .GetInstance();

                mb.AddRange(base.GetMembers());
                //   This is slightly wrong, but we don't have any syntax to
                //   cling onto apart from this...
                var binder      = DeclaringCompilation.GetBinder(_parent.GetNonNullSyntaxNode());
                var diagnostics = DiagnosticBag.GetInstance();

                MakeMembers(mb, binder, diagnostics);
                AddDeclarationDiagnostics(diagnostics);

                ImmutableInterlocked.InterlockedInitialize(ref _members, mb.ToImmutableAndFree());
            }
            return(_members);
        }
        public override ImmutableArray <Symbol> GetMembers()
        {
            // @t-mawind
            //   Not making this lazy results in new symbols being created every
            //   time we call GetMembers(), which is not only inefficient but
            //   breaks reference equality.
            if (_members.IsDefault)
            {
                var mb = ArrayBuilder <Symbol> .GetInstance();

                mb.AddRange(base.GetMembers());

                // @t-mawind
                //   This is slightly wrong, but we don't have any syntax to
                //   cling onto apart from this...
                var binder = DeclaringCompilation.GetBinder(ContainingType.GetNonNullSyntaxNode());

                var diagnostics = DiagnosticBag.GetInstance();

                var memberSyntax = _concept.GetConceptDefaultMethods();
                foreach (var m in memberSyntax)
                {
                    var ms = m.GetSyntax() as MethodDeclarationSyntax;
                    if (ms == null)
                    {
                        continue;
                    }

                    mb.Add(SourceMemberMethodSymbol.CreateMethodSymbol(this, binder, ms, diagnostics));
                }

                AddDeclarationDiagnostics(diagnostics);

                ImmutableInterlocked.InterlockedInitialize(ref _members, mb.ToImmutableAndFree());
            }
            return(_members);
        }
        protected override BoundExpression GenerateCall(SyntheticBoundNodeFactory f, BoundExpression receiver, ImmutableArray <BoundExpression> arguments, ImmutableArray <RefKind> refKinds, DiagnosticBag diagnostics)
        {
            // For user-defined operators, the normal shim call approach works
            // fine.  However, we also want to permit shim calls into types
            // with builtin operators, for which we need to do an actual
            // lookup as to which operator we're defining, and a quick
            // jump into part of the operator overload resolution code to see
            // if we're actually in one of those types.
            //
            // This may be incomplete, but is probably(??) sound.
            // TODO(@MattWindsor91): consider refkinds?
            if (ImplementingMethod.OriginalDefinition is SourceUserDefinedOperatorSymbol op)
            {
                Debug.Assert(receiver.Kind == BoundKind.TypeExpression,
                             "receiver of an operator should always be a type");
                var rectype = (BoundTypeExpression)receiver;

                var opdecl = op.GetSyntax();
                Debug.Assert(opdecl != null, "should have operator syntax here");
                var opsyn  = opdecl.OperatorToken;
                var opkind = opsyn.Kind();

                var binder = DeclaringCompilation.GetBinder(ImplementingMethod.GetNonNullSyntaxNode()).WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.InShim, this);
                var ovr    = new OverloadResolution(binder);
                var ignore = new HashSet <DiagnosticInfo>();

                if (arguments.Length == 1)
                {
                    (var usuccess, var ukind) = TryGetUnaryOperatorKind(opsyn.Kind());
                    if (usuccess)
                    {
                        var result = UnaryOperatorOverloadResolutionResult.GetInstance();
                        ovr.UnaryOperatorOverloadResolution(ukind, arguments[0], result, ref ignore);
                        if (result.SingleValid())
                        {
                            var bsig = result.Best.Signature;
                            if (bsig.Method == null)
                            {
                                return(f.Unary(bsig.Kind, bsig.ReturnType, arguments[0]));
                            }
                        }
                    }
                }
                else if (arguments.Length == 2)
                {
                    (var bsuccess, var bkind) = TryGetBinaryOperatorKind(opsyn.Kind());
                    if (bsuccess)
                    {
                        var result = BinaryOperatorOverloadResolutionResult.GetInstance();
                        ovr.BinaryOperatorOverloadResolution(bkind, arguments[0], arguments[1], result, ref ignore);
                        if (result.SingleValid())
                        {
                            var bsig = result.Best.Signature;
                            if (bsig.Method == null)
                            {
                                return(f.Binary(bsig.Kind, bsig.ReturnType, arguments[0], arguments[1]));
                            }
                        }
                    }
                }
            }

            return(base.GenerateCall(f, receiver, arguments, refKinds, diagnostics));
        }