-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Store nullable attribute constructor params in a field: #33668
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -286,11 +286,9 @@ private void CreateEmbeddedAttributesIfNeeded(DiagnosticBag diagnostics) | |
{ | ||
CreateEmbeddedAttributeItselfIfNeeded(diagnostics); | ||
|
||
CreateEmbeddedAttributeIfNeeded( | ||
CreateEmbeddedNullableAttributeIfNeeded( | ||
ref _lazyNullableAttribute, | ||
diagnostics, | ||
AttributeDescription.NullableAttribute, | ||
GetNullableAttributeConstructors); | ||
diagnostics); | ||
} | ||
} | ||
|
||
|
@@ -305,42 +303,36 @@ private void CreateEmbeddedAttributeItselfIfNeeded(DiagnosticBag diagnostics) | |
private void CreateEmbeddedAttributeIfNeeded( | ||
ref SynthesizedEmbeddedAttributeSymbol symbol, | ||
DiagnosticBag diagnostics, | ||
AttributeDescription description, | ||
Func<CSharpCompilation, NamedTypeSymbol, DiagnosticBag, ImmutableArray<MethodSymbol>> getConstructors = null) | ||
AttributeDescription description) | ||
{ | ||
if ((object)symbol == null) | ||
{ | ||
var attributeMetadataName = MetadataTypeName.FromFullName(description.FullName); | ||
var userDefinedAttribute = _sourceAssembly.SourceModule.LookupTopLevelMetadataType(ref attributeMetadataName); | ||
Debug.Assert((object)userDefinedAttribute.ContainingModule == _sourceAssembly.SourceModule); | ||
|
||
if (!(userDefinedAttribute is MissingMetadataTypeSymbol)) | ||
{ | ||
diagnostics.Add(ErrorCode.ERR_TypeReserved, userDefinedAttribute.Locations[0], description.FullName); | ||
} | ||
|
||
symbol = new SynthesizedEmbeddedAttributeSymbol(description, _sourceAssembly.DeclaringCompilation, getConstructors, diagnostics); | ||
AddDiagnosticsForExistingAttribute(description, diagnostics); | ||
symbol = new SynthesizedEmbeddedAttributeSymbol(description, _sourceAssembly.DeclaringCompilation, diagnostics); | ||
} | ||
} | ||
|
||
private static ImmutableArray<MethodSymbol> GetNullableAttributeConstructors( | ||
CSharpCompilation compilation, | ||
NamedTypeSymbol containingType, | ||
private void CreateEmbeddedNullableAttributeIfNeeded( | ||
ref SynthesizedEmbeddedAttributeSymbol symbol, | ||
DiagnosticBag diagnostics) | ||
{ | ||
var byteType = TypeSymbolWithAnnotations.Create(compilation.GetSpecialType(SpecialType.System_Byte)); | ||
Binder.ReportUseSiteDiagnostics(byteType.TypeSymbol, diagnostics, Location.None); | ||
var byteArray = TypeSymbolWithAnnotations.Create( | ||
ArrayTypeSymbol.CreateSZArray( | ||
byteType.TypeSymbol.ContainingAssembly, | ||
byteType)); | ||
return ImmutableArray.Create<MethodSymbol>( | ||
new SynthesizedEmbeddedAttributeConstructorSymbol( | ||
containingType, | ||
m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, byteType, 0, RefKind.None))), | ||
new SynthesizedEmbeddedAttributeConstructorSymbol( | ||
containingType, | ||
m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, byteArray, 0, RefKind.None)))); | ||
if ((object)symbol == null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
AddDiagnosticsForExistingAttribute(AttributeDescription.NullableAttribute, diagnostics); | ||
symbol = new SynthesizedEmbeddedNullableAttributeSymbol(_sourceAssembly.DeclaringCompilation, diagnostics); | ||
} | ||
} | ||
|
||
private void AddDiagnosticsForExistingAttribute(AttributeDescription description, DiagnosticBag diagnostics) | ||
{ | ||
var attributeMetadataName = MetadataTypeName.FromFullName(description.FullName); | ||
var userDefinedAttribute = _sourceAssembly.SourceModule.LookupTopLevelMetadataType(ref attributeMetadataName); | ||
Debug.Assert((object)userDefinedAttribute.ContainingModule == _sourceAssembly.SourceModule); | ||
|
||
if (!(userDefinedAttribute is MissingMetadataTypeSymbol)) | ||
{ | ||
diagnostics.Add(ErrorCode.ERR_TypeReserved, userDefinedAttribute.Locations[0], description.FullName); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,29 +27,25 @@ internal class SynthesizedEmbeddedAttributeSymbol : NamedTypeSymbol | |
private readonly string _name; | ||
private readonly NamedTypeSymbol _baseType; | ||
private readonly NamespaceSymbol _namespace; | ||
private readonly ImmutableArray<MethodSymbol> _constructors; | ||
private readonly ModuleSymbol _module; | ||
|
||
protected ImmutableArray<MethodSymbol> _constructors; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
public SynthesizedEmbeddedAttributeSymbol( | ||
AttributeDescription description, | ||
CSharpCompilation compilation, | ||
Func<CSharpCompilation, NamedTypeSymbol, DiagnosticBag, ImmutableArray<MethodSymbol>> getConstructors, | ||
DiagnosticBag diagnostics) | ||
DiagnosticBag diagnostics, | ||
bool generateDefaultConstructors = true) | ||
{ | ||
_name = description.Name; | ||
_baseType = MakeBaseType(compilation, diagnostics); | ||
|
||
if (getConstructors != null) | ||
{ | ||
_constructors = getConstructors(compilation, this, diagnostics); | ||
} | ||
else | ||
if (generateDefaultConstructors) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hate this. Any ideas on a better approach most welcome. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps replace the In reply to: 260050571 [](ancestors = 260050571) |
||
{ | ||
_constructors = ImmutableArray.Create<MethodSymbol>(new SynthesizedEmbeddedAttributeConstructorSymbol(this, m => ImmutableArray<ParameterSymbol>.Empty)); | ||
Debug.Assert(_constructors.Length == description.Signatures.Length); | ||
} | ||
|
||
Debug.Assert(_constructors.Length == description.Signatures.Length); | ||
|
||
_module = compilation.SourceModule; | ||
|
||
_namespace = _module.GlobalNamespace; | ||
|
@@ -217,4 +213,5 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, | |
GenerateMethodBodyCore(compilationState, diagnostics); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using Microsoft.Cci; | ||
using Roslyn.Utilities; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis.CSharp.Emit; | ||
using Microsoft.CodeAnalysis.PooledObjects; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.Symbols | ||
{ | ||
|
||
internal class SynthesizedEmbeddedNullableAttributeSymbol : SynthesizedEmbeddedAttributeSymbol | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
private readonly ImmutableArray<FieldSymbol> _fields; | ||
|
||
private readonly TypeSymbolWithAnnotations _byteType; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Can be stored as |
||
|
||
public SynthesizedEmbeddedNullableAttributeSymbol( | ||
CSharpCompilation compilation, | ||
DiagnosticBag diagnostics) | ||
: base(AttributeDescription.NullableAttribute, compilation, diagnostics, generateDefaultConstructors: false) | ||
{ | ||
_byteType = TypeSymbolWithAnnotations.Create(compilation.GetSpecialType(SpecialType.System_Byte)); | ||
Binder.ReportUseSiteDiagnostics(_byteType.TypeSymbol, diagnostics, Location.None); | ||
var byteArrayType = TypeSymbolWithAnnotations.Create( | ||
ArrayTypeSymbol.CreateSZArray( | ||
_byteType.TypeSymbol.ContainingAssembly, | ||
_byteType)); | ||
|
||
_fields = ImmutableArray.Create<FieldSymbol>( | ||
new SynthesizedFieldSymbol( | ||
this, | ||
byteArrayType.TypeSymbol, | ||
"nullableFlags", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this is |
||
isPublic: true, | ||
isReadOnly: true, | ||
isStatic: false)); | ||
|
||
_constructors = ImmutableArray.Create<MethodSymbol>( | ||
new SynthesizedEmbeddedAttributeConstructorWithBodySymbol( | ||
this, | ||
m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, _byteType, 0, RefKind.None)), | ||
GenerateSingleByteConstructorBody | ||
), | ||
new SynthesizedEmbeddedAttributeConstructorWithBodySymbol( | ||
this, | ||
m => ImmutableArray.Create(SynthesizedParameterSymbol.Create(m, byteArrayType, 0, RefKind.None)), | ||
GenerateByteArrayConstructorBody | ||
) | ||
); | ||
|
||
// Ensure we never get out of sync with the description | ||
Debug.Assert(_constructors.Length == AttributeDescription.NullableAttribute.Signatures.Length); | ||
} | ||
|
||
internal override IEnumerable<FieldSymbol> GetFieldsToEmit() => _fields; | ||
|
||
private void GenerateByteArrayConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements, ImmutableArray<ParameterSymbol> parameters) | ||
{ | ||
statements.Add( | ||
factory.ExpressionStatement( | ||
factory.AssignmentExpression( | ||
factory.Field( | ||
factory.This(), | ||
_fields.Single()), | ||
factory.Parameter(parameters.Single()) | ||
) | ||
) | ||
); | ||
} | ||
|
||
private void GenerateSingleByteConstructorBody(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements, ImmutableArray<ParameterSymbol> parameters) | ||
{ | ||
statements.Add( | ||
factory.ExpressionStatement( | ||
factory.AssignmentExpression( | ||
factory.Field( | ||
factory.This(), | ||
_fields.Single()), | ||
factory.Array( | ||
_byteType.TypeSymbol, | ||
ImmutableArray.Create<BoundExpression>( | ||
factory.Parameter(parameters.Single()) | ||
) | ||
) | ||
) | ||
) | ||
); | ||
} | ||
|
||
internal sealed class SynthesizedEmbeddedAttributeConstructorWithBodySymbol : SynthesizedInstanceConstructor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
ImmutableArray<ParameterSymbol> _parameters; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
readonly Action<SyntheticBoundNodeFactory, ArrayBuilder<BoundStatement>, ImmutableArray<ParameterSymbol>> _getConstructorBody; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
internal SynthesizedEmbeddedAttributeConstructorWithBodySymbol( | ||
NamedTypeSymbol containingType, | ||
Func<MethodSymbol, ImmutableArray<ParameterSymbol>> getParameters, | ||
Action<SyntheticBoundNodeFactory, ArrayBuilder<BoundStatement>, ImmutableArray<ParameterSymbol>> getConstructorBody) : | ||
base(containingType) | ||
{ | ||
_parameters = getParameters(this); | ||
_getConstructorBody = getConstructorBody; | ||
} | ||
|
||
public override ImmutableArray<ParameterSymbol> Parameters => _parameters; | ||
|
||
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) | ||
{ | ||
GenerateMethodBodyCore(compilationState, diagnostics); | ||
} | ||
|
||
protected override void GenerateMethodBodyStatements(SyntheticBoundNodeFactory factory, ArrayBuilder<BoundStatement> statements, DiagnosticBag diagnostics) => _getConstructorBody(factory, statements, _parameters); | ||
} | ||
|
||
|
||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
symbol is null
#Resolved