示例#1
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundStatement node, MethodSymbol method = null, CSharpSyntaxNode syntax = null)
        {
            if (syntax == null)
            {
                syntax = node.Syntax;
            }

            BoundStatement ret =
                (object)method != null && (object)method.IteratorElementType != null
                ? BoundYieldBreakStatement.Synthesized(syntax) as BoundStatement
                : BoundReturnStatement.Synthesized(syntax, null);

            if (syntax.Kind == SyntaxKind.Block)
            {
                var blockSyntax = (BlockSyntax)syntax;

                ret = new BoundSequencePointWithSpan(
                    blockSyntax,
                    ret,
                    blockSyntax.CloseBraceToken.Span)
                {
                    WasCompilerGenerated = true
                };
            }

            switch (node.Kind)
            {
            case BoundKind.Block:
                var block = (BoundBlock)node;
                return(block.Update(block.LocalsOpt, block.Statements.Add(ret)));

            default:
                return(new BoundBlock(syntax, ImmutableArray <LocalSymbol> .Empty, ImmutableArray.Create(ret, node)));
            }
        }
示例#2
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax = null)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            if (syntax == null)
            {
                syntax = body.Syntax;
            }

            Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause));

            BoundStatement ret = method.IsIterator
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, null);

            // Implicitly added return for async method does not need sequence points since lowering would add one.
            if (syntax.IsKind(SyntaxKind.Block) && !method.IsAsync)
            {
                var blockSyntax = (BlockSyntax)syntax;

                ret = new BoundSequencePointWithSpan(
                    blockSyntax,
                    ret,
                    blockSyntax.CloseBraceToken.Span)
                {
                    WasCompilerGenerated = true
                };
            }

            return(body.Update(body.Locals, body.Statements.Add(ret)));
        }
示例#3
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            SyntaxNode syntax = body.Syntax;

            Debug.Assert(body.WasCompilerGenerated ||
                         syntax.IsKind(SyntaxKind.Block) ||
                         syntax.IsKind(SyntaxKind.ArrowExpressionClause) ||
                         syntax.IsKind(SyntaxKind.ConstructorDeclaration));

            BoundStatement ret = (method.IsIterator && !method.IsAsync)
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, RefKind.None, null);

            return(body.Update(body.Locals, body.LocalFunctions, body.Statements.Add(ret)));
        }
示例#4
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundStatement node, MethodSymbol method, CSharpSyntaxNode syntax = null)
        {
            Debug.Assert(method != null);

            if (syntax == null)
            {
                syntax = node.Syntax;
            }

            BoundStatement ret = method.IsIterator
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, null);

            if (syntax.Kind() == SyntaxKind.Block)
            {
                // Implicitly added return for async method does not need sequence points since lowering would add one.
                if (!method.IsAsync)
                {
                    var blockSyntax = (BlockSyntax)syntax;

                    ret = new BoundSequencePointWithSpan(
                        blockSyntax,
                        ret,
                        blockSyntax.CloseBraceToken.Span)
                    {
                        WasCompilerGenerated = true
                    };
                }
            }

            switch (node.Kind)
            {
            case BoundKind.Block:
                var block = (BoundBlock)node;
                return(block.Update(block.Locals, block.Statements.Add(ret)));

            default:
                return(new BoundBlock(syntax, ImmutableArray <LocalSymbol> .Empty, ImmutableArray.Create(ret, node)));
            }
        }
示例#5
0
        /// <summary>
        /// Generate a thread-safe accessor for a WinRT field-like event.
        ///
        /// Add:
        ///   return EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddEventHandler(value);
        ///
        /// Remove:
        ///   EventRegistrationTokenTable&lt;Event&gt;.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveEventHandler(value);
        /// </summary>
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;

            Debug.Assert((object)accessor != null);

            FieldSymbol field = eventSymbol.AssociatedField;

            Debug.Assert((object)field != null);

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;

            Debug.Assert(fieldType.Name == "EventRegistrationTokenTable");

            MethodSymbol getOrCreateMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable,
                diagnostics,
                syntax: syntax);

            if ((object)getOrCreateMethod == null)
            {
                Debug.Assert(diagnostics.HasAnyErrors());
                return(null);
            }

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

            WellKnownMember processHandlerMember = isAddMethod
                ? WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler
                : WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler;

            MethodSymbol processHandlerMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                processHandlerMember,
                diagnostics,
                syntax: syntax);

            if ((object)processHandlerMethod == null)
            {
                Debug.Assert(diagnostics.HasAnyErrors());
                return(null);
            }

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

            // _tokenTable
            BoundFieldAccess fieldAccess = new BoundFieldAccess(
                syntax,
                field.IsStatic ? null : new BoundThisReference(syntax, accessor.ThisParameter.Type),
                field,
                constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
            BoundCall getOrCreateCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: getOrCreateMethod,
                arg0: fieldAccess);

            // value
            BoundParameter parameterAccess = new BoundParameter(
                syntax,
                accessor.Parameters.Single());

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value) // or RemoveHandler
            BoundCall processHandlerCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: getOrCreateCall,
                method: processHandlerMethod,
                arg0: parameterAccess);

            if (isAddMethod)
            {
                // {
                //     return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
                // }
                BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, processHandlerCall);
                return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement));
            }
            else
            {
                // {
                //     EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
                //     return;
                // }
                BoundStatement callStatement   = new BoundExpressionStatement(syntax, processHandlerCall);
                BoundStatement returnStatement = new BoundReturnStatement(syntax, expressionOpt: null);
                return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement));
            }
        }