private ImmutableArray <TAttributeData> GetAttributes(TModuleCompilationState compilationState, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { ArrayBuilder <TAttributeData> builder = ArrayBuilder <TAttributeData> .GetInstance(); // Copy some of the attributes. // Note, when porting attributes, we are not using constructors from original symbol. // The constructors might be missing (for example, in metadata case) and doing lookup // will ensure that we report appropriate errors. foreach (TAttributeData attrData in GetCustomAttributesToEmit(compilationState)) { if (IsTargetAttribute(attrData, AttributeDescription.ParamArrayAttribute)) { if (attrData.CommonConstructorArguments.Length == 0) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_ParamArrayAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.DateTimeConstantAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_DateTimeConstantAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else { int signatureIndex = TypeManager.GetTargetAttributeSignatureIndex(UnderlyingParameter, attrData, AttributeDescription.DecimalConstantAttribute); if (signatureIndex != -1) { Debug.Assert(signatureIndex == 0 || signatureIndex == 1); if (attrData.CommonConstructorArguments.Length == 5) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute( signatureIndex == 0 ? WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctor : WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctorByteByteInt32Int32Int32, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.DefaultParameterValueAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_DefaultParameterValueAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } } } return(builder.ToImmutableAndFree()); }
protected abstract IEnumerable <TAttributeData> GetCustomAttributesToEmit(TModuleCompilationState compilationState);
private ImmutableArray <TAttributeData> GetAttributes(TModuleCompilationState compilationState, TSyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { var builder = ArrayBuilder <TAttributeData> .GetInstance(); // Put the CompilerGenerated attribute on the NoPIA types we define so that // static analysis tools (e.g. fxcop) know that they can be skipped builder.AddOptional(TypeManager.CreateCompilerGeneratedAttribute()); // Copy some of the attributes. bool hasGuid = false; bool hasComEventInterfaceAttribute = false; // Note, when porting attributes, we are not using constructors from original symbol. // The constructors might be missing (for example, in metadata case) and doing lookup // will ensure that we report appropriate errors. foreach (var attrData in GetCustomAttributesToEmit(compilationState)) { if (IsTargetAttribute(attrData, AttributeDescription.GuidAttribute)) { string guidString; if (attrData.TryGetGuidAttributeValue(out guidString)) { // If this type has a GuidAttribute, we should emit it. hasGuid = true; builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_GuidAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.ComEventInterfaceAttribute)) { if (attrData.CommonConstructorArguments.Length == 2) { hasComEventInterfaceAttribute = true; builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_ComEventInterfaceAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else { int signatureIndex = TypeManager.GetTargetAttributeSignatureIndex(UnderlyingNamedType, attrData, AttributeDescription.InterfaceTypeAttribute); if (signatureIndex != -1) { Debug.Assert(signatureIndex == 0 || signatureIndex == 1); if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(signatureIndex == 0 ? WellKnownMember.System_Runtime_InteropServices_InterfaceTypeAttribute__ctorInt16 : WellKnownMember.System_Runtime_InteropServices_InterfaceTypeAttribute__ctorComInterfaceType, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.BestFitMappingAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_BestFitMappingAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.CoClassAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_CoClassAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.FlagsAttribute)) { if (attrData.CommonConstructorArguments.Length == 0 && UnderlyingNamedType.IsEnum) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_FlagsAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } else if (IsTargetAttribute(attrData, AttributeDescription.DefaultMemberAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Reflection_DefaultMemberAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); // Embed members matching default member name. string defaultMember = attrData.CommonConstructorArguments[0].Value as string; if (defaultMember != null) { EmbedDefaultMembers(defaultMember, syntaxNodeOpt, diagnostics); } } } else if (IsTargetAttribute(attrData, AttributeDescription.UnmanagedFunctionPointerAttribute)) { if (attrData.CommonConstructorArguments.Length == 1) { builder.AddOptional(TypeManager.CreateSynthesizedAttribute(WellKnownMember.System_Runtime_InteropServices_UnmanagedFunctionPointerAttribute__ctor, attrData, syntaxNodeOpt, diagnostics)); } } } } // We must emit a TypeIdentifier attribute which connects this local type with the canonical type. // Interfaces usually have a guid attribute, in which case the TypeIdentifier attribute we emit will // not need any additional parameters. For interfaces which lack a guid and all other types, we must // emit a TypeIdentifier that has parameters identifying the scope and name of the original type. We // will use the Assembly GUID as the scope identifier. if (IsInterface && !hasComEventInterfaceAttribute) { if (!IsComImport) { // If we have an interface not marked ComImport, but the assembly is linked, then // we need to give an error. We allow event interfaces to not have ComImport marked on them. // ERRID_NoPIAAttributeMissing2/ERR_InteropTypeMissingAttribute ReportMissingAttribute(AttributeDescription.ComImportAttribute, syntaxNodeOpt, diagnostics); } else if (!hasGuid) { // Interfaces used with No-PIA ought to have a guid attribute, or the CLR cannot do type unification. // This interface lacks a guid, so unification probably won't work. We allow event interfaces to not have a Guid. // ERRID_NoPIAAttributeMissing2/ERR_InteropTypeMissingAttribute ReportMissingAttribute(AttributeDescription.GuidAttribute, syntaxNodeOpt, diagnostics); } } // Note, this logic should match the one in RetargetingSymbolTranslator.RetargetNoPiaLocalType // when we try to predict what attributes we will emit on embedded type, which corresponds the // type we are retargeting. builder.AddOptional(CreateTypeIdentifierAttribute(hasGuid && IsInterface, syntaxNodeOpt, diagnostics)); return(builder.ToImmutableAndFree()); }