public static void EmitInsideNamespace(this JavascriptFormatter formatter, TypeDefinition typedef, bool isTopLevel, Action <bool> inner)
        {
            var fullNamespace = DefinitelyTypedUtilities.GetFullNamespace(typedef);

            foreach (var part in fullNamespace)
            {
                if (isTopLevel)
                {
                    formatter.WriteRaw("export");
                    formatter.Space();
                    formatter.WriteRaw("declare");
                    formatter.Space();
                    isTopLevel = false;
                }

                formatter.WriteRaw("namespace");
                formatter.Space();
                formatter.Identifier(part);
                formatter.Space();
                formatter.OpenBrace();
            }

            inner(isTopLevel);

            foreach (var part in fullNamespace)
            {
                formatter.CloseBrace();
            }
        }
        private void EmitInterfaceMethod(MethodDefinition method)
        {
            Formatter.Identifier("Call");

            if (method.GenericParameters.Count > 0)
            {
                Formatter.WriteGenericArgumentsIfNeed(method.GenericParameters, method.DeclaringType.GenericParameters);
            }

            Formatter.WriteRaw("(");
            Formatter.Identifier("thisArg");
            Formatter.Space();
            Formatter.WriteRaw(":");
            Formatter.Space();
            Formatter.WriteSelfReference(method.DeclaringType, Facade.Instance);
            Formatter.Comma();

            if (method.GenericParameters.Count > 0)
            {
                Formatter.Identifier("genericArgs");
                Formatter.Space();
                Formatter.WriteRaw(":");
                Formatter.Space();
                Formatter.OpenBracket();
                Formatter.CommaSeparatedList(DefinitelyTypedUtilities.BuildGenericParemetersMap(method.GenericParameters, method.DeclaringType.GenericParameters), pair => {
                    Formatter.WriteRaw("$Type");
                    Formatter.WriteGenericArgumentsIfNeed(new[] { DefinitelyTypedUtilities.GetGenericParameterInstanceParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterInParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterOutParameterName(pair.Value) });
                });
                Formatter.CloseBracket();
            }
            else
            {
                Formatter.WriteRaw("nullArg");
                Formatter.Space();
                Formatter.WriteRaw(":");
                Formatter.Space();
                Formatter.Identifier("$Null");
            }

            if (method.Parameters.Count > 0)
            {
                Formatter.Comma();

                Formatter.CommaSeparatedList(method.Parameters, item => {
                    Formatter.Identifier(item.Name);
                    Formatter.Space();
                    Formatter.WriteRaw(":");
                    Formatter.Space();
                    Formatter.WriteTypeReference(item.ParameterType, null, JavascriptFormatterHelper.ReplaceMode.Instance);
                });
            }

            Formatter.WriteRaw(")");
            Formatter.Space();
            Formatter.WriteRaw(":");
            Formatter.Space();
            Formatter.WriteTypeReference(method.ReturnType, null, JavascriptFormatterHelper.ReplaceMode.Out);
            Formatter.Semicolon();
        }
        public static void WriteGenericMethodSignatureWithoutResultType(this JavascriptFormatter formatter, IEnumerable <GenericParameter> args, IEnumerable <GenericParameter> additionalArgsForNameCalculation)
        {
            formatter.WriteGenericArgumentsIfNeed(args, additionalArgsForNameCalculation);
            formatter.WriteRaw("(");

            formatter.CommaSeparatedList(DefinitelyTypedUtilities.BuildGenericParemetersMap(args, additionalArgsForNameCalculation), pair => {
                formatter.Identifier("__" + pair.Value);
                formatter.Space();
                formatter.WriteRaw(":");
                formatter.Space();
                formatter.WriteRaw("$Type");
                formatter.WriteGenericArgumentsIfNeed(new[] { DefinitelyTypedUtilities.GetGenericParameterInstanceParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterInParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterOutParameterName(pair.Value) });
            });
            formatter.WriteRaw(")");
        }
        public override bool EmitTypeDeclarationHeader(DecompilerContext context, IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo)
        {
            if (!DefinitelyTypedUtilities.IsTypePublic(typedef))
            {
                return(true);
            }

            Formatter.EmitInsideNamespace(typedef, true, isTopLevel => {
                if (isTopLevel)
                {
                    Formatter.WriteRaw("export");
                    Formatter.Space();
                    Formatter.WriteRaw("declare");
                    Formatter.Space();
                }

                Formatter.WriteRaw("let");
                Formatter.Space();

                Formatter.Identifier(DefinitelyTypedUtilities.GetClassName(typedef));
                Formatter.Space();
                Formatter.WriteRaw(":");
                Formatter.Space();

                Formatter.Identifier("$this");
                Formatter.Dot();

                foreach (var part in DefinitelyTypedUtilities.GetFullNamespace(typedef))
                {
                    Formatter.Identifier(part);
                    Formatter.Dot();
                }

                Formatter.Identifier(DefinitelyTypedUtilities.GetClassName(typedef));
                Formatter.Dot();
                Formatter.Identifier("Factory");
                Formatter.Semicolon();
            });

            return(true);
        }
        public override bool EmitTypeDeclarationHeader(DecompilerContext context, IAstEmitter astEmitter, TypeDefinition typedef, TypeInfo typeInfo)
        {
            if (!DefinitelyTypedUtilities.IsTypePublic(typedef))
            {
                return(true);
            }

            Formatter.EmitInsideNamespace(typedef, false, isTopLevel => {
                Formatter.WriteRaw("namespace");
                Formatter.Space();
                Formatter.Identifier(DefinitelyTypedUtilities.GetClassName(typedef));
                Formatter.OpenBrace();
                EmitClassInstance(typedef);
                EmitClassInOutType(typedef);
                EmitClassStatic(typedef);
                EmitClassFactory(typedef);
                Formatter.CloseBrace();
            });

            Formatter.NewLine();

            return(true);
        }
 public static void WriteGenericArgumentsIfNeed(this JavascriptFormatter formatter, IEnumerable <GenericParameter> args, IEnumerable <GenericParameter> additionalArgsForNameCalculation)
 {
     formatter.WriteGenericArgumentsIfNeed(
         DefinitelyTypedUtilities.BuildGenericParemetersMap(args, additionalArgsForNameCalculation)
         .SelectMany(pair => new[] { DefinitelyTypedUtilities.GetGenericParameterInstanceParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterInParameterName(pair.Value), DefinitelyTypedUtilities.GetGenericParameterOutParameterName(pair.Value) }));
 }
        private void EmitClassInstance(TypeDefinition typedef)
        {
            Formatter.WriteRaw("class");
            Formatter.Space();
            Formatter.WriteSelfReference(typedef, Facade.Instance);
            Formatter.Space();
            Formatter.OpenBrace();

            Formatter.WriteRaw("private __$brand_");
            Formatter.Identifier(typedef.FullName);
            Formatter.WriteRaw(" : any");
            Formatter.Semicolon();

            foreach (var genericParameter in DefinitelyTypedUtilities.BuildGenericParemetersMap(typedef.GenericParameters, null))
            {
                Formatter.WriteRaw("private");
                Formatter.Space();
                Formatter.WriteRaw("__$" + genericParameter.Value + "_brand_");
                Formatter.Identifier(typedef.FullName);
                Formatter.Space();
                Formatter.WriteRaw(":");
                Formatter.Space();
                if (genericParameter.Key.IsCovariant)
                {
                    Formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterOutParameterName(genericParameter.Value));
                }
                else if (genericParameter.Key.IsContravariant)
                {
                    Formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterInParameterName(genericParameter.Value));
                }
                else
                {
                    Formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterInstanceParameterName(genericParameter.Value));
                }
                Formatter.Semicolon();
            }

            if (!typedef.IsInterface)
            {
                var instanceFields = typedef.Fields.Where(it => it.IsPublic && !it.IsStatic && !Translator.ShouldSkipMember(it)).OrderBy(md => md.Name);
                foreach (var instanceField in instanceFields)
                {
                    EmitField(instanceField);
                }

                // TODO: We need filter them to not hide fields
                var instanceProperties = typedef.Properties
                                         .Where(it => !Translator.ShouldSkipMember(it) && !it.HasParameters && (
                                                    (it.GetMethod != null && it.GetMethod.IsPublic && !it.GetMethod.IsStatic && !Translator.ShouldSkipMember(it.GetMethod)) ||
                                                    (it.SetMethod != null && it.SetMethod.IsPublic && !it.SetMethod.IsStatic && !Translator.ShouldSkipMember(it.SetMethod))))
                                         .OrderBy(md => md.Name);
                foreach (var instanceProperty in instanceProperties)
                {
                    EmitProperty(instanceProperty);
                }

                var instanceMethods = typedef.Methods.Where(it => it.IsPublic && !it.IsStatic && !it.IsConstructor && !Translator.ShouldSkipMember(it)).OrderBy(md => md.Name);
                foreach (var instanceMethod in instanceMethods)
                {
                    EmitMethod(instanceMethod);
                }
            }

            Formatter.CloseBrace();
        }
        public static bool WriteTypeReference(this JavascriptFormatter formatter, TypeReference typeReference, TypeDefinition context, ReplaceMode replaceMode, bool useStandartSubstitution = true)
        {
            if (typeReference is ArrayType)
            {
                var arrayType = (ArrayType)typeReference;
                formatter.WriteRaw("$asmJsilCore.System.");
                formatter.Identifier(arrayType.IsVector ? "Vector" : "Array");
                formatter.TRSuffix(replaceMode);
                formatter.WriteRaw("<");
                formatter.WriteTypeReference(arrayType.ElementType, context, ReplaceMode.Instance);
                formatter.Comma();
                formatter.WriteTypeReference(arrayType.ElementType, context, ReplaceMode.In);
                formatter.Comma();
                formatter.WriteTypeReference(arrayType.ElementType, context, ReplaceMode.Out);
                if (!arrayType.IsVector)
                {
                    formatter.Comma();
                    formatter.WriteRaw("\"");
                    formatter.Value(arrayType.Dimensions.Count.ToString(CultureInfo.InvariantCulture));
                    formatter.WriteRaw("\"");
                }
                formatter.WriteRaw(">");
            }
            else if (typeReference is ByReferenceType)
            {
                var byRefType = (ByReferenceType)typeReference;
                formatter.WriteRaw("$asmJsilCore.JSIL.Reference");
                formatter.TRSuffix(replaceMode);
                formatter.WriteRaw("<");
                formatter.WriteTypeReference(byRefType.ElementType, context, ReplaceMode.Instance);
                formatter.Comma();
                formatter.WriteTypeReference(byRefType.ElementType, context, ReplaceMode.In);
                formatter.Comma();
                formatter.WriteTypeReference(byRefType.ElementType, context, ReplaceMode.Out);
                formatter.WriteRaw(">");
            }
            else if (typeReference is GenericParameter)
            {
                var gp = (GenericParameter)typeReference;
                DefinitelyTypedUtilities.GenericParemetersKeyedCollection map;
                if (gp.Owner is TypeDefinition)
                {
                    map = DefinitelyTypedUtilities.BuildGenericParemetersMap(((TypeDefinition)gp.Owner).GenericParameters, null);
                }
                else if (gp.Owner is MethodDefinition)
                {
                    map = DefinitelyTypedUtilities.BuildGenericParemetersMap(((MethodDefinition)gp.Owner).GenericParameters, ((MethodDefinition)gp.Owner).DeclaringType.GenericParameters);
                }
                else
                {
                    throw new Exception("Unexpected generic parameter owner");
                }

                var name = map[gp].Value;

                switch (replaceMode)
                {
                case ReplaceMode.Instance:
                    formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterInstanceParameterName(name));
                    break;

                case ReplaceMode.Out:
                    formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterOutParameterName(name));
                    break;

                case ReplaceMode.In:
                    formatter.Identifier(DefinitelyTypedUtilities.GetGenericParameterInParameterName(name));
                    break;

                default:
                    throw new ArgumentOutOfRangeException("replaceMode", replaceMode, null);
                }
            }
            else if (typeReference is GenericInstanceType)
            {
                var genericType = (GenericInstanceType)typeReference;
                if (formatter.WriteTypeReference(genericType.ElementType, context, replaceMode)) /*TODO*/
                {
                    formatter.WriteRaw("<");
                    formatter.CommaSeparatedList(genericType.GenericArguments, genericArgument => {
                        formatter.WriteTypeReference(genericArgument, context, ReplaceMode.Instance);
                        formatter.Comma();
                        formatter.WriteTypeReference(genericArgument, context, ReplaceMode.In);
                        formatter.Comma();
                        formatter.WriteTypeReference(genericArgument, context, ReplaceMode.Out);
                    });
                    formatter.WriteRaw(">");
                }
            }
            else if (typeReference is PointerType || typeReference is OptionalModifierType || typeReference is RequiredModifierType || typeReference is PinnedType || typeReference is SentinelType || typeReference is FunctionPointerType ||
                     (!_coreTypes.Contains(typeReference.FullName) && formatter.TypeInfo.Get(typeReference).IsSuppressDeclaration))
            {
                formatter.WriteRaw("Object"); // TODO!
                return(false);
            }
            else
            {
                string rawType;
                if (useStandartSubstitution && _rawTypes.TryGetValue(typeReference.FullName, out rawType))
                {
                    formatter.WriteRaw(rawType);
                }
                else
                {
                    var    definition     = typeReference.Resolve();
                    var    targetAssembly = JavascriptFormatter.GetContainingAssemblyName(typeReference);
                    string assemblyRef;

                    if (_coreTypes.Contains(definition.FullName))
                    {
                        assemblyRef = "$asmJsilCore";
                    }
                    else if (targetAssembly == formatter.Assembly.FullName)
                    {
                        assemblyRef = string.Empty;
                    }
                    else
                    {
                        assemblyRef = formatter.Manifest.Entries.FirstOrDefault(item => item.Value == targetAssembly).Key;
                    }
                    if (definition != null && assemblyRef != null)
                    {
                        if (assemblyRef != string.Empty)
                        {
                            formatter.Identifier(assemblyRef);
                            formatter.Dot();
                        }
                        else
                        {
                            formatter.Identifier("$private");
                            formatter.Dot();
                        }

                        foreach (var part in DefinitelyTypedUtilities.GetFullNamespace(definition))
                        {
                            formatter.Identifier(part);
                            formatter.Dot();
                        }

                        formatter.Identifier(DefinitelyTypedUtilities.GetClassName(definition));

                        /* Hack to solve ciruclar refrence in generics.
                         * It could be improved, by we really need generic variance support or support of:
                         * type T = something & I<T> (see Microsoft/TypeScript#6230)
                         */
                        var fixedMode = (replaceMode != ReplaceMode.Instance && context == definition) ? ReplaceMode.Instance : replaceMode;
                        formatter.TRSuffix(fixedMode);
                    }
                    else
                    {
                        //TODO: We was unable to resolve assembly. Think about JSIL Proxies
                        formatter.WriteRaw("Object");
                        return(false);
                    }
                }
            }
            return(true);
        }
        private void EmitClassInOutType(TypeDefinition typedef)
        {
            /*In*/
            Formatter.WriteRaw("type");
            Formatter.Space();
            Formatter.WriteSelfReference(typedef, Facade.TIn);

            Formatter.Space();
            Formatter.WriteRaw("=");
            Formatter.Space();

            Formatter.WriteSelfReference(typedef, Facade.Instance);

            if (typedef.IsClass && typedef.BaseType != null)
            {
                Formatter.Space();
                Formatter.WriteRaw("|");
                Formatter.Space();
                Formatter.WriteTypeReference(typedef.BaseType, typedef, JavascriptFormatterHelper.ReplaceMode.In, false);
            }

            var interfaces = typedef.Interfaces.Where(it => DefinitelyTypedUtilities.IsTypePublic(it) && !Translator.ShouldSkipMember(it));

            foreach (var iface in interfaces)
            {
                Formatter.Space();
                Formatter.WriteRaw("|");
                Formatter.Space();
                Formatter.WriteTypeReference(iface, typedef, JavascriptFormatterHelper.ReplaceMode.In, false);
            }

            Formatter.Semicolon();

            /*Out*/
            Formatter.WriteRaw("type");
            Formatter.Space();
            Formatter.WriteSelfReference(typedef, Facade.TOut);

            Formatter.Space();
            Formatter.WriteRaw("=");
            Formatter.Space();

            Formatter.WriteSelfReference(typedef, Facade.Instance);

            if (typedef.IsClass && typedef.BaseType != null)
            {
                Formatter.Space();
                Formatter.WriteRaw("&");
                Formatter.Space();
                Formatter.WriteTypeReference(typedef.BaseType, typedef, JavascriptFormatterHelper.ReplaceMode.Out, false);
            }

            foreach (var iface in interfaces)
            {
                Formatter.Space();
                Formatter.WriteRaw("&");
                Formatter.Space();
                Formatter.WriteTypeReference(iface, typedef, JavascriptFormatterHelper.ReplaceMode.Out, false);
            }

            Formatter.Semicolon();
        }