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();
            }
        }
        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 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);
        }