Skip to content

Commit de01132

Browse files
authored
Merge pull request #33 from smdn/fix-issue-20
Add overloads to CSharpFormatter.FormatParameter/FormatParameterList/FormatTypeName that accepts lock object for NullabilityInfoContext
2 parents f376b0b + 16c31d1 commit de01132

File tree

7 files changed

+578
-8
lines changed

7 files changed

+578
-8
lines changed

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/CSharpFormatter.FormatTypeName.cs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@ public static string FormatTypeName(
4646
bool typeWithNamespace = true,
4747
bool withDeclaringTypeName = true,
4848
bool translateLanguagePrimitiveType = true
49+
)
50+
=> FormatTypeName(
51+
f: f ?? throw new ArgumentNullException(nameof(f)),
52+
nullabilityInfoContext: nullabilityInfoContext,
53+
nullabilityInfoContextLockObject: null,
54+
typeWithNamespace: typeWithNamespace,
55+
withDeclaringTypeName: withDeclaringTypeName,
56+
translateLanguagePrimitiveType: translateLanguagePrimitiveType
57+
);
58+
59+
public static string FormatTypeName(
60+
this FieldInfo f,
61+
NullabilityInfoContext? nullabilityInfoContext,
62+
object? nullabilityInfoContextLockObject,
63+
bool typeWithNamespace = true,
64+
bool withDeclaringTypeName = true,
65+
bool translateLanguagePrimitiveType = true
4966
)
5067
=> nullabilityInfoContext is null
5168
? FormatTypeName(
@@ -55,7 +72,7 @@ public static string FormatTypeName(
5572
translateLanguagePrimitiveType: translateLanguagePrimitiveType
5673
)
5774
: FormatTypeNameWithNullabilityAnnotation(
58-
nullabilityInfoContext.Create(f ?? throw new ArgumentNullException(nameof(f))),
75+
target: nullabilityInfoContext.Create(f ?? throw new ArgumentNullException(nameof(f)), nullabilityInfoContextLockObject),
5976
builder: new(capacity: 32),
6077
options: new(
6178
AttributeProvider: f,
@@ -92,6 +109,23 @@ public static string FormatTypeName(
92109
bool typeWithNamespace = true,
93110
bool withDeclaringTypeName = true,
94111
bool translateLanguagePrimitiveType = true
112+
)
113+
=> FormatTypeName(
114+
p: p ?? throw new ArgumentNullException(nameof(p)),
115+
nullabilityInfoContext: nullabilityInfoContext,
116+
nullabilityInfoContextLockObject: null,
117+
typeWithNamespace: typeWithNamespace,
118+
withDeclaringTypeName: withDeclaringTypeName,
119+
translateLanguagePrimitiveType: translateLanguagePrimitiveType
120+
);
121+
122+
public static string FormatTypeName(
123+
this PropertyInfo p,
124+
NullabilityInfoContext? nullabilityInfoContext,
125+
object? nullabilityInfoContextLockObject,
126+
bool typeWithNamespace = true,
127+
bool withDeclaringTypeName = true,
128+
bool translateLanguagePrimitiveType = true
95129
)
96130
=> nullabilityInfoContext is null
97131
? FormatTypeName(
@@ -101,7 +135,7 @@ public static string FormatTypeName(
101135
translateLanguagePrimitiveType: translateLanguagePrimitiveType
102136
)
103137
: FormatTypeNameWithNullabilityAnnotation(
104-
nullabilityInfoContext.Create(p ?? throw new ArgumentNullException(nameof(p))),
138+
target: nullabilityInfoContext.Create(p ?? throw new ArgumentNullException(nameof(p)), nullabilityInfoContextLockObject),
105139
builder: new(capacity: 32),
106140
options: new(
107141
AttributeProvider: p,
@@ -138,6 +172,23 @@ public static string FormatTypeName(
138172
bool typeWithNamespace = true,
139173
bool withDeclaringTypeName = true,
140174
bool translateLanguagePrimitiveType = true
175+
)
176+
=> FormatTypeName(
177+
p: p ?? throw new ArgumentNullException(nameof(p)),
178+
nullabilityInfoContext: nullabilityInfoContext,
179+
nullabilityInfoContextLockObject: null,
180+
typeWithNamespace: typeWithNamespace,
181+
withDeclaringTypeName: withDeclaringTypeName,
182+
translateLanguagePrimitiveType: translateLanguagePrimitiveType
183+
);
184+
185+
public static string FormatTypeName(
186+
this ParameterInfo p,
187+
NullabilityInfoContext? nullabilityInfoContext,
188+
object? nullabilityInfoContextLockObject,
189+
bool typeWithNamespace = true,
190+
bool withDeclaringTypeName = true,
191+
bool translateLanguagePrimitiveType = true
141192
)
142193
=> nullabilityInfoContext is null
143194
? FormatTypeName(
@@ -147,7 +198,7 @@ public static string FormatTypeName(
147198
translateLanguagePrimitiveType: translateLanguagePrimitiveType
148199
)
149200
: FormatTypeNameWithNullabilityAnnotation(
150-
nullabilityInfoContext.Create(p ?? throw new ArgumentNullException(nameof(p))),
201+
target: nullabilityInfoContext.Create(p ?? throw new ArgumentNullException(nameof(p)), nullabilityInfoContextLockObject),
151202
builder: new(capacity: 32),
152203
options: new(
153204
AttributeProvider: p,
@@ -184,6 +235,23 @@ public static string FormatTypeName(
184235
bool typeWithNamespace = true,
185236
bool withDeclaringTypeName = true,
186237
bool translateLanguagePrimitiveType = true
238+
)
239+
=> FormatTypeName(
240+
ev: ev,
241+
nullabilityInfoContext: nullabilityInfoContext,
242+
nullabilityInfoContextLockObject: null,
243+
typeWithNamespace: typeWithNamespace,
244+
withDeclaringTypeName: withDeclaringTypeName,
245+
translateLanguagePrimitiveType: translateLanguagePrimitiveType
246+
);
247+
248+
public static string FormatTypeName(
249+
this EventInfo ev,
250+
NullabilityInfoContext? nullabilityInfoContext,
251+
object? nullabilityInfoContextLockObject,
252+
bool typeWithNamespace = true,
253+
bool withDeclaringTypeName = true,
254+
bool translateLanguagePrimitiveType = true
187255
)
188256
=> nullabilityInfoContext is null
189257
? FormatTypeName(
@@ -193,7 +261,7 @@ public static string FormatTypeName(
193261
translateLanguagePrimitiveType: translateLanguagePrimitiveType
194262
)
195263
: FormatTypeNameWithNullabilityAnnotation(
196-
nullabilityInfoContext.Create(ev ?? throw new ArgumentNullException(nameof(ev))),
264+
target: nullabilityInfoContext.Create(ev ?? throw new ArgumentNullException(nameof(ev)), nullabilityInfoContextLockObject),
197265
builder: new(capacity: 32),
198266
options: new(
199267
AttributeProvider: ev,

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/CSharpFormatter.cs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public static string FormatParameterList(
221221
parameterList: (m ?? throw new ArgumentNullException(nameof(m))).GetParameters(),
222222
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
223223
nullabilityInfoContext: null,
224+
nullabilityInfoContextLockObject: null,
224225
#endif
225226
typeWithNamespace: typeWithNamespace,
226227
useDefaultLiteral: useDefaultLiteral
@@ -236,6 +237,22 @@ public static string FormatParameterList(
236237
=> FormatParameterListCore(
237238
parameterList: (m ?? throw new ArgumentNullException(nameof(m))).GetParameters(),
238239
nullabilityInfoContext: nullabilityInfoContext,
240+
nullabilityInfoContextLockObject: null,
241+
typeWithNamespace: typeWithNamespace,
242+
useDefaultLiteral: useDefaultLiteral
243+
);
244+
245+
public static string FormatParameterList(
246+
MethodBase m,
247+
NullabilityInfoContext? nullabilityInfoContext,
248+
object? nullabilityInfoContextLockObject,
249+
bool typeWithNamespace = true,
250+
bool useDefaultLiteral = false
251+
)
252+
=> FormatParameterListCore(
253+
parameterList: (m ?? throw new ArgumentNullException(nameof(m))).GetParameters(),
254+
nullabilityInfoContext: nullabilityInfoContext,
255+
nullabilityInfoContextLockObject: nullabilityInfoContextLockObject,
239256
typeWithNamespace: typeWithNamespace,
240257
useDefaultLiteral: useDefaultLiteral
241258
);
@@ -250,6 +267,7 @@ public static string FormatParameterList(
250267
parameterList: parameterList ?? throw new ArgumentNullException(nameof(parameterList)),
251268
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
252269
nullabilityInfoContext: null,
270+
nullabilityInfoContextLockObject: null,
253271
#endif
254272
typeWithNamespace: typeWithNamespace,
255273
useDefaultLiteral: useDefaultLiteral
@@ -265,6 +283,22 @@ public static string FormatParameterList(
265283
=> FormatParameterListCore(
266284
parameterList: parameterList ?? throw new ArgumentNullException(nameof(parameterList)),
267285
nullabilityInfoContext: nullabilityInfoContext,
286+
nullabilityInfoContextLockObject: null,
287+
typeWithNamespace: typeWithNamespace,
288+
useDefaultLiteral: useDefaultLiteral
289+
);
290+
291+
public static string FormatParameterList(
292+
ParameterInfo[] parameterList,
293+
NullabilityInfoContext? nullabilityInfoContext,
294+
object? nullabilityInfoContextLockObject,
295+
bool typeWithNamespace = true,
296+
bool useDefaultLiteral = false
297+
)
298+
=> FormatParameterListCore(
299+
parameterList: parameterList ?? throw new ArgumentNullException(nameof(parameterList)),
300+
nullabilityInfoContext: nullabilityInfoContext,
301+
nullabilityInfoContextLockObject: nullabilityInfoContextLockObject,
268302
typeWithNamespace: typeWithNamespace,
269303
useDefaultLiteral: useDefaultLiteral
270304
);
@@ -274,6 +308,7 @@ private static string FormatParameterListCore(
274308
ParameterInfo[] parameterList,
275309
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
276310
NullabilityInfoContext? nullabilityInfoContext,
311+
object? nullabilityInfoContextLockObject,
277312
#endif
278313
bool typeWithNamespace = true,
279314
bool useDefaultLiteral = false
@@ -285,6 +320,7 @@ private static string FormatParameterListCore(
285320
p,
286321
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
287322
nullabilityInfoContext: nullabilityInfoContext,
323+
nullabilityInfoContextLockObject: nullabilityInfoContextLockObject,
288324
#endif
289325
typeWithNamespace: typeWithNamespace,
290326
useDefaultLiteral: useDefaultLiteral
@@ -297,10 +333,11 @@ public static string FormatParameter(
297333
bool typeWithNamespace = true,
298334
bool useDefaultLiteral = false
299335
)
300-
=> FormatParameter(
336+
=> FormatParameterCore(
301337
p: p ?? throw new ArgumentNullException(nameof(p)),
302338
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
303339
nullabilityInfoContext: null,
340+
nullabilityInfoContextLockObject: null,
304341
#endif
305342
typeWithNamespace: typeWithNamespace,
306343
typeWithDeclaringTypeName: true,
@@ -323,6 +360,22 @@ public static string FormatParameter(
323360
=> FormatParameter(
324361
p: p ?? throw new ArgumentNullException(nameof(p)),
325362
nullabilityInfoContext: nullabilityInfoContext,
363+
nullabilityInfoContextLockObject: null,
364+
typeWithNamespace: typeWithNamespace,
365+
useDefaultLiteral: useDefaultLiteral
366+
);
367+
368+
public static string FormatParameter(
369+
ParameterInfo p,
370+
NullabilityInfoContext? nullabilityInfoContext,
371+
object? nullabilityInfoContextLockObject,
372+
bool typeWithNamespace = true,
373+
bool useDefaultLiteral = false
374+
)
375+
=> FormatParameterCore(
376+
p: p ?? throw new ArgumentNullException(nameof(p)),
377+
nullabilityInfoContext: nullabilityInfoContext,
378+
nullabilityInfoContextLockObject: nullabilityInfoContextLockObject,
326379
typeWithNamespace: typeWithNamespace,
327380
typeWithDeclaringTypeName: true,
328381
valueFormatOptions: new(
@@ -335,10 +388,11 @@ public static string FormatParameter(
335388
);
336389
#endif
337390

338-
internal static string FormatParameter(
391+
internal static string FormatParameterCore(
339392
ParameterInfo p,
340393
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
341394
NullabilityInfoContext? nullabilityInfoContext,
395+
object? nullabilityInfoContextLockObject,
342396
#endif
343397
bool typeWithNamespace,
344398
bool typeWithDeclaringTypeName,
@@ -368,6 +422,7 @@ ValueFormatOptions valueFormatOptions
368422
#pragma warning disable SA1114
369423
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
370424
nullabilityInfoContext: nullabilityInfoContext,
425+
nullabilityInfoContextLockObject: nullabilityInfoContextLockObject,
371426
#endif
372427
typeWithNamespace: typeWithNamespace,
373428
withDeclaringTypeName: typeWithDeclaringTypeName

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/Generator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,12 +985,13 @@ GeneratorOptions options
985985
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
986986
var isDelegate = p.Member == p.Member.DeclaringType?.GetDelegateSignatureMethod();
987987
#endif
988-
var param = CSharpFormatter.FormatParameter(
988+
var param = CSharpFormatter.FormatParameterCore(
989989
p,
990990
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
991991
nullabilityInfoContext: isDelegate
992992
? options.TypeDeclaration.NullabilityInfoContext
993993
: options.MemberDeclaration.NullabilityInfoContext,
994+
nullabilityInfoContextLockObject: null, // TODO
994995
#endif
995996
typeWithNamespace: options.ParameterDeclaration.WithNamespace,
996997
typeWithDeclaringTypeName: options.ParameterDeclaration.WithDeclaringTypeName,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-FileCopyrightText: 2023 smdn <smdn@smdn.jp>
2+
// SPDX-License-Identifier: MIT
3+
#if SYSTEM_REFLECTION_NULLABILITYINFOCONTEXT
4+
using System;
5+
using System.Reflection;
6+
7+
namespace Smdn.Reflection.ReverseGenerating;
8+
9+
/// <summary>
10+
/// Provides extension methods for <see cref="NullabilityInfoContext"/>.
11+
/// </summary>
12+
/// <remarks>
13+
/// <see cref="NullabilityInfoContext"/> internally caches created <see cref="NullabilityInfo"/> using <see cref="System.Collections.Generic.Dictionary{TKey, TValue}"/>.
14+
/// This may cause an exception to be thrown if <see cref="NullabilityInfoContext.Create"/> is called concurrently.
15+
/// So, this class provides extension methods that uses a lock object to lock and then calls <see cref="NullabilityInfoContext.Create"/>.
16+
/// </remarks>
17+
internal static class NullabilityInfoContextExtensions {
18+
internal static NullabilityInfo Create(this NullabilityInfoContext context, FieldInfo field, object? lockObject)
19+
{
20+
if (lockObject is null)
21+
return context.Create(field);
22+
23+
lock (lockObject) {
24+
return context.Create(field);
25+
}
26+
}
27+
28+
internal static NullabilityInfo Create(this NullabilityInfoContext context, PropertyInfo property, object? lockObject)
29+
{
30+
if (lockObject is null)
31+
return context.Create(property);
32+
33+
lock (lockObject) {
34+
return context.Create(property);
35+
}
36+
}
37+
38+
internal static NullabilityInfo Create(this NullabilityInfoContext context, ParameterInfo parameter, object? lockObject)
39+
{
40+
if (lockObject is null)
41+
return context.Create(parameter);
42+
43+
lock (lockObject) {
44+
return context.Create(parameter);
45+
}
46+
}
47+
48+
internal static NullabilityInfo Create(this NullabilityInfoContext context, EventInfo @event, object? lockObject)
49+
{
50+
if (lockObject is null)
51+
return context.Create(@event);
52+
53+
lock (lockObject) {
54+
return context.Create(@event);
55+
}
56+
}
57+
}
58+
#endif

0 commit comments

Comments
 (0)