File: Parsing\SymbolLoader.cs
Web Access
Project: src\src\Generators\Microsoft.Gen.Logging\Microsoft.Gen.Logging.csproj (Microsoft.Gen.Logging)
// 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 Microsoft.CodeAnalysis;
using Microsoft.Gen.Shared;
 
namespace Microsoft.Gen.Logging.Parsing;
 
internal static class SymbolLoader
{
    internal const string LoggerMessageAttribute = "Microsoft.Extensions.Logging.LoggerMessageAttribute";
    internal const string LogPropertiesAttribute = "Microsoft.Extensions.Logging.LogPropertiesAttribute";
    internal const string TagProviderAttribute = "Microsoft.Extensions.Logging.TagProviderAttribute";
    internal const string TagNameAttribute = "Microsoft.Extensions.Logging.TagNameAttribute";
    internal const string LogPropertyIgnoreAttribute = "Microsoft.Extensions.Logging.LogPropertyIgnoreAttribute";
    internal const string ITagCollectorType = "Microsoft.Extensions.Logging.ITagCollector";
    internal const string ILoggerType = "Microsoft.Extensions.Logging.ILogger";
    internal const string LogLevelType = "Microsoft.Extensions.Logging.LogLevel";
    internal const string ExceptionType = "System.Exception";
    internal const string DataClassificationAttribute = "Microsoft.Extensions.Compliance.Classification.DataClassificationAttribute";
    internal const string NoDataClassificationAttribute = "Microsoft.Extensions.Compliance.Classification.NoDataClassificationAttribute";
    internal const string IEnrichmentPropertyBag = "Microsoft.Extensions.Diagnostics.Enrichment.IEnrichmentPropertyBag";
    internal const string IFormatProviderType = "System.IFormatProvider";
    internal const string ISpanFormattableType = "System.ISpanFormattable";
 
    private static readonly string[] _ignored = new[]
    {
        "System.DateTimeOffset",
        "System.Guid",
        "System.TimeSpan",
        "System.TimeOnly",
        "System.DateOnly",
        "System.Version",
        "System.Uri",
        "System.Net.IPAddress",
        "System.Net.EndPoint",
        "System.Net.IPEndPoint",
        "System.Net.DnsEndPoint",
        "System.Numerics.BigInteger",
        "System.Numerics.Complex",
        "System.Numerics.Matrix3x2",
        "System.Numerics.Matrix4x4",
        "System.Numerics.Plane",
        "System.Numerics.Quaternion",
        "System.Numerics.Vector2",
        "System.Numerics.Vector3",
        "System.Numerics.Vector4",
    };
 
    internal static SymbolHolder? LoadSymbols(
        Compilation compilation,
        Action<DiagnosticDescriptor, Location?, object?[]?> diagCallback)
    {
        var loggerSymbol = compilation.GetBestTypeByMetadataName(ILoggerType);
        var logLevelSymbol = compilation.GetBestTypeByMetadataName(LogLevelType);
        var loggerMessageAttributeSymbol = compilation.GetBestTypeByMetadataName(LoggerMessageAttribute);
        var logPropertiesAttributeSymbol = compilation.GetBestTypeByMetadataName(LogPropertiesAttribute);
        var tagProviderAttributeSymbol = compilation.GetBestTypeByMetadataName(TagProviderAttribute);
        var tagNameAttributeSymbol = compilation.GetBestTypeByMetadataName(TagNameAttribute);
        var tagCollectorSymbol = compilation.GetBestTypeByMetadataName(ITagCollectorType);
        var logPropertyIgnoreAttributeSymbol = compilation.GetBestTypeByMetadataName(LogPropertyIgnoreAttribute);
        var dataClassificationAttribute = compilation.GetBestTypeByMetadataName(DataClassificationAttribute);
        var noDataClassificationAttribute = compilation.GetBestTypeByMetadataName(NoDataClassificationAttribute);
 
#pragma warning disable S1067 // Expressions should not be too complex
        if (loggerSymbol == null
            || logLevelSymbol == null
            || loggerMessageAttributeSymbol == null
            || logPropertiesAttributeSymbol == null
            || tagProviderAttributeSymbol == null
            || tagNameAttributeSymbol == null
            || tagCollectorSymbol == null
            || logPropertyIgnoreAttributeSymbol == null)
        {
            // nothing to do if these types aren't available
            return null;
        }
#pragma warning restore S1067 // Expressions should not be too complex
 
        var exceptionSymbol = compilation.GetBestTypeByMetadataName(ExceptionType);
        if (exceptionSymbol == null)
        {
            diagCallback(DiagDescriptors.MissingRequiredType, null, new object[] { ExceptionType });
            return null;
        }
 
        var enumerableSymbol = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerable);
        var formatProviderSymbol = compilation.GetBestTypeByMetadataName(IFormatProviderType)!;
        var spanFormattableSymbol = compilation.GetBestTypeByMetadataName(ISpanFormattableType);
 
        var ignorePropsSymbols = new HashSet<INamedTypeSymbol>(SymbolEqualityComparer.Default);
 
        foreach (var ign in _ignored)
        {
            var s = compilation.GetBestTypeByMetadataName(ign);
            if (s != null)
            {
                _ = ignorePropsSymbols.Add(s);
            }
        }
 
        return new(
            compilation,
            loggerMessageAttributeSymbol,
            logPropertiesAttributeSymbol,
            tagProviderAttributeSymbol,
            tagNameAttributeSymbol,
            logPropertyIgnoreAttributeSymbol,
            tagCollectorSymbol,
            loggerSymbol,
            logLevelSymbol,
            exceptionSymbol,
            ignorePropsSymbols,
            enumerableSymbol,
            formatProviderSymbol,
            spanFormattableSymbol,
            dataClassificationAttribute,
            noDataClassificationAttribute);
    }
}