private static void WriteOneDelegate(OutputWriter outputWriter, Context.DelegateSyntaxAndSymbol first, bool fileExists) { Context.Instance.Namespace = first.Symbol.ContainingNamespace.FullName(); Context.Instance.Type = first.Symbol; TypeProcessor.ClearUsedTypes(); var mynamespace = Context.Instance.Type.ContainingNamespace.FullName().RemoveFromEndOfString(".Namespace"); // + "." + TypeState.Instance.TypeName; var myUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(mynamespace)); var SystemUsingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")); // Required as certain functions like boxing are in this namespace Context.Instance.UsingDeclarations = first.Syntax.Parent.DescendantNodes().OfType<UsingDirectiveSyntax>().ToArray() .Union(new[] { myUsingDirective, SystemUsingDirective }).ToArray(); OutputWriter writer = null; using ( writer = outputWriter == null ? new OutputWriter(Context.Instance.Namespace, Context.Instance.TypeName) : new TempWriter()) { if (outputWriter != null) { writer.WriteLine(); writer.Indent = outputWriter.Indent + 2; writer.WriteIndent(); } writer.FileExists = fileExists; WriteBcl.Go(writer); WriteStandardIncludes.Go(writer); //Look for generic arguments { List<TypeParameterSyntax> genericArgs = new List<TypeParameterSyntax>(); if (first.Syntax.TypeParameterList != null) genericArgs = first.Syntax.TypeParameterList.Parameters.ToList(); var name = WriteType.TypeName(Context.Instance.Type, false); //Context.Instance.TypeName; if (genericArgs.Count > 0) { name = "template " + name; name += ("("); name += (string.Join(" , ", genericArgs.Select(o => o))); name += (")"); writer.WriteLine(name); writer.OpenBrace(); writer.WriteLine("alias __Delegate!(" + TypeProcessor.ConvertType(first.Syntax.ReturnType) + " delegate" + WriteMethod.GetParameterListAsString(first.Syntax.ParameterList.Parameters) + ") " + WriteType.TypeName(Context.Instance.Type, false) + ";"); writer.CloseBrace(); } else { //Non-generic writer.WriteLine("alias __Delegate!(" + TypeProcessor.ConvertType(first.Syntax.ReturnType) + " delegate" + WriteMethod.GetParameterListAsString(first.Syntax.ParameterList.Parameters) + ") " + WriteType.TypeName(Context.Instance.Type, false) + ";"); } } if (outputWriter != null) outputWriter.WriteLine(writer.ToString()); } }
public static void Update(Compilation compilation) { Instance = new Context(); if (compilation != null) Instance.UpdateContext(compilation); }
internal static void Pop() { Instance = Instances.Pop(); }
private static void WriteOutNestedTypes(Context.SyntaxAndSymbol first, OutputWriter writer) { //WriteOut All My nested classes Context.Push(); var delegates = first.Syntax.DescendantNodes().OfType<DelegateDeclarationSyntax>() .Select(o => new { Syntax = o, Symbol = TypeProcessor.GetDeclaredSymbol(o), TypeName = WriteType.TypeName((INamedTypeSymbol)TypeProcessor.GetDeclaredSymbol(o)) }).Where(k => k.Symbol.ContainingType == Context.Instance.Type) // Ignore all nested delegates .GroupBy(o => o.Symbol.ContainingNamespace.FullNameWithDot() + o.TypeName) .ToList(); delegates.ForEach(type => //.ForEach(type => //.Parallel(type => { Context.Instance = new Context { TypeName = type.First().TypeName, DelegatePartials = type.Select( o => new Context.DelegateSyntaxAndSymbol { Symbol = (INamedTypeSymbol)o.Symbol, Syntax = o.Syntax }) .Where(o => !Program.DoNotWrite.ContainsKey(o.Syntax)) .ToList() }; if (Context.Instance.DelegatePartials.Count > 0) WriteDelegate.Go(writer); }); Context.Pop(); Context.Push(); var subclasses = first.Syntax.DescendantNodes().OfType<BaseTypeDeclarationSyntax>() .Select(o => new { Syntax = o, Symbol = TypeProcessor.GetDeclaredSymbol(o), TypeName = WriteType.TypeName((INamedTypeSymbol)TypeProcessor.GetDeclaredSymbol(o)) }).Where(k => k.Symbol.ContainingType == Context.Instance.Type) // Ignore all nested classes .GroupBy(o => o.Symbol.ContainingNamespace.FullNameWithDot() + o.TypeName) .ToList(); subclasses.ForEach(type => //.ForEach(type => //.Parallel(type => { Context.Instance = new Context { TypeName = type.First().TypeName, Partials = type.Select( o => new Context.SyntaxAndSymbol { Symbol = (INamedTypeSymbol)o.Symbol, Syntax = o.Syntax }) .Where(o => !Program.DoNotWrite.ContainsKey(o.Syntax)) .ToList() }; if (Context.Instance.Partials.Count > 0) { try { WriteType.Go(writer); } catch (Exception ex) { //TODO: remove this when done with CorLib throw ex; } } }); Context.Pop(); }
private static IEnumerable<MemberDeclarationSyntax> WriteFields(List<MemberDeclarationSyntax> membersToWrite, Context.SyntaxAndSymbol first, OutputWriter writer) { var fields = membersToWrite.OfType<FieldDeclarationSyntax>().ToList(); var nonFields = membersToWrite.Except(fields); // also static fields should be separately dealt with //Not needed anymore ... reflection takes care of this //if (fields.Count > 0 && fields.Any(j => j.GetModifiers().Any(SyntaxKind.ConstKeyword) || // j.GetModifiers().Any(SyntaxKind.StaticKeyword))) //{ // writer.WriteLine("enum __staticFieldTuple = __Tuple!(" + // fields.Where( // j => // j.GetModifiers().Any(SyntaxKind.ConstKeyword) || // j.GetModifiers().Any(SyntaxKind.StaticKeyword)) // .Select( // k => // "\"" + // WriteIdentifierName.TransformIdentifier( // k.Declaration.Variables[0].Identifier.ValueText) + "\"") // .Aggregate((i, j) => i + "," + j) + ");//Reflection Support"); //} var structLayout = first.Syntax.GetAttribute(Context.StructLayout); if (structLayout != null) { LayoutKind value = LayoutKind.Auto; if ( structLayout.ArgumentList.Arguments.Any( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Value")) { value = (LayoutKind) Enum.Parse(typeof(LayoutKind), structLayout.ArgumentList.Arguments.FirstOrDefault( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Value") .Expression.ToFullString() .SubstringAfterLast('.')); } else if (structLayout.ArgumentList.Arguments.Count > 0 && structLayout.ArgumentList.Arguments[0].NameEquals == null) { value = (LayoutKind) Enum.Parse(typeof(LayoutKind), structLayout.ArgumentList.Arguments[0].Expression.ToFullString() .SubstringAfterLast('.')); } int pack = -1; int size = -1; CharSet charset = CharSet.Auto; // if (structLayout.ArgumentList.Arguments.Count > 1) { try { if ( structLayout.ArgumentList.Arguments.Any( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "CharSet")) { charset = (CharSet) Enum.Parse(typeof(CharSet), structLayout.ArgumentList.Arguments.FirstOrDefault( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "CharSet") .Expression.ToFullString() .SubstringAfterLast('.')); //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value"); } //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value"); else if (structLayout.ArgumentList.Arguments.Count > 1 && structLayout.ArgumentList.Arguments[1].NameEquals == null) { charset = (CharSet) Enum.Parse(typeof(CharSet), structLayout.ArgumentList.Arguments[1].Expression.ToFullString() .SubstringAfterLast('.')); } } catch (Exception ex) { } try { if ( structLayout.ArgumentList.Arguments.Any( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Pack")) { pack = int.Parse( structLayout.ArgumentList.Arguments.FirstOrDefault( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Pack") .Expression.ToFullString()); } //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value"); else if (structLayout.ArgumentList.Arguments.Count > 2 && structLayout.ArgumentList.Arguments[2].NameEquals == null) pack = int.Parse(structLayout.ArgumentList.Arguments[2].Expression.ToFullString()); } catch (Exception ex) { } try { if ( structLayout.ArgumentList.Arguments.Any( k => k.NameEquals != null && k.NameEquals.Name.ToFullString().Trim() == "Size")) { size = int.Parse( structLayout.ArgumentList.Arguments.FirstOrDefault( k => k.NameColon != null && k.NameColon.ToFullString().Trim() == "Size") .Expression.ToFullString()); } //structLayout.ArgumentList.Arguments.Where (k => k.Expression is MemberAccessExpressionSyntax).FirstOrDefault(k=>(k.Expression as MemberAccessExpressionSyntax).Name.ToFullString() == "Value"); else if (structLayout.ArgumentList.Arguments.Count > 3 && structLayout.ArgumentList.Arguments[3].NameEquals == null) size = int.Parse(structLayout.ArgumentList.Arguments[3].Expression.ToFullString()); } catch (Exception ex) { } // size = int.Parse (structLayout.ArgumentList.Arguments [3].Expression.ToFullString ()); } // var pack = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "Pack"); // var charset = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "CharSet"); // var size = structLayout.ArgumentList.Arguments.FirstOrDefault (k => k.NameColon.Name.ToFullString() == "Size"); if (value == LayoutKind.Explicit) { var fieldGroups = fields.GroupBy(f => f.GetAttribute(Context.FieldOffset).ArgumentList.Arguments[0].ToString()) .OrderBy(k => k.Key); writer.Indent++; foreach (var group in fieldGroups) { writer.WriteLine("//FieldOffset(" + @group.Key + ")"); writer.WriteLine("union {"); foreach (var member in @group) Core.Write(writer, member); writer.WriteLine("}"); } // foreach (var member in fields) // { // // writer.WriteLine(); // Core.Write (writer, member); // } } else if (value == LayoutKind.Sequential) { fields = SortFields(fields); writer.Indent++; foreach (var member in fields) { if (pack != -1) writer.WriteLine("align (" + pack + "): //Pack = " + pack); // writer.WriteLine(); Core.Write(writer, member); } } else { //Looks like C# aligns to 1 by default ... don't know about D... fields = SortFields(fields); writer.Indent++; foreach (var member in fields) { pack = 1; //TODO: on mac osx and mono this is required, on windows, it causes and issue // writer.WriteLine("align (" + pack + "): //Pack = " + pack + " C# default"); // writer.WriteLine(); Core.Write(writer, member); } } } else { //Looks like C# aligns to 1 by default ... don't know about D... fields = SortFields(fields); writer.Indent++; foreach (var member in fields) { var pack = 1; //TODO: on mac osx and mono this is required, on windows, it causes an issue (sizes are different) // writer.WriteLine("align (" + pack + "): //Pack = " + pack + "C# default"); // writer.WriteLine(); Core.Write(writer, member); } } return nonFields; }
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()); } } }