11// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22
3+ #nullable enable
4+
35using System . Collections . Generic ;
46using System . Collections . Immutable ;
57using System . Diagnostics ;
1214
1315namespace Microsoft . CodeAnalysis . CSharp . Symbols
1416{
15- internal sealed class LocalFunctionSymbol : SourceMethodSymbol
17+ internal sealed class LocalFunctionSymbol : SourceMethodSymbol , IAttributeTargetSymbol
1618 {
1719 private readonly Binder _binder ;
1820 private readonly LocalFunctionStatementSyntax _syntax ;
@@ -25,8 +27,11 @@ internal sealed class LocalFunctionSymbol : SourceMethodSymbol
2527 private bool _lazyIsVarArg ;
2628 // Initialized in two steps. Hold a copy if accessing during initialization.
2729 private ImmutableArray < TypeParameterConstraintClause > _lazyTypeParameterConstraints ;
28- private TypeWithAnnotations . Boxed _lazyReturnType ;
29- private TypeWithAnnotations . Boxed _lazyIteratorElementType ;
30+ private TypeWithAnnotations . Boxed ? _lazyReturnType ;
31+ private TypeWithAnnotations . Boxed ? _lazyIteratorElementType ;
32+
33+ private CustomAttributesBag < CSharpAttributeData > ? _lazyCustomAttributesBag ;
34+ private CustomAttributesBag < CSharpAttributeData > ? _lazyReturnTypeCustomAttributesBag ;
3035
3136 // Lock for initializing lazy fields and registering their diagnostics
3237 // Acquire this lock when initializing lazy objects to guarantee their declaration
@@ -121,6 +126,9 @@ internal void GetDeclarationDiagnostics(DiagnosticBag addTo)
121126
122127 ComputeReturnType ( ) ;
123128
129+ GetAttributes ( ) ;
130+ GetReturnTypeAttributes ( ) ;
131+
124132 addTo . AddRange ( _declarationDiagnostics ) ;
125133 }
126134
@@ -202,7 +210,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
202210 get
203211 {
204212 ComputeReturnType ( ) ;
205- return _lazyReturnType . Value ;
213+ return _lazyReturnType ! . Value ;
206214 }
207215 }
208216
@@ -341,17 +349,17 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations
341349
342350 internal override MethodImplAttributes ImplementationAttributes => default ( MethodImplAttributes ) ;
343351
344- internal override ObsoleteAttributeData ObsoleteAttributeData => null ;
352+ internal override ObsoleteAttributeData ? ObsoleteAttributeData => null ;
345353
346- internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation => null ;
354+ internal override MarshalPseudoCustomAttributeData ? ReturnValueMarshallingInformation => null ;
347355
348356 internal override CallingConvention CallingConvention => CallingConvention . Default ;
349357
350358 internal override bool HasDeclarativeSecurity => false ;
351359
352360 internal override bool RequiresSecurityObject => false ;
353361
354- public override Symbol AssociatedSymbol => null ;
362+ public override Symbol ? AssociatedSymbol => null ;
355363
356364 public override Accessibility DeclaredAccessibility => ModifierUtils . EffectiveAccessibility ( _declarationModifiers ) ;
357365
@@ -375,7 +383,13 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations
375383
376384 internal override bool IsDeclaredReadOnly => false ;
377385
378- public override DllImportData GetDllImportData ( ) => null ;
386+ IAttributeTargetSymbol IAttributeTargetSymbol . AttributesOwner => this ;
387+
388+ AttributeLocation IAttributeTargetSymbol . AllowedAttributeLocations => AttributeLocation . Method | AttributeLocation . Return ;
389+
390+ AttributeLocation IAttributeTargetSymbol . DefaultAttributeLocation => AttributeLocation . Method ;
391+
392+ public override DllImportData ? GetDllImportData ( ) => null ;
379393
380394 internal override ImmutableArray < string > GetAppliedConditionalSymbols ( ) => ImmutableArray < string > . Empty ;
381395
@@ -393,25 +407,29 @@ internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree l
393407 throw ExceptionUtilities . Unreachable ;
394408 }
395409
396- internal override bool TryGetThisParameter ( out ParameterSymbol thisParameter )
410+ internal override bool TryGetThisParameter ( out ParameterSymbol ? thisParameter )
397411 {
398412 // Local function symbols have no "this" parameter
399413 thisParameter = null ;
400414 return true ;
401415 }
402416
403- private static void ReportAttributesDisallowed ( SyntaxList < AttributeListSyntax > attributes , DiagnosticBag diagnostics )
417+ private void ReportAttributesDisallowed ( SyntaxList < AttributeListSyntax > attributes , DiagnosticBag diagnostics )
404418 {
405- foreach ( var attrList in attributes )
419+ var diagnosticInfo = MessageID . IDS_FeatureLocalFunctionAttributes . GetFeatureAvailabilityDiagnosticInfoOpt ( ( CSharpParseOptions ) _syntax . SyntaxTree . Options ) ;
420+ if ( diagnosticInfo is object )
406421 {
407- diagnostics . Add ( ErrorCode . ERR_AttributesInLocalFuncDecl , attrList . Location ) ;
422+ foreach ( var attrList in attributes )
423+ {
424+ diagnostics . Add ( diagnosticInfo , attrList . Location ) ;
425+ }
408426 }
409427 }
410428
411429 private ImmutableArray < SourceMethodTypeParameterSymbol > MakeTypeParameters ( DiagnosticBag diagnostics )
412430 {
413431 var result = ArrayBuilder < SourceMethodTypeParameterSymbol > . GetInstance ( ) ;
414- var typeParameters = _syntax . TypeParameterList . Parameters ;
432+ var typeParameters = _syntax . TypeParameterList ? . Parameters ?? default ;
415433 for ( int ordinal = 0 ; ordinal < typeParameters . Count ; ordinal ++ )
416434 {
417435 var parameter = typeParameters [ ordinal ] ;
@@ -420,7 +438,6 @@ private ImmutableArray<SourceMethodTypeParameterSymbol> MakeTypeParameters(Diagn
420438 diagnostics . Add ( ErrorCode . ERR_IllegalVarianceSyntax , parameter . VarianceKeyword . GetLocation ( ) ) ;
421439 }
422440
423- // Attributes are currently disallowed on local function type parameters
424441 ReportAttributesDisallowed ( parameter . AttributeLists , diagnostics ) ;
425442
426443 var identifier = parameter . Identifier ;
@@ -493,6 +510,33 @@ public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterCo
493510 return _lazyTypeParameterConstraints ;
494511 }
495512
513+ public override ImmutableArray < CSharpAttributeData > GetAttributes ( )
514+ {
515+ var lazyCustomAttributesBag = _lazyCustomAttributesBag ;
516+ if ( lazyCustomAttributesBag == null )
517+ {
518+ LoadAndValidateAttributes ( OneOrMany . Create ( _syntax . AttributeLists ) , ref _lazyCustomAttributesBag ) ;
519+ lazyCustomAttributesBag = _lazyCustomAttributesBag ;
520+ }
521+
522+ return lazyCustomAttributesBag . Attributes ;
523+ }
524+
525+ public override ImmutableArray < CSharpAttributeData > GetReturnTypeAttributes ( )
526+ {
527+ var lazyReturnTypeCustomAttributesBag = _lazyReturnTypeCustomAttributesBag ;
528+ if ( lazyReturnTypeCustomAttributesBag == null )
529+ {
530+ LoadAndValidateAttributes (
531+ OneOrMany . Create ( _syntax . AttributeLists ) ,
532+ ref _lazyReturnTypeCustomAttributesBag ,
533+ symbolPart : AttributeLocation . Return ) ;
534+ lazyReturnTypeCustomAttributesBag = _lazyReturnTypeCustomAttributesBag ;
535+ }
536+
537+ return lazyReturnTypeCustomAttributesBag . Attributes ;
538+ }
539+
496540 public override int GetHashCode ( )
497541 {
498542 // this is what lambdas do (do not use hashes of other fields)
@@ -504,8 +548,7 @@ public sealed override bool Equals(Symbol symbol, TypeCompareKind compareKind)
504548 if ( ( object ) this == symbol ) return true ;
505549
506550 var localFunction = symbol as LocalFunctionSymbol ;
507- return ( object ) localFunction != null
508- && localFunction . _syntax == _syntax ;
551+ return localFunction ? . _syntax == _syntax ;
509552 }
510553 }
511554}
0 commit comments