File: JSMarshalAsAttributeInfoParser.cs
Web Access
Project: src\src\libraries\System.Runtime.InteropServices.JavaScript\gen\JSImportGenerator\JSImportGenerator.csproj (Microsoft.Interop.JavaScript.JSImportGenerator)
// 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.Data;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using Microsoft.CodeAnalysis;
 
namespace Microsoft.Interop.JavaScript
{
    internal sealed class JSMarshalAsAttributeParser : IMarshallingInfoAttributeParser, IUseSiteAttributeParser
    {
        private readonly INamedTypeSymbol _jsMarshalAsAttribute;
 
        public JSMarshalAsAttributeParser(Compilation compilation)
        {
            _jsMarshalAsAttribute = compilation.GetTypeByMetadataName(Constants.JSMarshalAsAttribute)!.ConstructUnboundGenericType();
        }
        public bool CanParseAttributeType(INamedTypeSymbol attributeType) => attributeType.IsGenericType && SymbolEqualityComparer.Default.Equals(_jsMarshalAsAttribute, attributeType.ConstructUnboundGenericType());
        public MarshallingInfo ParseAttribute(AttributeData attributeData, ITypeSymbol type, int indirectionDepth, UseSiteAttributeProvider useSiteAttributes, GetMarshallingInfoCallback marshallingInfoCallback)
        {
            JSTypeFlags jsType = JSTypeFlags.None;
            List<JSTypeFlags> jsTypeArguments = new List<JSTypeFlags>();
            INamedTypeSymbol? jsTypeArgs = attributeData.AttributeClass.TypeArguments[0] as INamedTypeSymbol;
            if (jsTypeArgs.IsGenericType)
            {
                string gt = jsTypeArgs.ConstructUnboundGenericType().ToDisplayString();
                string name = gt.Substring(gt.IndexOf("JSType") + "JSType.".Length);
                name = name.Substring(0, name.IndexOf("<"));
 
                Enum.TryParse(name, out jsType);
 
                foreach (var ta in jsTypeArgs.TypeArguments.Cast<INamedTypeSymbol>().Select(x => x.ToDisplayString()))
                {
                    string argName = ta.Substring(ta.IndexOf("JSType") + "JSType.".Length);
                    JSTypeFlags jsTypeArg = JSTypeFlags.None;
                    Enum.TryParse(argName, out jsTypeArg);
                    jsTypeArguments.Add(jsTypeArg);
                }
            }
            else
            {
                string st = jsTypeArgs.ToDisplayString();
                string name = st.Substring(st.IndexOf("JSType") + "JSType.".Length);
                Enum.TryParse(name, out jsType);
            }
 
            if (jsType == JSTypeFlags.None)
            {
                return new JSMissingMarshallingInfo(JSTypeInfo.CreateJSTypeInfoForTypeSymbol(type));
            }
 
            return new JSMarshallingInfo(NoMarshallingInfo.Instance, JSTypeInfo.CreateJSTypeInfoForTypeSymbol(type))
            {
                JSType = jsType,
                JSTypeArguments = jsTypeArguments.ToArray(),
            };
        }
 
        UseSiteAttributeData IUseSiteAttributeParser.ParseAttribute(AttributeData attributeData, IElementInfoProvider elementInfoProvider, GetMarshallingInfoCallback marshallingInfoCallback)
        {
            return new UseSiteAttributeData(0, NoCountInfo.Instance, attributeData);
        }
    }
}