| File: Emitter\Model\AttributeDataAdapter.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Symbols; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal abstract partial class CSharpAttributeData : Cci.ICustomAttribute { ImmutableArray<Cci.IMetadataExpression> Cci.ICustomAttribute.GetArguments(EmitContext context) { var commonArgs = this.CommonConstructorArguments; if (commonArgs.IsEmpty) { return ImmutableArray<Cci.IMetadataExpression>.Empty; } var builder = ArrayBuilder<Cci.IMetadataExpression>.GetInstance(); foreach (var argument in commonArgs) { Debug.Assert(argument.Kind != TypedConstantKind.Error); builder.Add(CreateMetadataExpression(argument, context)); } return builder.ToImmutableAndFree(); } Cci.IMethodReference Cci.ICustomAttribute.Constructor(EmitContext context, bool reportDiagnostics) { if (this.AttributeConstructor.IsDefaultValueTypeConstructor()) { // Default parameterless constructors for structs exist in symbol table, but are not emitted. // Produce an error since we cannot use it (instead of crashing). // Details: https://github.com/dotnet/roslyn/issues/19394 if (reportDiagnostics) { context.Diagnostics.Add(ErrorCode.ERR_NotAnAttributeClass, context.Location ?? NoLocation.Singleton, this.AttributeClass); } return null; } PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return (Cci.IMethodReference)moduleBeingBuilt.Translate(this.AttributeConstructor, (CSharpSyntaxNode)context.SyntaxNode, context.Diagnostics); } ImmutableArray<Cci.IMetadataNamedArgument> Cci.ICustomAttribute.GetNamedArguments(EmitContext context) { var commonArgs = this.CommonNamedArguments; if (commonArgs.IsEmpty) { return ImmutableArray<Cci.IMetadataNamedArgument>.Empty; } var builder = ArrayBuilder<Cci.IMetadataNamedArgument>.GetInstance(); foreach (var namedArgument in commonArgs) { builder.Add(CreateMetadataNamedArgument(namedArgument.Key, namedArgument.Value, context)); } return builder.ToImmutableAndFree(); } int Cci.ICustomAttribute.ArgumentCount { get { return this.CommonConstructorArguments.Length; } } ushort Cci.ICustomAttribute.NamedArgumentCount { get { return (ushort)this.CommonNamedArguments.Length; } } Cci.ITypeReference Cci.ICustomAttribute.GetType(EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return moduleBeingBuilt.Translate(this.AttributeClass, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); } bool Cci.ICustomAttribute.AllowMultiple { get { return this.AttributeClass.GetAttributeUsageInfo().AllowMultiple; } } private Cci.IMetadataExpression CreateMetadataExpression(TypedConstant argument, EmitContext context) { if (argument.IsNull) { return CreateMetadataConstant(argument.TypeInternal, null, context); } switch (argument.Kind) { case TypedConstantKind.Array: return CreateMetadataArray(argument, context); case TypedConstantKind.Type: return CreateType(argument, context); default: return CreateMetadataConstant(argument.TypeInternal, argument.ValueInternal, context); } } private MetadataCreateArray CreateMetadataArray(TypedConstant argument, EmitContext context) { Debug.Assert(!argument.Values.IsDefault); var values = argument.Values; var arrayType = ((PEModuleBuilder)context.Module).Translate((ArrayTypeSymbol)argument.TypeInternal); if (values.Length == 0) { return new MetadataCreateArray(arrayType, arrayType.GetElementType(context), ImmutableArray<Cci.IMetadataExpression>.Empty); } var metadataExprs = new Cci.IMetadataExpression[values.Length]; for (int i = 0; i < values.Length; i++) { metadataExprs[i] = CreateMetadataExpression(values[i], context); } return new MetadataCreateArray(arrayType, arrayType.GetElementType(context), metadataExprs.AsImmutableOrNull()); } private static MetadataTypeOf CreateType(TypedConstant argument, EmitContext context) { Debug.Assert(argument.ValueInternal != null); var moduleBeingBuilt = (PEModuleBuilder)context.Module; var syntaxNodeOpt = (CSharpSyntaxNode)context.SyntaxNode; var diagnostics = context.Diagnostics; return new MetadataTypeOf(moduleBeingBuilt.Translate((TypeSymbol)argument.ValueInternal, syntaxNodeOpt, diagnostics), moduleBeingBuilt.Translate((TypeSymbol)argument.TypeInternal, syntaxNodeOpt, diagnostics)); } private static MetadataConstant CreateMetadataConstant(ITypeSymbolInternal type, object value, EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return moduleBeingBuilt.CreateConstant((TypeSymbol)type, value, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); } private Cci.IMetadataNamedArgument CreateMetadataNamedArgument(string name, TypedConstant argument, EmitContext context) { var symbol = LookupName(name); var value = CreateMetadataExpression(argument, context); TypeSymbol type; var fieldSymbol = symbol as FieldSymbol; if ((object)fieldSymbol != null) { type = fieldSymbol.Type; } else { type = ((PropertySymbol)symbol).Type; } PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return new MetadataNamedArgument(symbol, moduleBeingBuilt.Translate(type, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics), value); } private Symbol LookupName(string name) { var type = this.AttributeClass; while ((object)type != null) { foreach (var member in type.GetMembers(name)) { if (member.DeclaredAccessibility == Accessibility.Public) { return member; } } type = type.BaseTypeNoUseSiteDiagnostics; } Debug.Assert(false, "Name does not match an attribute field or a property. How can that be?"); return null; } } }