• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Sholtee / proxygen / 1060

02 May 2025 09:09AM UTC coverage: 92.623% (-0.08%) from 92.705%
1060

push

appveyor

Sholtee
fix RoslynV3 ParameterList issue

4859 of 5246 relevant lines covered (92.62%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.35
/SRC/Private/SyntaxFactories/ClassSyntaxFactoryBase.Method.cs
1
/********************************************************************************
2
* ClassSyntaxFactoryBase.Method.cs                                              *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Collections.Generic;
8
using System.Diagnostics;
9
using System.Linq;
10

11
using Microsoft.CodeAnalysis;
12
using Microsoft.CodeAnalysis.CSharp;
13
using Microsoft.CodeAnalysis.CSharp.Syntax;
14

15
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
16

17
namespace Solti.Utils.Proxy.Internals
18
{
19
    internal partial class ClassSyntaxFactoryBase
20
    {
21
        private static ArgumentListSyntax ResolveArgumentList(IMethodInfo method, IEnumerable<ArgumentSyntax> arguments) => ArgumentList
1✔
22
        (
1✔
23
            arguments.ToSyntaxList
1✔
24
            (
1✔
25
                (arg, i) => method.Parameters[i].Kind switch
1✔
26
                {
1✔
27
                    ParameterKind.In => arg.WithRefKindKeyword
1✔
28
                    (
1✔
29
                        refKindKeyword: Token(SyntaxKind.InKeyword)
1✔
30
                    ),
1✔
31
                    ParameterKind.Out => arg.WithRefKindKeyword
1✔
32
                    (
1✔
33
                        refKindKeyword: Token(SyntaxKind.OutKeyword)
1✔
34
                    ),
1✔
35
                    ParameterKind.Ref => arg.WithRefKindKeyword
1✔
36
                    (
1✔
37
                        refKindKeyword: Token(SyntaxKind.RefKeyword)
1✔
38
                    ),
1✔
39
                    _ => arg
1✔
40
                }
1✔
41
            )
1✔
42
        );
1✔
43

44
        private ParameterListSyntax ResolveParameterList(IMethodInfo method) => ParameterList
1✔
45
        (
1✔
46
            method.Parameters.ToSyntaxList(param =>
1✔
47
            {
1✔
48
                ParameterSyntax parameter = Parameter
1✔
49
                (
1✔
50
                    Identifier(param.Name)
1✔
51
                )
1✔
52
                .WithType
1✔
53
                (
1✔
54
                    type: ResolveType(param.Type)
1✔
55
                );
1✔
56

1✔
57
                SyntaxKind? modifier = param.Kind switch
1✔
58
                {
1✔
59
                    ParameterKind.In => SyntaxKind.InKeyword,
1✔
60
                    ParameterKind.Out => SyntaxKind.OutKeyword,
1✔
61
                    ParameterKind.Ref => SyntaxKind.RefKeyword,
1✔
62
                    ParameterKind.Params => SyntaxKind.ParamsKeyword,
1✔
63
                    _ => null
1✔
64
                };
1✔
65

1✔
66
                return modifier is null ? parameter : parameter.WithModifiers
1✔
67
                (
1✔
68
                    TokenList
1✔
69
                    (
1✔
70
                        Token(modifier.Value)
1✔
71
                    )
1✔
72
                );
1✔
73
            })
1✔
74
        );
1✔
75

76
        protected static string EnsureUnused(IEnumerable<IParameterInfo> parameters, string variable) => EnsureUnused
1✔
77
        (
1✔
78
            parameters.Select(static param => param.Name),
1✔
79
            variable
1✔
80
        );
1✔
81

82
        protected static string EnsureUnused(IMethodInfo method, string variable) => EnsureUnused(method.Parameters, variable);
1✔
83

84
        /// <summary>
85
        /// <code>
86
        /// [[(Type)] target | [(Type)] this | Namespace.Type].Method&lt;...&gt;(...)
87
        /// </code>
88
        /// </summary>
89
        #if DEBUG
90
        internal
91
        #endif
92
        protected MemberAccessExpressionSyntax MethodAccess(ExpressionSyntax? target, IMethodInfo method, ITypeInfo? castTargetTo = null)
93
        {
1✔
94
            SimpleNameSyntax identifier = IdentifierName(method.Name);
1✔
95
            if (method is IGenericMethodInfo genericMethod)
1✔
96
                identifier = GenericName(identifier.Identifier).WithTypeArgumentList
1✔
97
                (
1✔
98
                    typeArgumentList: TypeArgumentList
1✔
99
                    (
1✔
100
                        arguments: genericMethod.GenericArguments.ToSyntaxList(ResolveType)
1✔
101
                    )
1✔
102
                );
1✔
103

104
            return SimpleMemberAccess
1✔
105
            (
1✔
106
                AmendTarget(target, method, castTargetTo),
1✔
107
                identifier
1✔
108
            );
1✔
109
        }
1✔
110

111

112
        /// <summary>
113
        /// <code>
114
        /// int Foo(T a, ref TT b)
115
        /// </code>
116
        /// </summary>
117
        #if DEBUG
118
        internal
119
        #endif
120
        protected MethodDeclarationSyntax ResolveMethodCore(IMethodInfo method, bool allowProtected = false)
121
        {
1✔
122
            //
123
            // Starting from .NET 5.0 interface members may have visibility.
124
            //
125

126
            Visibility.Check(method, ContainingAssembly, allowProtected);
1✔
127

128
            TypeSyntax returnTypeSyntax = ResolveType(method.ReturnValue.Type);
1✔
129

130
            if (method.ReturnValue.Kind >= ParameterKind.Ref)
1✔
131
            {
1✔
132
                RefTypeSyntax refReturnTypeSyntax = RefType(returnTypeSyntax);
1✔
133

134
                if (method.ReturnValue.Kind is ParameterKind.RefReadonly)
1✔
135
                    refReturnTypeSyntax = refReturnTypeSyntax.WithReadOnlyKeyword
1✔
136
                    (
1✔
137
                        Token(SyntaxKind.ReadOnlyKeyword)
1✔
138
                    );
1✔
139

140
                returnTypeSyntax = refReturnTypeSyntax;
1✔
141
            }
1✔
142

143
            return MethodDeclaration
1✔
144
            (
1✔
145
                returnType: returnTypeSyntax,
1✔
146
                identifier: Identifier(method.Name)
1✔
147
            )
1✔
148
            .WithParameterList
1✔
149
            (
1✔
150
                ResolveParameterList(method)
1✔
151
            );
1✔
152
        }
1✔
153

154
        /// <summary>
155
        /// <code>
156
        /// int IInterface.Foo&lt;...&gt;(T a, ref TT b) [where ...]
157
        /// </code>
158
        /// or
159
        /// <code>
160
        /// public override int Foo&lt;...&gt;(T a, ref TT b) [where ...]
161
        /// </code>
162
        /// </summary>
163
        #if DEBUG
164
        internal
165
        #endif
166
        protected MethodDeclarationSyntax ResolveMethod(IMethodInfo method, bool allowProtected = false)
167
        {
1✔
168
            MethodDeclarationSyntax result = ResolveMethodCore(method, allowProtected);
1✔
169

170
            if (method.DeclaringType.Flags.HasFlag(TypeInfoFlags.IsInterface))
1✔
171
            {
1✔
172
                CheckNotStaticAbstract(method);
1✔
173

174
                result = result.WithExplicitInterfaceSpecifier
1✔
175
                (
1✔
176
                    explicitInterfaceSpecifier: ExplicitInterfaceSpecifier((NameSyntax) ResolveType(method.DeclaringType))
1✔
177
                );
1✔
178
            }
1✔
179
            else
180
            {
1✔
181
                List<SyntaxKind> tokens = [.. ResolveAccessModifiers(method)];
1✔
182

183
                tokens.Add(method.IsVirtual || method.IsAbstract ? SyntaxKind.OverrideKeyword : SyntaxKind.NewKeyword);
1✔
184

185
                result = result.WithModifiers
×
186
                (
×
187
                    TokenList
×
188
                    (
×
189
                        tokens.Select(Token)
×
190
                    )
×
191
                );
×
192
            }
1✔
193

194
            if (method is IGenericMethodInfo genericMethod)
1✔
195
            {
1✔
196
                result = result.WithTypeParameterList
1✔
197
                (
1✔
198
                    typeParameterList: TypeParameterList
1✔
199
                    (
1✔
200
                        parameters: genericMethod
1✔
201
                            .GenericArguments
1✔
202
                            .ToSyntaxList
1✔
203
                            (
1✔
204
                                type => TypeParameter
1✔
205
                                (
1✔
206
                                    ResolveType(type).ToFullString()
1✔
207
                                )
1✔
208
                            )
1✔
209
                    )
1✔
210
                );
1✔
211

212
                if (genericMethod.IsGenericDefinition)
1✔
213
                {
1✔
214
                    result = result.WithConstraintClauses
1✔
215
                    (
1✔
216
                        List
1✔
217
                        (
1✔
218
                            genericMethod
1✔
219
                                .GenericConstraints
1✔
220
                                .Where(constraint => GetConstraints(constraint).Any())
1✔
221
                                .Select
1✔
222
                                (
1✔
223
                                    constraint => TypeParameterConstraintClause
1✔
224
                                    (
1✔
225
                                        IdentifierName
1✔
226
                                        (
1✔
227
                                            constraint.Target.Name  // T, T, etc
1✔
228
                                        )
1✔
229
                                    )
1✔
230
                                    .WithConstraints
1✔
231
                                    (
1✔
232
                                        GetConstraints(constraint).ToSyntaxList()
1✔
233
                                    )
1✔
234
                                )
1✔
235
                        )
1✔
236
                    );
1✔
237

238
                    IEnumerable<TypeParameterConstraintSyntax> GetConstraints(IGenericConstraint constraint)
239
                    {
1✔
240
                        if (constraint.Struct)
1✔
241
                            yield return ClassOrStructConstraint(SyntaxKind.StructConstraint);
1✔
242
                        if (constraint.Reference)
1✔
243
                            yield return ClassOrStructConstraint(SyntaxKind.ClassConstraint);
1✔
244

245
                        //
246
                        // Explicit interface implementations must not specify type constraints
247
                        //
248

249
                        if (method.DeclaringType.Flags.HasFlag(TypeInfoFlags.IsInterface))
1✔
250
                            yield break;
1✔
251

252
                        if (constraint.DefaultConstructor)
1✔
253
                            yield return ConstructorConstraint();
1✔
254

255
                        foreach (ITypeInfo typeConstraint in constraint.ConstraintTypes)
1✔
256
                        {
1✔
257
                            yield return TypeConstraint
1✔
258
                            (
1✔
259
                                ResolveType(typeConstraint)
1✔
260
                            );
1✔
261
                        }
1✔
262
                    }
1✔
263
                }
1✔
264
            }
1✔
265

266
            return result;
1✔
267
        }
1✔
268

269
        /// <summary>
270
        /// <code>
271
        /// target.Foo(..., ref ..., ...)
272
        /// </code>
273
        /// </summary>
274
        #if DEBUG
275
        internal
276
        #endif
277
        protected InvocationExpressionSyntax InvokeMethod(IMethodInfo method, ExpressionSyntax? target = null, ITypeInfo? castTargetTo = null, params IEnumerable<ArgumentSyntax> arguments)
278
        {
1✔
279
            Debug.Assert(arguments.Count() == method.Parameters.Count);
1✔
280

281
            return InvocationExpression
1✔
282
            (
1✔
283
                expression: MethodAccess
1✔
284
                (
1✔
285
                    target,
1✔
286
                    method,
1✔
287
                    castTargetTo
1✔
288
                )
1✔
289
            )
1✔
290
            .WithArgumentList
1✔
291
            (
1✔
292
                ResolveArgumentList(method, arguments)
1✔
293
            );
1✔
294
        }
1✔
295

296
        /// <summary>
297
        /// <code>
298
        /// target.Foo(ref a, b, c)
299
        /// </code>
300
        /// </summary>
301
        #if DEBUG
302
        internal
303
        #endif
304
        protected InvocationExpressionSyntax InvokeMethod(IMethodInfo method, ExpressionSyntax? target = null, ITypeInfo? castTargetTo = null, params IReadOnlyList<string> arguments)
305
        {
1✔
306
            Debug.Assert(arguments.Count == method.Parameters.Count);
1✔
307

308
            return InvokeMethod
1✔
309
            (
1✔
310
                method,
1✔
311
                target,
1✔
312
                castTargetTo,
1✔
313
                arguments: method
1✔
314
                    .Parameters
1✔
315
                    .Select
1✔
316
                    (
1✔
317
                        (param, i) => Argument
1✔
318
                        (
1✔
319
                            expression: IdentifierName(arguments[i])
1✔
320
                        )
1✔
321
                    )
1✔
322
                    .ToArray()
1✔
323
            );
1✔
324
        }
1✔
325
    
326
        #if DEBUG
327
        internal
328
        #endif
329
        protected virtual ClassDeclarationSyntax ResolveMethods(ClassDeclarationSyntax cls, object context) => cls;
1✔
330

331
        #if DEBUG
332
        internal
333
        #endif
334
        protected virtual ClassDeclarationSyntax ResolveMethod(ClassDeclarationSyntax cls, object context, IMethodInfo method) => throw new NotImplementedException();
×
335
    }
336
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc