Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System;
using System.Diagnostics;
using Roslyn.Utilities;
Expand Down Expand Up @@ -200,7 +202,7 @@ public override string ToString()
return ToString(null, null);
}

public string ToString(string format, IFormatProvider formatProvider)
public string ToString(string? format, IFormatProvider? formatProvider)
{
return ErrorFacts.GetMessage(_id, formatProvider as System.Globalization.CultureInfo);
}
Expand All @@ -221,7 +223,7 @@ public static LocalizableErrorArgument Localize(this MessageID id)
// If this method returns non-null, use that.
// Features should be mutually exclusive between RequiredFeature and RequiredVersion.
// (hence the above rule - RequiredVersion throws when RequiredFeature returns non-null)
internal static string RequiredFeature(this MessageID feature)
internal static string? RequiredFeature(this MessageID feature)
{
// Check for current experimental features, if any, in the current branch.
switch (feature)
Expand All @@ -235,7 +237,7 @@ internal static bool CheckFeatureAvailability(
this MessageID feature,
DiagnosticBag diagnostics,
SyntaxNode syntax,
Location location = null)
Location? location = null)
{
var diag = GetFeatureAvailabilityDiagnosticInfoOpt(feature, (CSharpParseOptions)syntax.SyntaxTree.Options);
if (diag is object)
Expand All @@ -260,15 +262,15 @@ internal static bool CheckFeatureAvailability(
return true;
}

internal static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfoOpt(this MessageID feature, CSharpParseOptions options)
internal static CSDiagnosticInfo? GetFeatureAvailabilityDiagnosticInfoOpt(this MessageID feature, CSharpParseOptions options)
=> options.IsFeatureEnabled(feature) ? null : GetDisabledFeatureDiagnosticInfo(feature, options.LanguageVersion);

internal static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfoOpt(this MessageID feature, CSharpCompilation compilation)
internal static CSDiagnosticInfo? GetFeatureAvailabilityDiagnosticInfoOpt(this MessageID feature, CSharpCompilation compilation)
=> compilation.IsFeatureEnabled(feature) ? null : GetDisabledFeatureDiagnosticInfo(feature, compilation.LanguageVersion);

private static CSDiagnosticInfo GetDisabledFeatureDiagnosticInfo(MessageID feature, LanguageVersion availableVersion)
{
string requiredFeature = feature.RequiredFeature();
string? requiredFeature = feature.RequiredFeature();
if (requiredFeature != null)
{
return new CSDiagnosticInfo(ErrorCode.ERR_FeatureIsExperimental, feature.Localize(), requiredFeature);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
Expand All @@ -12,7 +14,7 @@

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal sealed class LocalFunctionSymbol : SourceMethodSymbol
internal sealed class LocalFunctionSymbol : SourceMethodSymbol, IAttributeTargetSymbol
{
private readonly Binder _binder;
private readonly LocalFunctionStatementSyntax _syntax;
Expand All @@ -25,8 +27,11 @@ internal sealed class LocalFunctionSymbol : SourceMethodSymbol
private bool _lazyIsVarArg;
// Initialized in two steps. Hold a copy if accessing during initialization.
private ImmutableArray<TypeParameterConstraintClause> _lazyTypeParameterConstraints;
private TypeWithAnnotations.Boxed _lazyReturnType;
private TypeWithAnnotations.Boxed _lazyIteratorElementType;
private TypeWithAnnotations.Boxed? _lazyReturnType;
private TypeWithAnnotations.Boxed? _lazyIteratorElementType;

private CustomAttributesBag<CSharpAttributeData>? _lazyCustomAttributesBag;
private CustomAttributesBag<CSharpAttributeData>? _lazyReturnTypeCustomAttributesBag;

// Lock for initializing lazy fields and registering their diagnostics
// Acquire this lock when initializing lazy objects to guarantee their declaration
Expand Down Expand Up @@ -121,6 +126,9 @@ internal void GetDeclarationDiagnostics(DiagnosticBag addTo)

ComputeReturnType();

GetAttributes();
GetReturnTypeAttributes();

addTo.AddRange(_declarationDiagnostics);
}

Expand Down Expand Up @@ -202,7 +210,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get
{
ComputeReturnType();
return _lazyReturnType.Value;
return _lazyReturnType!.Value;
}
}

Expand Down Expand Up @@ -341,17 +349,17 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations

internal override MethodImplAttributes ImplementationAttributes => default(MethodImplAttributes);

internal override ObsoleteAttributeData ObsoleteAttributeData => null;
internal override ObsoleteAttributeData? ObsoleteAttributeData => null;

internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation => null;
internal override MarshalPseudoCustomAttributeData? ReturnValueMarshallingInformation => null;

internal override CallingConvention CallingConvention => CallingConvention.Default;

internal override bool HasDeclarativeSecurity => false;

internal override bool RequiresSecurityObject => false;

public override Symbol AssociatedSymbol => null;
public override Symbol? AssociatedSymbol => null;

public override Accessibility DeclaredAccessibility => ModifierUtils.EffectiveAccessibility(_declarationModifiers);

Expand All @@ -375,7 +383,13 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations

internal override bool IsDeclaredReadOnly => false;

public override DllImportData GetDllImportData() => null;
IAttributeTargetSymbol IAttributeTargetSymbol.AttributesOwner => this;

AttributeLocation IAttributeTargetSymbol.AllowedAttributeLocations => AttributeLocation.Method | AttributeLocation.Return;

AttributeLocation IAttributeTargetSymbol.DefaultAttributeLocation => AttributeLocation.Method;

public override DllImportData? GetDllImportData() => null;

internal override ImmutableArray<string> GetAppliedConditionalSymbols() => ImmutableArray<string>.Empty;

Expand All @@ -393,25 +407,29 @@ internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree l
throw ExceptionUtilities.Unreachable;
}

internal override bool TryGetThisParameter(out ParameterSymbol thisParameter)
internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
{
// Local function symbols have no "this" parameter
thisParameter = null;
return true;
}

private static void ReportAttributesDisallowed(SyntaxList<AttributeListSyntax> attributes, DiagnosticBag diagnostics)
private void ReportAttributesDisallowed(SyntaxList<AttributeListSyntax> attributes, DiagnosticBag diagnostics)
{
foreach (var attrList in attributes)
var diagnosticInfo = MessageID.IDS_FeatureLocalFunctionAttributes.GetFeatureAvailabilityDiagnosticInfoOpt((CSharpParseOptions)_syntax.SyntaxTree.Options);
if (diagnosticInfo is object)
{
diagnostics.Add(ErrorCode.ERR_AttributesInLocalFuncDecl, attrList.Location);
foreach (var attrList in attributes)
{
diagnostics.Add(diagnosticInfo, attrList.Location);
}
}
}

private ImmutableArray<SourceMethodTypeParameterSymbol> MakeTypeParameters(DiagnosticBag diagnostics)
{
var result = ArrayBuilder<SourceMethodTypeParameterSymbol>.GetInstance();
var typeParameters = _syntax.TypeParameterList.Parameters;
var typeParameters = _syntax.TypeParameterList?.Parameters ?? default;
for (int ordinal = 0; ordinal < typeParameters.Count; ordinal++)
{
var parameter = typeParameters[ordinal];
Expand All @@ -420,7 +438,6 @@ private ImmutableArray<SourceMethodTypeParameterSymbol> MakeTypeParameters(Diagn
diagnostics.Add(ErrorCode.ERR_IllegalVarianceSyntax, parameter.VarianceKeyword.GetLocation());
}

// Attributes are currently disallowed on local function type parameters
ReportAttributesDisallowed(parameter.AttributeLists, diagnostics);

var identifier = parameter.Identifier;
Expand Down Expand Up @@ -493,6 +510,33 @@ public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterCo
return _lazyTypeParameterConstraints;
}

public override ImmutableArray<CSharpAttributeData> GetAttributes()
{
var lazyCustomAttributesBag = _lazyCustomAttributesBag;
if (lazyCustomAttributesBag == null)
{
LoadAndValidateAttributes(OneOrMany.Create(_syntax.AttributeLists), ref _lazyCustomAttributesBag);
lazyCustomAttributesBag = _lazyCustomAttributesBag;
}

return lazyCustomAttributesBag.Attributes;
}

public override ImmutableArray<CSharpAttributeData> GetReturnTypeAttributes()
{
var lazyReturnTypeCustomAttributesBag = _lazyReturnTypeCustomAttributesBag;
if (lazyReturnTypeCustomAttributesBag == null)
{
LoadAndValidateAttributes(
OneOrMany.Create(_syntax.AttributeLists),
ref _lazyReturnTypeCustomAttributesBag,
symbolPart: AttributeLocation.Return);
lazyReturnTypeCustomAttributesBag = _lazyReturnTypeCustomAttributesBag;
}

return lazyReturnTypeCustomAttributesBag.Attributes;
}

public override int GetHashCode()
{
// this is what lambdas do (do not use hashes of other fields)
Expand All @@ -504,8 +548,7 @@ public sealed override bool Equals(Symbol symbol, TypeCompareKind compareKind)
if ((object)this == symbol) return true;

var localFunction = symbol as LocalFunctionSymbol;
return (object)localFunction != null
&& localFunction._syntax == _syntax;
return localFunction?._syntax == _syntax;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6571,12 +6571,8 @@ async System.Collections.Generic.IAsyncEnumerable<int> local([EnumeratorCancella
}
}
";
var comp = CreateCompilationWithAsyncIterator(new[] { source, EnumeratorCancellationAttributeType });
comp.VerifyDiagnostics(
// (13,70): error CS8205: Attributes are not allowed on local function parameters or type parameters
// async System.Collections.Generic.IAsyncEnumerable<int> local([EnumeratorCancellation] CancellationToken token)
Diagnostic(ErrorCode.ERR_AttributesInLocalFuncDecl, "[EnumeratorCancellation]").WithLocation(13, 70)
);
var comp = CreateCompilationWithTasksExtensions(new[] { source, EnumeratorCancellationAttributeType, AsyncStreamsTypes }, parseOptions: TestOptions.RegularPreview);
comp.VerifyDiagnostics();
}

[Fact, WorkItem(35166, "https://github.com/dotnet/roslyn/issues/35166")]
Expand Down
Loading