2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
// See the LICENSE file in the project root for more information.
4
4
5
+ using System ;
5
6
using System . Collections . Generic ;
6
7
using System . Collections . Immutable ;
7
8
using System . Diagnostics ;
@@ -224,12 +225,6 @@ private ImmutableArray<Symbol> BindExtensionMemberCref(ExtensionMemberCrefSyntax
224
225
{
225
226
CheckFeatureAvailability ( syntax , MessageID . IDS_FeatureExtensions , diagnostics ) ;
226
227
227
- if ( containerOpt is not NamedTypeSymbol namedContainer )
228
- {
229
- ambiguityWinner = null ;
230
- return ImmutableArray < Symbol > . Empty ;
231
- }
232
-
233
228
int arity = 0 ;
234
229
TypeArgumentListSyntax ? typeArgumentListSyntax = null ;
235
230
CrefParameterListSyntax ? parameters = null ;
@@ -256,7 +251,7 @@ private ImmutableArray<Symbol> BindExtensionMemberCref(ExtensionMemberCrefSyntax
256
251
257
252
TypeArgumentListSyntax ? extensionTypeArguments = syntax . TypeArgumentList ;
258
253
int extensionArity = extensionTypeArguments ? . Arguments . Count ?? 0 ;
259
- ImmutableArray < Symbol > sortedSymbols = computeSortedAndFilteredCrefExtensionMembers ( namedContainer , memberName , extensionArity , arity , extensionTypeArguments , diagnostics , syntax ) ;
254
+ ImmutableArray < Symbol > sortedSymbols = computeSortedAndFilteredCrefExtensionMembers ( containerOpt , memberName , extensionArity , arity , extensionTypeArguments , diagnostics , syntax ) ;
260
255
261
256
if ( sortedSymbols . IsDefaultOrEmpty )
262
257
{
@@ -268,7 +263,7 @@ private ImmutableArray<Symbol> BindExtensionMemberCref(ExtensionMemberCrefSyntax
268
263
269
264
return ProcessCrefMemberLookupResults ( sortedSymbols , arity , syntax , typeArgumentListSyntax , parameters , out ambiguityWinner , diagnostics ) ;
270
265
271
- ImmutableArray < Symbol > computeSortedAndFilteredCrefExtensionMembers ( NamedTypeSymbol container , string name , int extensionArity , int arity , TypeArgumentListSyntax ? extensionTypeArguments , BindingDiagnosticBag diagnostics , ExtensionMemberCrefSyntax syntax )
266
+ ImmutableArray < Symbol > computeSortedAndFilteredCrefExtensionMembers ( NamespaceOrTypeSymbol ? containerOpt , string name , int extensionArity , int arity , TypeArgumentListSyntax ? extensionTypeArguments , BindingDiagnosticBag diagnostics , ExtensionMemberCrefSyntax syntax )
272
267
{
273
268
Debug . Assert ( name is not null ) ;
274
269
@@ -295,9 +290,19 @@ ImmutableArray<Symbol> computeSortedAndFilteredCrefExtensionMembers(NamedTypeSym
295
290
CompoundUseSiteInfo < AssemblySymbol > useSiteInfo = this . GetNewCompoundUseSiteInfo ( diagnostics ) ;
296
291
ArrayBuilder < Symbol > ? sortedSymbolsBuilder = null ;
297
292
298
- foreach ( var nested in container . GetTypeMembers ( ) )
293
+ IEnumerable < NamedTypeSymbol > candidateTypes = containerOpt switch
294
+ {
295
+ null => enumerateCandidateTypes ( containerOpt , syntax , diagnostics ) ,
296
+ NamedTypeSymbol container => container . GetTypeMembers ( "" ) ,
297
+ _ => [ ]
298
+ } ;
299
+
300
+ foreach ( var nested in candidateTypes )
299
301
{
300
- if ( ! nested . IsExtension || nested . Arity != extensionArity || nested . ExtensionParameter is null )
302
+ if ( ! nested . IsExtension
303
+ || nested . Arity != extensionArity
304
+ || nested . ExtensionParameter is null
305
+ || nested is not { ContainingType : { ContainingType : null } } ) // only consider extension blocks in top-level types
301
306
{
302
307
continue ;
303
308
}
@@ -365,6 +370,36 @@ ImmutableArray<Symbol> computeSortedAndFilteredCrefExtensionMembers(NamedTypeSym
365
370
366
371
return sortedSymbolsBuilder . ToImmutableAndFree ( ) ;
367
372
}
373
+
374
+ IEnumerable < NamedTypeSymbol > enumerateCandidateTypes ( NamespaceOrTypeSymbol ? container , SyntaxNode syntax , BindingDiagnosticBag diagnostics )
375
+ {
376
+ CompoundUseSiteInfo < AssemblySymbol > useSiteInfo = GetNewCompoundUseSiteInfo ( diagnostics ) ;
377
+ LookupResult result = LookupResult . GetInstance ( ) ;
378
+ this . LookupSymbolsOrMembersInternal (
379
+ result ,
380
+ container ,
381
+ name : "" ,
382
+ arity : 0 ,
383
+ basesBeingResolved : null ,
384
+ options : LookupOptions . AllNamedTypesOnArityZero | LookupOptions . NamespacesOrTypesOnly ,
385
+ diagnose : false ,
386
+ useSiteInfo : ref useSiteInfo ) ;
387
+
388
+ diagnostics . Add ( syntax , useSiteInfo ) ;
389
+
390
+ if ( result . IsMultiViable )
391
+ {
392
+ foreach ( var symbol in result . Symbols )
393
+ {
394
+ if ( symbol is NamedTypeSymbol namedType )
395
+ {
396
+ yield return namedType ;
397
+ }
398
+ }
399
+ }
400
+
401
+ result . Free ( ) ;
402
+ }
368
403
}
369
404
370
405
// NOTE: not guaranteed to be a method (e.g. class op_Addition)
0 commit comments