780615ead0065bb9cb85d04c34a08b4c70948693
[platform/upstream/dotnet/runtime.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 using System.Collections.Generic;
5 using System.Runtime.InteropServices.JavaScript;
6 using Microsoft.CodeAnalysis.CSharp;
7 using Microsoft.CodeAnalysis.CSharp.Syntax;
8 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
9
10 namespace Microsoft.Interop.JavaScript
11 {
12     internal sealed class TaskJSGenerator : BaseJSGenerator
13     {
14         private MarshalerType _resultMarshalerType;
15         public TaskJSGenerator(MarshalerType resultMarshalerType)
16             : base(MarshalerType.Task, new Forwarder())
17         {
18             _resultMarshalerType = resultMarshalerType;
19         }
20
21         public override IEnumerable<ExpressionSyntax> GenerateBind(TypePositionInfo info, StubCodeContext context)
22         {
23             var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)info.MarshallingAttributeInfo).TypeInfo;
24             if (jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void))
25             {
26                 yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task), ArgumentList());
27             }
28             else
29             {
30                 yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task),
31                     ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_resultMarshalerType)))));
32             }
33         }
34
35         public override IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
36         {
37             var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)info.MarshallingAttributeInfo).TypeInfo;
38
39             string argName = context.GetAdditionalIdentifier(info, "js_arg");
40             var target = info.IsManagedReturnPosition
41                 ? Constants.ArgumentReturn
42                 : argName;
43
44             var source = info.IsManagedReturnPosition
45                 ? Argument(IdentifierName(context.GetIdentifiers(info).native))
46                 : _inner.AsArgument(info, context);
47
48             if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && info.IsManagedReturnPosition)
49             {
50                 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
51                     ? ToManagedMethodVoid(target, source)
52                     : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
53             }
54
55             if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && info.IsManagedReturnPosition)
56             {
57                 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
58                     ? ToJSMethodVoid(target, source)
59                     : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
60             }
61
62             foreach (var x in base.Generate(info, context))
63             {
64                 yield return x;
65             }
66
67             if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsManagedReturnPosition)
68             {
69                 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
70                     ? ToJSMethodVoid(target, source)
71                     : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
72             }
73
74             if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsManagedReturnPosition)
75             {
76                 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
77                     ? ToManagedMethodVoid(target, source)
78                     : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
79             }
80         }
81
82         private StatementSyntax ToManagedMethodVoid(string target, ArgumentSyntax source)
83         {
84             return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
85                     IdentifierName(target), GetToManagedMethod(Type)))
86                     .WithArgumentList(ArgumentList(SingletonSeparatedList(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))));
87         }
88
89         private StatementSyntax ToJSMethodVoid(string target, ArgumentSyntax source)
90         {
91             return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
92                     IdentifierName(target), GetToJSMethod(Type)))
93                     .WithArgumentList(ArgumentList(SingletonSeparatedList(source))));
94         }
95
96         private StatementSyntax ToManagedMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
97         {
98             return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
99                     IdentifierName(target), GetToManagedMethod(Type)))
100                 .WithArgumentList(ArgumentList(SeparatedList(new[]{
101                     source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
102                     Argument(ParenthesizedLambdaExpression()
103                     .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
104                     .WithParameterList(ParameterList(SeparatedList(new[]{
105                         Parameter(Identifier("__task_result_arg"))
106                         .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword)))
107                         .WithType(IdentifierName(Constants.JSMarshalerArgumentGlobal)),
108                         Parameter(Identifier("__task_result"))
109                         .WithModifiers(TokenList(Token(SyntaxKind.OutKeyword)))
110                         .WithType(sourceType)})))
111                     .WithBlock(Block(SingletonList<StatementSyntax>(ExpressionStatement(
112                         InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
113                         IdentifierName("__task_result_arg"), GetToManagedMethod(_resultMarshalerType)))
114                         .WithArgumentList(ArgumentList(SeparatedList(new[]{
115                             Argument(IdentifierName("__task_result")).WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
116                         }))))))))}))));
117         }
118
119         private StatementSyntax ToJSMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
120         {
121             return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
122                     IdentifierName(target), GetToJSMethod(Type)))
123                 .WithArgumentList(ArgumentList(SeparatedList(new[]{
124                     source,
125                     Argument(ParenthesizedLambdaExpression()
126                     .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
127                     .WithParameterList(ParameterList(SeparatedList(new[]{
128                         Parameter(Identifier("__task_result_arg"))
129                         .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword)))
130                         .WithType(IdentifierName(Constants.JSMarshalerArgumentGlobal)),
131                         Parameter(Identifier("__task_result"))
132                         .WithType(sourceType)})))
133                     .WithBlock(Block(SingletonList<StatementSyntax>(ExpressionStatement(
134                         InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
135                         IdentifierName("__task_result_arg"), GetToJSMethod(_resultMarshalerType)))
136                         .WithArgumentList(ArgumentList(SeparatedList(new[]{
137                             Argument(IdentifierName("__task_result")),
138                         }))))))))}))));
139         }
140     }
141 }