diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index e3a09bf1..a9fba9da 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -282,6 +282,7 @@ namespace CppSharp if (Options.GenerateInlines) TranslationUnitPasses.AddPass(new GenerateInlinesCodePass()); TranslationUnitPasses.AddPass(new TrimSpecializationsPass()); + TranslationUnitPasses.AddPass(new MoveNestedTemplateInternalsPass()); TranslationUnitPasses.AddPass(new GenerateTemplatesCodePass()); } diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index e0d48e4b..9c3bb5ae 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -348,7 +348,10 @@ namespace CppSharp.Generators.CSharp return; PushBlock(CSharpBlockKind.Namespace); - WriteLine("namespace {0}", classTemplate.Name); + WriteLine("namespace {0}{1}", + classTemplate.OriginalNamespace is Class ? + classTemplate.OriginalNamespace.Name + '_' : string.Empty, + classTemplate.Name); WriteStartBraceIndent(); foreach (var specialization in specializations) diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 39a3e9c1..55988016 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -388,7 +388,7 @@ namespace CppSharp.Generators.CSharp return GetNestedQualifiedName(decl); var specialization = template.GetClassTemplateSpecialization(); return string.Format("{0}.Internal{1}", - GetNestedQualifiedName(specialization.TemplatedDecl.Namespace, specialization), + GetNestedQualifiedName(specialization), Helpers.GetSuffixForInternal(specialization, this)); } @@ -611,21 +611,30 @@ namespace CppSharp.Generators.CSharp return GetNestedQualifiedName(@enum); } - public string GetNestedQualifiedName(ClassTemplateSpecialization decl) + public string GetNestedQualifiedName(Declaration decl) { - return GetNestedQualifiedName(decl.Namespace, decl); - } - - private string GetNestedQualifiedName(Declaration decl) - { - return GetNestedQualifiedName(decl.Namespace, decl); - } + var names = new List(); - private string GetNestedQualifiedName(Declaration @namespace, Declaration decl) - { - var names = new List { decl.Name }; - - var ctx = @namespace; + Declaration ctx; + var specialization = decl as ClassTemplateSpecialization; + if (specialization != null) + { + ctx = specialization.TemplatedDecl.Namespace; + if (specialization.OriginalNamespace is Class) + { + names.Add(string.Format("{0}_{1}", decl.OriginalNamespace.Name, decl.Name)); + ctx = ctx.Namespace; + } + else + { + names.Add(decl.Name); + } + } + else + { + names.Add(decl.Name); + ctx = decl.Namespace; + } while (ctx != null) { if (!string.IsNullOrWhiteSpace(ctx.Name)) diff --git a/src/Generator/Passes/MoveNestedTemplateInternalsPass.cs b/src/Generator/Passes/MoveNestedTemplateInternalsPass.cs new file mode 100644 index 00000000..38342a77 --- /dev/null +++ b/src/Generator/Passes/MoveNestedTemplateInternalsPass.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; + +namespace CppSharp.Passes +{ + public class MoveNestedTemplateInternalsPass : TranslationUnitPass + { + public MoveNestedTemplateInternalsPass() + { + Options.VisitClassBases = false; + Options.VisitClassFields = false; + Options.VisitClassMethods = false; + Options.VisitClassProperties = false; + Options.VisitFunctionParameters = false; + Options.VisitFunctionReturnType = false; + Options.VisitNamespaceEnums = false; + Options.VisitNamespaceEvents = false; + Options.VisitNamespaceTypedefs = false; + Options.VisitNamespaceVariables = false; + Options.VisitTemplateArguments = false; + } + + public override bool VisitLibrary(ASTContext context) + { + var result = base.VisitLibrary(context); + foreach (var entry in movedClassTemplates) + { + foreach (var template in entry.Value) + { + foreach (var decl in new[] { template, template.TemplatedDecl }) + { + int index = entry.Key.Declarations.IndexOf(decl.Namespace); + decl.Namespace.Declarations.Remove(decl); + decl.Namespace = entry.Key; + entry.Key.Declarations.Insert(index, decl); + } + } + } + return result; + } + + public override bool VisitClassTemplateDecl(ClassTemplate template) + { + if (!base.VisitClassTemplateDecl(template) || + template.Specializations.Count == 0 || + template.Specializations.All(s => s is ClassTemplatePartialSpecialization)) + return false; + + var @class = template.TemplatedDecl.Namespace as Class; + if (@class == null || @class is ClassTemplateSpecialization || + @class.Namespace is Class) + return false; + + if (movedClassTemplates.ContainsKey(@class.Namespace)) + movedClassTemplates[@class.Namespace].Add(template); + else + movedClassTemplates.Add(@class.Namespace, new List { template }); + + return true; + } + + private Dictionary> movedClassTemplates = + new Dictionary>(); + } +} diff --git a/tests/CSharp/CSharpTemplates.h b/tests/CSharp/CSharpTemplates.h index bceff8a4..8dc8c4fc 100644 --- a/tests/CSharp/CSharpTemplates.h +++ b/tests/CSharp/CSharpTemplates.h @@ -50,6 +50,10 @@ class DLL_API TemplateSpecializer { public: TemplateSpecializer(); + template + class NestedTemplate + { + }; private: IndependentFields independentFields; DependentValueFields dependentValueFields; @@ -59,6 +63,7 @@ private: DependentValueFields dependentPointerFieldsT2; DependentValueFields> specializeWithSpecialization; DependentValueFields> specializeWithSameSpecialization; + NestedTemplate nestedTemplate; void completeSpecializationInParameter(DependentValueFields p1, DependentValueFields p2, DependentValueFields p3);