File: GeneratorDiagnosticsBag.cs
Web Access
Project: src\src\libraries\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj (Microsoft.Interop.SourceGeneration)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Resources;
using Microsoft.CodeAnalysis;
 
namespace Microsoft.Interop
{
    /// <summary>
    /// A bag of diagnostics that generators can report diagnostics to.
    /// </summary>
    public class GeneratorDiagnosticsBag
    {
        private readonly IDiagnosticDescriptorProvider _descriptorProvider;
        private readonly ISignatureDiagnosticLocations _locations;
        private readonly ResourceManager _resourceManager;
        private readonly Type _resourceSource;
 
        private readonly List<DiagnosticInfo> _diagnostics = new();
        public IEnumerable<DiagnosticInfo> Diagnostics => _diagnostics;
 
        /// <summary>
        /// Construct a generator diagnostics bag.
        /// </summary>
        /// <param name="descriptorProvider">A provider of specific diagnostic descriptors to use.</param>
        /// <param name="locations">A provider of locations for diagnostics on <see cref="TypePositionInfo"/>s.</param>
        /// <param name="resourceManager">A resource manager to resolve resource string parameters to diagnostics.</param>
        /// <param name="resourceSource">The type that represents the resource source.</param>
        public GeneratorDiagnosticsBag(IDiagnosticDescriptorProvider descriptorProvider, ISignatureDiagnosticLocations locations, ResourceManager resourceManager, Type resourceSource)
        {
            _descriptorProvider = descriptorProvider;
            _locations = locations;
            _resourceManager = resourceManager;
            _resourceSource = resourceSource;
        }
 
        /// <summary>
        /// Report a diagnostic.
        /// </summary>
        /// <param name="diagnostic">The diagnostic info.</param>
        public void ReportDiagnostic(DiagnosticInfo diagnostic)
        {
            _diagnostics.Add(diagnostic);
        }
 
        /// <summary>
        /// Report diagnostic for configuration that is not supported by the DLL import source generator
        /// </summary>
        /// <param name="attributeData">Attribute specifying the unsupported configuration</param>
        /// <param name="configurationName">Name of the configuration</param>
        /// <param name="unsupportedValue">Unsupported configuration value</param>
        public void ReportConfigurationNotSupported(
            AttributeData attributeData,
            string configurationName,
            string unsupportedValue)
        {
            ReportDiagnostic(attributeData.CreateDiagnosticInfo(_descriptorProvider.ConfigurationValueNotSupported, unsupportedValue, configurationName));
        }
 
        /// <summary>
        /// Report diagnostic for configuration that is not supported by the DLL import source generator
        /// </summary>
        /// <param name="attributeData">Attribute specifying the unsupported configuration</param>
        /// <param name="configurationName">Name of the configuration</param>
        public void ReportConfigurationNotSupported(
            AttributeData attributeData,
            string configurationName)
        {
            ReportDiagnostic(attributeData.CreateDiagnosticInfo(_descriptorProvider.ConfigurationNotSupported, configurationName));
        }
 
        /// <summary>
        /// Report a diagnostic for an invalid marshalling attribute.
        /// </summary>
        /// <param name="attributeData">The attribute data.</param>
        /// <param name="reasonResourceName">A resource name with the string describing the reason the attribute is invalid.</param>
        /// <param name="reasonArgs">The arguments for the localizable string.</param>
        public void ReportInvalidMarshallingAttributeInfo(
            AttributeData attributeData,
            string reasonResourceName,
            params string[] reasonArgs)
        {
            ReportDiagnostic(attributeData.CreateDiagnosticInfo(_descriptorProvider.InvalidMarshallingAttributeInfo, new LocalizableResourceString(reasonResourceName, _resourceManager, _resourceSource, reasonArgs)));
        }
 
        /// <summary>
        /// Report a diagnostic generated when resolving a generator.
        /// </summary>
        /// <param name="diagnostic">The generated diagnostic.</param>
        /// <exception cref="InvalidOperationException">The <see cref="IDiagnosticDescriptorProvider"/> did not provide a diagnostic for a fatal diagnostic.</exception>
        public void ReportGeneratorDiagnostic(GeneratorDiagnostic diagnostic)
        {
            DiagnosticDescriptor? descriptor = _descriptorProvider.GetDescriptor(diagnostic);
            if (descriptor is null)
            {
                if (diagnostic.IsFatal)
                {
                    throw new InvalidOperationException();
                }
                return;
            }
            _diagnostics.Add(_locations.CreateDiagnosticInfo(descriptor, diagnostic));
        }
 
        /// <summary>
        /// Report a diagnostic generated when resolving a generator.
        /// </summary>
        /// <param name="diagnostic">The generated diagnostic.</param>
        /// <exception cref="InvalidOperationException">The <see cref="IDiagnosticDescriptorProvider"/> did not provide a diagnostic for a fatal diagnostic.</exception>
        public void ReportGeneratorDiagnostics(ImmutableArray<GeneratorDiagnostic> diagnostics)
        {
            foreach (var diagnostic in diagnostics)
            {
                ReportGeneratorDiagnostic(diagnostic);
            }
        }
    }
 
    /// <summary>
    /// Properties that are common to many interop generators' diagnostics. These properties are used by code-fixers to provide a good user experience.
    /// </summary>
    public class GeneratorDiagnosticProperties
    {
        /// <summary>
        /// The diagnostic can be resolved by adding the System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute to the assembly
        /// </summary>
        public const string AddDisableRuntimeMarshallingAttribute = nameof(AddDisableRuntimeMarshallingAttribute);
 
        /// <summary>
        /// The diagnostic can be resolved by adding the System.Runtime.InteropServices.MarshalAsAttribute to the element with one of the UnmanagedType values
        /// specified in the comma-separated list of values specified in the value of this property.
        /// </summary>
        public const string AddMarshalAsAttribute = nameof(AddMarshalAsAttribute);
    }
}