@@ -19,7 +19,6 @@ public static WellKnownTypes GetOrCreate(Compilation compilation) =>
19
19
20
20
private readonly INamedTypeSymbol ? [ ] _lazyWellKnownTypes ;
21
21
private readonly Compilation _compilation ;
22
- private readonly INamedTypeSymbol _missingTypeSymbol ;
23
22
24
23
static WellKnownTypes ( )
25
24
{
@@ -52,15 +51,35 @@ private WellKnownTypes(Compilation compilation)
52
51
{
53
52
_lazyWellKnownTypes = new INamedTypeSymbol ? [ WellKnownTypeData . WellKnownTypeNames . Length ] ;
54
53
_compilation = compilation ;
55
- _missingTypeSymbol = compilation . GetTypeByMetadataName ( typeof ( MissingType ) . FullName ! ) ! ;
56
54
}
57
55
58
56
public INamedTypeSymbol Get ( SpecialType type )
59
57
{
60
58
return _compilation . GetSpecialType ( type ) ;
61
59
}
62
60
61
+ /// <summary>
62
+ /// Returns the type symbol for the specified well-known type, or throws if the type cannot be found.
63
+ /// </summary>
63
64
public INamedTypeSymbol Get ( WellKnownTypeData . WellKnownType type )
65
+ {
66
+ return Get ( type , throwOnNotFound : true ) ;
67
+ }
68
+
69
+ /// <summary>
70
+ /// Returns the type symbol for the specified well-known type, or a special marker type symbol if the type cannot be found.
71
+ /// </summary>
72
+ /// <remarks>
73
+ /// We use a special marker type for cases where some types can be legitimately missing.
74
+ /// E.g. The Microsoft.Extensions.Validation source generator checks against some types
75
+ /// from the shared framework which are missing in Blazor WebAssembly SDK projects.
76
+ /// </remarks>
77
+ public INamedTypeSymbol GetOptional ( WellKnownTypeData . WellKnownType type )
78
+ {
79
+ return Get ( type , throwOnNotFound : false ) ;
80
+ }
81
+
82
+ private INamedTypeSymbol Get ( WellKnownTypeData . WellKnownType type , bool throwOnNotFound )
64
83
{
65
84
var index = ( int ) type ;
66
85
var symbol = _lazyWellKnownTypes [ index ] ;
@@ -71,12 +90,22 @@ public INamedTypeSymbol Get(WellKnownTypeData.WellKnownType type)
71
90
72
91
// Symbol hasn't been added to the cache yet.
73
92
// Resolve symbol from name, cache, and return.
74
- return GetAndCache ( index ) ;
93
+ return GetAndCache ( index , throwOnNotFound ) ;
75
94
}
76
95
77
- private INamedTypeSymbol GetAndCache ( int index )
96
+ private INamedTypeSymbol GetAndCache ( int index , bool throwOnNotFound )
78
97
{
79
- var result = GetTypeByMetadataNameInTargetAssembly ( WellKnownTypeData . WellKnownTypeNames [ index ] ) ?? _missingTypeSymbol ;
98
+ var result = GetTypeByMetadataNameInTargetAssembly ( WellKnownTypeData . WellKnownTypeNames [ index ] ) ;
99
+
100
+ if ( result == null && throwOnNotFound )
101
+ {
102
+ throw new InvalidOperationException ( $ "Failed to resolve well-known type '{ WellKnownTypeData . WellKnownTypeNames [ index ] } '.") ;
103
+ }
104
+ else
105
+ {
106
+ result ??= _compilation . GetTypeByMetadataName ( typeof ( MissingType ) . FullName ! ) ! ;
107
+ }
108
+
80
109
Interlocked . CompareExchange ( ref _lazyWellKnownTypes [ index ] , result , null ) ;
81
110
82
111
// GetTypeByMetadataName should always return the same instance for a name.
0 commit comments