private JsExpression GetMetadataDescriptor(ITypeDefinition type, bool isGenericSpecialization)
        {
            var properties           = new List <JsObjectLiteralProperty>();
            var scriptableAttributes = type.Attributes.Where(a => !a.IsConditionallyRemoved && _metadataImporter.GetTypeSemantics(a.AttributeType.GetDefinition()).Type == TypeScriptSemantics.ImplType.NormalType).ToList();

            if (scriptableAttributes.Count != 0)
            {
                properties.Add(new JsObjectLiteralProperty("attr", JsExpression.ArrayLiteral(scriptableAttributes.Select(a => MetadataUtils.ConstructAttribute(a, type, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter)))));
            }
            if (type.Kind == TypeKind.Interface && MetadataUtils.IsJsGeneric(type, _metadataImporter) && type.TypeParameters != null && type.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant))
            {
                properties.Add(new JsObjectLiteralProperty("variance", JsExpression.ArrayLiteral(type.TypeParameters.Select(typeParameter => JsExpression.Number(ConvertVarianceToInt(typeParameter.Variance))))));
            }
            if (type.Kind == TypeKind.Class)
            {
                var members = type.Members.Where(m => MetadataUtils.IsReflectable(m, _metadataImporter))
                              .OrderBy(m => m, MemberOrderer.Instance)
                              .Select(m => {
                    _errorReporter.Region = m.Region;
                    return(MetadataUtils.ConstructMemberInfo(m, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, t => _runtimeLibrary.InstantiateType(t, isGenericSpecialization ? _genericSpecializationReflectionRuntimeContext : _defaultReflectionRuntimeContext), includeDeclaringType: false));
                })
                              .ToList();
                if (members.Count > 0)
                {
                    properties.Add(new JsObjectLiteralProperty("members", JsExpression.ArrayLiteral(members)));
                }

                var aua = AttributeReader.ReadAttribute <AttributeUsageAttribute>(type);
                if (aua != null)
                {
                    if (!aua.Inherited)
                    {
                        properties.Add(new JsObjectLiteralProperty("attrNoInherit", JsExpression.True));
                    }
                    if (aua.AllowMultiple)
                    {
                        properties.Add(new JsObjectLiteralProperty("attrAllowMultiple", JsExpression.True));
                    }
                }
            }
            if (type.Kind == TypeKind.Enum && AttributeReader.HasAttribute <FlagsAttribute>(type))
            {
                properties.Add(new JsObjectLiteralProperty("enumFlags", JsExpression.True));
            }

            return(properties.Count > 0 ? JsExpression.ObjectLiteral(properties) : null);
        }
 public static bool IsImported(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <ImportedAttribute>(type));
 }
 public static bool IsMixin(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <MixinAttribute>(type));
 }
 public static bool IsSerializable(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <SerializableAttribute>(type) || (type.GetAllBaseTypeDefinitions().Any(td => td.FullName == "System.Record") && type.FullName != "System.Record"));
 }
        /// <summary>
        /// Determines the preferred name for a member. The first item is the name, the second item is true if the name was explicitly specified.
        /// </summary>
        public static Tuple <string, bool> DeterminePreferredMemberName(IMember member, bool minimizeNames)
        {
            member = UnwrapValueTypeConstructor(member);

            bool isConstructor        = member is IMethod && ((IMethod)member).IsConstructor;
            bool isAccessor           = member is IMethod && ((IMethod)member).IsAccessor;
            bool isPreserveMemberCase = IsPreserveMemberCase(member.DeclaringTypeDefinition);

            string defaultName;

            if (isConstructor)
            {
                defaultName = "$ctor";
            }
            else if (!CanBeMinimized(member))
            {
                defaultName = isPreserveMemberCase ? member.Name : MakeCamelCase(member.Name);
            }
            else
            {
                if (minimizeNames && member.DeclaringType.Kind != TypeKind.Interface)
                {
                    defaultName = null;
                }
                else
                {
                    defaultName = "$" + (isPreserveMemberCase ? member.Name : MakeCamelCase(member.Name));
                }
            }

            var asa = AttributeReader.ReadAttribute <AlternateSignatureAttribute>(member);

            if (asa != null)
            {
                var otherMembers = member.DeclaringTypeDefinition.Methods.Where(m => m.Name == member.Name && !AttributeReader.HasAttribute <AlternateSignatureAttribute>(m) && !AttributeReader.HasAttribute <NonScriptableAttribute>(m) && !AttributeReader.HasAttribute <InlineCodeAttribute>(m)).ToList();
                if (otherMembers.Count == 1)
                {
                    return(DeterminePreferredMemberName(otherMembers[0], minimizeNames));
                }
                else
                {
                    return(Tuple.Create(member.Name, false));                           // Error
                }
            }

            var sna = AttributeReader.ReadAttribute <ScriptNameAttribute>(member);

            if (sna != null)
            {
                string name = sna.Name;
                if (IsNamedValues(member.DeclaringTypeDefinition) && (name == "" || !name.IsValidJavaScriptIdentifier()))
                {
                    return(Tuple.Create(defaultName, false));                           // For named values enum, allow the use to specify an empty or invalid value, which will only be used as the literal value for the field, not for the name.
                }
                if (name == "" && isConstructor)
                {
                    name = "$ctor";
                }
                return(Tuple.Create(name, true));
            }

            if (isConstructor && IsImported(member.DeclaringTypeDefinition))
            {
                return(Tuple.Create("$ctor", true));
            }

            var ica = AttributeReader.ReadAttribute <InlineCodeAttribute>(member);

            if (ica != null)
            {
                if (ica.GeneratedMethodName != null)
                {
                    return(Tuple.Create(ica.GeneratedMethodName, true));
                }
            }

            if (AttributeReader.HasAttribute <PreserveCaseAttribute>(member))
            {
                return(Tuple.Create(member.Name, true));
            }

            bool preserveName = (!isConstructor && !isAccessor && (AttributeReader.HasAttribute <PreserveNameAttribute>(member) ||
                                                                   AttributeReader.HasAttribute <InstanceMethodOnFirstArgumentAttribute>(member) ||
                                                                   AttributeReader.HasAttribute <IntrinsicPropertyAttribute>(member) ||
                                                                   IsPreserveMemberNames(member.DeclaringTypeDefinition) && member.ImplementedInterfaceMembers.Count == 0 && !member.IsOverride) ||
                                 (IsSerializable(member.DeclaringTypeDefinition) && !member.IsStatic && (member is IProperty || member is IField))) ||
                                (IsNamedValues(member.DeclaringTypeDefinition) && member is IField);

            if (preserveName)
            {
                return(Tuple.Create(isPreserveMemberCase ? member.Name : MakeCamelCase(member.Name), true));
            }

            return(Tuple.Create(defaultName, false));
        }
 public static bool CanBeMinimized(IMember member)
 {
     return(!member.IsExternallyVisible() || AttributeReader.HasAttribute <MinimizePublicNamesAttribute>(member.ParentAssembly.AssemblyAttributes));
 }
 public static bool IsAsyncModule(IAssembly assembly)
 {
     return(AttributeReader.HasAttribute <AsyncModuleAttribute>(assembly.AssemblyAttributes));
 }
 public static bool IsGlobalMethods(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <GlobalMethodsAttribute>(type));
 }
 public static bool IsNamedValues(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <NamedValuesAttribute>(type));
 }
 public static bool IsResources(ITypeDefinition type)
 {
     return(AttributeReader.HasAttribute <ResourcesAttribute>(type));
 }