Esempio n. 1
0
        private static void WriteOutOneType(OutputWriter parentModuleWriter, Context.SyntaxAndSymbol[] typeSymbols, bool fileExists)
        {
            TypeProcessor.ClearUsedTypes();
            var mynamespace = Context.Instance.Type.ContainingNamespace.FullName().RemoveFromEndOfString(".Namespace");

            var fullname = Context.Instance.Namespace + "." + Context.Instance.TypeName;

            if (TypeRenames.ContainsKey(fullname))
            {
                Context.Instance.TypeName = TypeRenames[fullname];
            }

            // + "." + TypeState.Instance.TypeName;
            // if (Driver.Verbose)
            //    Console.WriteLine("Writing out type: " + fullname);
            if (fullname.StartsWith(
                    "System.Collections.Generic.Dictionary"))
            {
            }

            var myUsingDirective     = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(mynamespace));
            var SystemUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System"));
            // Required as certain functions like boxing are in this namespace
            var namespaces      = typeSymbols.First().Syntax.Parent.DescendantNodes().OfType <UsingDirectiveSyntax>().ToArray();
            var usingStatements = typeSymbols.First().Syntax.Parent.DescendantNodes().OfType <UsingStatementSyntax>().ToArray();
            var allTypeAliases  = typeSymbols.First().Syntax.DescendantNodes().OfType <QualifiedNameSyntax>().ToArray();

            Context.Instance.UsingDeclarations = namespaces
                                                 .Union(new[]
            {
                myUsingDirective, SystemUsingDirective
            }).ToArray();



            TypeProcessor.AddAlias(Context.Instance.Type.ContainingNamespace as INamespaceSymbol, Context.Instance.Type.ContainingNamespace.GetModuleName());


            foreach (var ns in namespaces)
            {
                //TODO: Add support for type aliases ...
                var symbol = TypeProcessor.GetSymbolInfo(ns.Name).Symbol;
                if (allTypeAliases.All(o => TypeProcessor.GetSymbolInfo(o.Left).Symbol != symbol))
                {
                    TypeProcessor.AddAlias(symbol as INamespaceSymbol, (symbol as INamespaceSymbol).GetModuleName());
                }
            }

            var aliases = allTypeAliases.DistinctBy(j => TypeProcessor.GetSymbolInfo(j.Left));

            foreach (var alias in aliases)
            {
                var left = alias.Left;
                var type = TypeProcessor.GetSymbolInfo(left).Symbol as INamespaceSymbol;
                var name = left.ToString();
                if (type != null && type.ToString() != name)
                {
                    TypeProcessor.AddAlias(type, name);
                }
            }
            OutputWriter writer = null;

            using (
                writer =
                    parentModuleWriter == null
                        ? new OutputWriter(Context.Instance.Namespace, Context.Instance.TypeName)
                        : new TempWriter())
            {
                writer.FileExists = fileExists;

                if (parentModuleWriter != null)
                {
                    writer.WriteLine();
                    writer.Indent = parentModuleWriter.Indent + 2;
                    writer.WriteIndent();
                }

                var bases    = new List <ITypeSymbol>();
                var baselist = typeSymbols.Select(k => k.Syntax.As <BaseTypeDeclarationSyntax>()).Select(o => o.BaseList).Where(k => k != null).ToArray();

                if (baselist.Any())
                {
                    bases = baselist.SelectMany(k => k.Types)
                            .Select(o => TypeProcessor.GetTypeInfo(o.Type).ConvertedType ?? TypeProcessor.GetTypeInfo(o.Type).Type)
                            .Where(k => k != null)
                            .Distinct()
                            .ToList();
                }

                //                var interfaces = bases.Where(o => o.TypeKind == TypeKind.Interface).ToList();

                if (Context.Instance.Type != Context.Object)
                {
                    if (bases != null && (!bases.Any((j => j.TypeKind != TypeKind.Interface)) &&
                                          !(typeSymbols.First().Symbol.TypeKind == TypeKind.Interface || typeSymbols.First().Symbol.TypeKind == TypeKind.Struct)))
                    {
                        //TODO: fix structs using mixins / alias this
                        bases.Add(Context.Object);
                    }
                }
                if (bases == null)
                {
                    bases = new List <ITypeSymbol>();
                }

                foreach (var type in bases)
                {
                    TypeProcessor.AddUsedType(type);
                }

                //TODO: Fix enum support
                if (typeSymbols.First().Syntax is EnumDeclarationSyntax)
                {
                    WriteEnum.Go(writer,
                                 Context.Instance.Partials.Select(o => o.Syntax)
                                 .Cast <EnumDeclarationSyntax>()
                                 .SelectMany(o => o.Members)
                                 .Where(o => !Program.DoNotWrite.ContainsKey(o)));

                    if (parentModuleWriter != null)
                    {
                        parentModuleWriter.Write(writer.ToString());
                    }

                    return;
                }

                Context.Instance.AllMembers =
                    typeSymbols.Select(k => k.Syntax.As <TypeDeclarationSyntax>()).SelectMany(o => o.Members)
                    .Where(o => !Program.DoNotWrite.ContainsKey(o))
                    .ToList();

                var allMembersToWrite = Context.Instance.AllMembers
                                        .Where(member => !(member is TypeDeclarationSyntax) &&
                                               !(member is EnumDeclarationSyntax) &&
                                               !(member is DelegateDeclarationSyntax) &&
                                               !(member is ConstructorDeclarationSyntax))
                                        .ToList();

                Context.Instance.MemberNames = allMembersToWrite.Select(k => k.GetCSharpName()).ToList();
                if (Context.Instance.Type.ContainingType != null)
                {
                    Context.Instance.MemberNames.AddRange(Context.Instance.Type.ContainingType.MemberNames);
                }


                {
                    //                    WriteStandardIncludes.Go(writer);

                    //                    writer.WriteLine(String.Format("#include \"{0}\"", TypeState.Instance.TypeName + ".h"));



                    WriteBcl.Go(writer);

                    //TypeState.Instance.DerivesFromObject = bases.Count == interfaces.Count;

                    var @namespace  = typeSymbols.First().Symbol.ContainingNamespace.FullName();
                    var genericArgs = Context.Instance.Type.TypeParameters.Select(l => l as ITypeSymbol).ToList();

                    //Module name = namespace + "." + typename;

                    WriteStandardIncludes.Go(writer);

                    //                    var namespaces = @namespace.Split(new string[] { "." }, StringSplitOptions.None);
                    //
                    //                    if (@namespace.Length > 0)
                    //                    {
                    //                        foreach (var ns in namespaces)
                    //                        {
                    //                            writer.WriteLine("namespace " + ns + "\r\n{");
                    //                            writer.WriteLine("namespace " + ns + "\r\n{");
                    //                        }
                    //
                    //                    }

                    var instanceCtors = Context.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>()
                                        .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword))
                                        .ToList();

                    var staticCtors = Context.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>()
                                      .Where(o => (o.Modifiers.Any(SyntaxKind.StaticKeyword)))
                                      .ToList();

                    //TODO: Add support for overloading constructing
                    //                    if (instanceCtors.Count > 1)
                    //                        throw new Exception(
                    //                            "Overloaded constructors are not supported.  Consider changing all but one to static Create methods " +
                    //                            Utility.Descriptor(first.Syntax));

                    //                    var ctorOpt = instanceCtors.SingleOrDefault();
                    //TODO: Handle interfaces by

                    /*
                     * class Interface
                     * {
                     * public:
                     *  virtual ~Interface() { }
                     *  virtual void test() = 0; // Functions, must all be virtual
                     * }
                     */

                    var membersToWrite = allMembersToWrite.ToList();
                    //.Where(o => IsStatic(o) == staticMembers).ToList();

                    //                    if (membersToWrite.Count == 0 && (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.StaticKeyword))))
                    //                        continue;

                    //                    if (staticMembers)
                    //                        writer.Write("object ");
                    //                    else if (first.Syntax.Kind == SyntaxKind.InterfaceDeclaration)
                    //                        writer.Write("trait ");
                    //                    else
                    //                    {
                    //                        if (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.AbstractKeyword)))
                    //                            writer.Write("abstract ");

                    //                    }

                    // writer.Write(TypeState.Instance.TypeName);

                    if (typeSymbols.First().Syntax is TypeDeclarationSyntax)
                    {
                        //Internal classes/structs are declared static in D to behave correctly
                        if (parentModuleWriter != null)
                        {
                            writer.Write("static ");
                        }
                        if (Context.Instance.Type.TypeKind == TypeKind.Class)
                        {
                            writer.Write("class ");
                        }
                        else if (Context.Instance.Type.TypeKind == TypeKind.Interface)
                        {
                            writer.Write("interface ");
                        }
                        else if (Context.Instance.Type.TypeKind == TypeKind.Struct)
                        {
                            writer.Write("struct ");
                            //						writer.Write (" class "); // Allows inheritance ... but too many issues, will look at this when it gets relevant
                        }
                        else
                        {
                            throw new Exception("don't know how to write type: " + Context.Instance.Type.TypeKind);
                        }
                        List <ITypeSymbol> parentTypeParameters;
                        if (Context.Instance.Type.ContainingType != null)
                        {
                            parentTypeParameters = GetParentTypeParameters(Context.Instance.Type);
                        }
                        else
                        {
                            parentTypeParameters = new List <ITypeSymbol>();
                        }

                        writer.Write(TypeName(Context.Instance.Type, false));
                        //TypeProcessor.ConvertType(Context.Instance.Type, true, false,true));

                        if (Context.Instance.Type.IsGenericType)
                        {
                            {
                                foreach (var @base in bases)
                                {
                                    var namedTypeSymbol = @base as INamedTypeSymbol;
                                    if (namedTypeSymbol != null)
                                    {
                                        foreach (var arg in namedTypeSymbol.TypeArguments)
                                        {
                                            if (arg.TypeKind == TypeKind.TypeParameter && !parentTypeParameters.Contains(arg))
                                            {
                                                if (!genericArgs.Any(k => k.Name == arg.Name))
                                                {
                                                    genericArgs.Add(arg);
                                                }
                                            }
                                        }
                                    }
                                }
                                if (genericArgs.Any())
                                {
                                    writer.Write("(" +
                                                 string.Join(" , ",
                                                             genericArgs.Select(o => TypeProcessor.ConvertType(o, true, true, false))) + ")");
                                }
                            }
                        }

                        bool firstBase = true;

                        if (Context.Instance.Type.TypeKind != TypeKind.Struct)
                        {
                            foreach (var baseType in bases.OrderBy(o => o.TypeKind == TypeKind.Interface ? 1 : 0))
                            {
                                var convertType = TypeProcessor.ConvertType(baseType);

                                writer.Write(firstBase ? " : " : " ,");

                                writer.Write(convertType);

                                firstBase = false;
                            }
                        }

                        string constraints = GetTypeConstraints((TypeDeclarationSyntax)typeSymbols.First().Syntax);
                        writer.Write(constraints);
                    }

                    writer.WriteLine();

                    writer.OpenBrace();

                    var nonFields = WriteFields(membersToWrite, typeSymbols.First(), writer);

                    foreach (var member in nonFields)
                    {
                        //                    writer.WriteLine();
                        Core.Write(writer, member);
                    }

                    WriteConstructors(instanceCtors, writer);

                    WriteStaticConstructors(staticCtors, writer);

                    //PInvoke is now centralized, so we can call it on all libraries etc without issue

                    writer.Indent--;
                    WriteOutNestedTypes(typeSymbols.First(), writer);

                    var methodSymbols = membersToWrite.OfType <MethodDeclarationSyntax>().Select(TypeProcessor.GetDeclaredSymbol);
                    //TypeProcessor.GetDeclaredSymbol(method);

                    if (!methodSymbols.OfType <IMethodSymbol>()
                        .Any(k => k.Name == "ToString" && k.Parameters.Length == 0 && k.ReturnType == Context.String))
                    {
                        if (Context.Instance.Type.TypeKind == TypeKind.Struct ||
                            (Context.Instance.Type.TypeKind == TypeKind.Class))
                        {
                            var overrideS = Context.Instance.Type.TypeKind == TypeKind.Struct ? "" : "override ";
                            writer.WriteLine();
                            writer.WriteLine("public " + overrideS + "String ToString()");
                            writer.OpenBrace();
                            writer.WriteLine("return GetType().FullName;");//Better names based on specialization
                            writer.CloseBrace();
                        }
                    }

                    WriteOutBoxed(writer, genericArgs, bases);
                }

                if (Context.Instance.Type.TypeKind == TypeKind.Struct)
                {
                    writer.WriteLine();
                    writer.WriteLine("public __Boxed_ __Get_Boxed()");
                    writer.OpenBrace();
                    writer.WriteLine("return new __Boxed_(this);");
                    writer.CloseBrace();
                    writer.WriteLine("alias __Get_Boxed this;");
                }

                if (Context.Instance.Type.TypeKind != TypeKind.Interface)
                {
                    writer.WriteLine();
                    if (Context.Instance.Type.TypeKind == TypeKind.Class)
                    {
                        writer.WriteLine("public override Type GetType()");
                    }
                    //					else if (Context.Instance.Type.TypeKind == TypeKind.Interface) // Messes with GetType overrides of objects
                    //					{
                    //						writer.WriteLine ("public final Type GetType()");
                    //					}
                    else if (Context.Instance.Type.TypeKind == TypeKind.Struct)
                    {
                        writer.WriteLine("public Type GetType()");
                    }
                    writer.OpenBrace();
                    //if (Context.Instance.Type.TypeKind == TypeKind.Class)
                    writer.WriteLine("return __TypeOf!(typeof(this));");
                    // else
                    //     writer.WriteLine("return __TypeOf!(__Boxed_);");

                    writer.CloseBrace();
                }

                writer.CloseBrace();

                WriteEntryMethod(writer);

                if (parentModuleWriter != null)
                {
                    writer.Finalize();
                    parentModuleWriter.Write(writer.ToString());
                }
            }
        }