From 3693d991afe2418e01c5acd8c072507de4228a1b Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Fri, 30 Jan 2015 14:06:54 +0200 Subject: [PATCH 1/5] Implement further tests for namespaces --- tests/NamespacesBase/NamespacesBase.cpp | 2 +- tests/NamespacesBase/NamespacesBase.h | 21 +++++++++++++++++++ tests/NamespacesDerived/NamespacesDerived.cpp | 8 ++++++- tests/NamespacesDerived/NamespacesDerived.h | 20 ++++++++++++++++-- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/tests/NamespacesBase/NamespacesBase.cpp b/tests/NamespacesBase/NamespacesBase.cpp index 07685d46..a91800f2 100644 --- a/tests/NamespacesBase/NamespacesBase.cpp +++ b/tests/NamespacesBase/NamespacesBase.cpp @@ -10,4 +10,4 @@ Base::Base(int i) Base::Base() { -} \ No newline at end of file +} diff --git a/tests/NamespacesBase/NamespacesBase.h b/tests/NamespacesBase/NamespacesBase.h index b431de6c..5459d8d3 100644 --- a/tests/NamespacesBase/NamespacesBase.h +++ b/tests/NamespacesBase/NamespacesBase.h @@ -1,5 +1,26 @@ #include "../Tests.h" + +namespace OverlappingNamespace +{ + enum Colors { + white, + black, + red, + blue, + green, + }; + + class InBaseLib + { + public: + InBaseLib() + { + + }; + }; +} + class DLL_API Base { public: diff --git a/tests/NamespacesDerived/NamespacesDerived.cpp b/tests/NamespacesDerived/NamespacesDerived.cpp index 4bb67564..209262cb 100644 --- a/tests/NamespacesDerived/NamespacesDerived.cpp +++ b/tests/NamespacesDerived/NamespacesDerived.cpp @@ -1,6 +1,12 @@ #include "NamespacesDerived.h" -Derived::Derived() : Base(10), component(5) +Derived::Derived() : Base(10), baseComponent(5), nestedNSComponent(), color(OverlappingNamespace::blue) { } + + +OverlappingNamespace::InDerivedLib::InDerivedLib() : parentNSComponent(), color(black) +{ + +} diff --git a/tests/NamespacesDerived/NamespacesDerived.h b/tests/NamespacesDerived/NamespacesDerived.h index 091fb7c4..13f0d96f 100644 --- a/tests/NamespacesDerived/NamespacesDerived.h +++ b/tests/NamespacesDerived/NamespacesDerived.h @@ -1,13 +1,29 @@ #include "../Tests.h" #include "../NamespacesBase/NamespacesBase.h" +namespace OverlappingNamespace +{ + + class InDerivedLib + { + public: + InDerivedLib(); + Base parentNSComponent; + Colors color; + }; +} + class DLL_API Derived : public Base { public: Derived(); - Base component; + Base baseComponent; + + OverlappingNamespace::InBaseLib nestedNSComponent; + + OverlappingNamespace::Colors color; private: int d; -}; \ No newline at end of file +}; From c6c9bc4c2faa19aecf620ed54140f46e57b0b783 Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Wed, 4 Feb 2015 20:51:39 +0200 Subject: [PATCH 2/5] Improved premake scripts for tests. --- build/Tests.lua | 17 +++++++++++------ tests/NamespacesDerived/premake4.lua | 6 +++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/build/Tests.lua b/build/Tests.lua index ac5ace34..b403a7bf 100644 --- a/build/Tests.lua +++ b/build/Tests.lua @@ -38,7 +38,7 @@ function SetupManagedTestProject() SetupManagedProject() end -function SetupTestGeneratorProject(name) +function SetupTestGeneratorProject(name, depends) project(name .. ".Gen") SetupManagedTestProject() kind "ConsoleApp" @@ -47,14 +47,19 @@ function SetupTestGeneratorProject(name) dependson { name .. ".Native" } - links - { + linktable = { "System.Core", "CppSharp.AST", "CppSharp.Generator", - "CppSharp.Generator.Tests" + "CppSharp.Generator.Tests", } + if depends ~= nil then + table.insert(linktable, depends .. ".Gen") + end + + links(linktable) + SetupParser() end @@ -84,7 +89,7 @@ function SetupTestNativeProject(name, depends) files { "**.h", "**.cpp" } if depends ~= nil then - links { depends } + links { depends .. ".Native" } end end @@ -117,7 +122,7 @@ function SetupTestProjectsCSharp(name, depends) linktable = { "CppSharp.Runtime" } if depends ~= nil then - table.insert(linktable, depends) + table.insert(linktable, depends .. ".CSharp") end links(linktable) diff --git a/tests/NamespacesDerived/premake4.lua b/tests/NamespacesDerived/premake4.lua index 0056d5f6..ad98cb93 100644 --- a/tests/NamespacesDerived/premake4.lua +++ b/tests/NamespacesDerived/premake4.lua @@ -1,4 +1,4 @@ group "Tests/Namespaces" - SetupTestGeneratorProject("NamespacesDerived") - SetupTestNativeProject("NamespacesDerived", "NamespacesBase.Native") - SetupTestProjectsCSharp("NamespacesDerived", "NamespacesBase.CSharp") \ No newline at end of file + SetupTestGeneratorProject("NamespacesDerived", "NamespacesBase") + SetupTestNativeProject("NamespacesDerived", "NamespacesBase") + SetupTestProjectsCSharp("NamespacesDerived", "NamespacesBase") \ No newline at end of file From 8a85058c4813ce15d10e4071b23ee67ab9afd4cd Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Thu, 27 Nov 2014 20:32:32 +0200 Subject: [PATCH 3/5] Implemented name importing & exporting. --- src/Generator/Driver.cs | 14 +++++++ .../Generators/CSharp/CSharpTextTemplate.cs | 2 +- .../Generators/CSharp/CSharpTypePrinter.cs | 3 -- src/Generator/Passes/RenameRootNamespaces.cs | 37 +++++++++++++++++++ tests/NamespacesBase/NamespacesBase.cs | 2 - tests/NamespacesDerived/NamespacesDerived.cs | 2 +- 6 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 src/Generator/Passes/RenameRootNamespaces.cs diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index c015f2e6..1bd72493 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -32,6 +32,18 @@ namespace CppSharp public ASTContext ASTContext { get; private set; } public SymbolContext Symbols { get; private set; } + public struct TranslationUnitRenameInfo + { + public string translationUnit; + public string rootNamespaceName; + } + public static Dictionary RootNamespaceRenames { get; private set; } + + static Driver() + { + Driver.RootNamespaceRenames = new Dictionary(); + } + public Driver(DriverOptions options, IDiagnosticConsumer diagnostics) { Options = options; @@ -279,6 +291,8 @@ namespace CppSharp if (Options.GeneratePropertiesAdvanced) TranslationUnitPasses.AddPass(new GetterSetterToPropertyAdvancedPass()); + + TranslationUnitPasses.AddPass(new RenameRootNamespacesPass()); } public void ProcessCode() diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index b8a52db0..c2bfde18 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1781,7 +1781,7 @@ namespace CppSharp.Generators.CSharp var hasBaseClass = @class.HasBaseClass && @class.BaseClass.IsRefType; if (hasBaseClass) WriteLineIndent(": base(({0}.Internal*) native{1})", - @class.BaseClass.Name, @class.IsAbstractImpl ? ", true" : string.Empty); + QualifiedIdentifier(@class.BaseClass), @class.IsAbstractImpl ? ", true" : string.Empty); WriteStartBraceIndent(); diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index b3a85263..7897768d 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -551,9 +551,6 @@ namespace CppSharp.Generators.CSharp var ctx = decl.Namespace; while (ctx != null) { - if (ctx is TranslationUnit) - break; - if (!string.IsNullOrWhiteSpace(ctx.Name)) names.Add(ctx.Name); diff --git a/src/Generator/Passes/RenameRootNamespaces.cs b/src/Generator/Passes/RenameRootNamespaces.cs new file mode 100644 index 00000000..e9fdc743 --- /dev/null +++ b/src/Generator/Passes/RenameRootNamespaces.cs @@ -0,0 +1,37 @@ +using CppSharp.AST; +using System; +using System.Collections.Generic; + +namespace CppSharp.Passes +{ + // This pass visits all the translation units and checks if they originate from library being processed or + // from some other library that is being depended upon. It will rename the root namespaces of all the "foreign" + // libraries so that there wouldn't be clashes and so that the code generation phase would be able to generate + // names with fully qualified namespace prefixes. + public class RenameRootNamespacesPass : TranslationUnitPass + { + + public override bool VisitTranslationUnit(TranslationUnit unit) + { + if (!base.VisitTranslationUnit(unit)) + return false; + + + var fileName = unit.TranslationUnit.FileName; + if (Driver.RootNamespaceRenames.ContainsKey(fileName)) + { + unit.Name = Driver.RootNamespaceRenames[fileName].rootNamespaceName; + } + else if (unit.GenerationKind == GenerationKind.Generate) + { + Driver.RootNamespaceRenames.Add(fileName, new Driver.TranslationUnitRenameInfo + { + translationUnit = fileName, + rootNamespaceName = Driver.Options.OutputNamespace, + }); + } + return true; + } + + } +} \ No newline at end of file diff --git a/tests/NamespacesBase/NamespacesBase.cs b/tests/NamespacesBase/NamespacesBase.cs index 871a4204..d274bb12 100644 --- a/tests/NamespacesBase/NamespacesBase.cs +++ b/tests/NamespacesBase/NamespacesBase.cs @@ -32,7 +32,5 @@ namespace CppSharp.Tests { ConsoleDriver.Run(new NamespacesBaseTests(GeneratorKind.CSharp)); } - } } - diff --git a/tests/NamespacesDerived/NamespacesDerived.cs b/tests/NamespacesDerived/NamespacesDerived.cs index c9f49ffe..8addbe3a 100644 --- a/tests/NamespacesDerived/NamespacesDerived.cs +++ b/tests/NamespacesDerived/NamespacesDerived.cs @@ -15,7 +15,6 @@ namespace CppSharp.Tests public override void SetupPasses(Driver driver) { - driver.Options.DependentNameSpaces.Add("NamespacesBase"); } public override void Preprocess(Driver driver, ASTContext ctx) @@ -39,6 +38,7 @@ namespace CppSharp.Tests public static void Main(string[] args) { + ConsoleDriver.Run(new NamespacesBaseTests(GeneratorKind.CSharp)); ConsoleDriver.Run(new NamespacesDerivedTests(GeneratorKind.CSharp)); } From 575088aeb67caddb1f644027a5456a16d9ac0a94 Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Fri, 6 Feb 2015 22:05:18 +0200 Subject: [PATCH 4/5] Extended namespaces tests to consider taking a parameter and returning a value of types declared in other libraries. Implemented QualifiedIdentifierIfNeeded(). --- .../Generators/CSharp/CSharpTextTemplate.cs | 45 +++++++++++++++-- tests/NamespacesBase/NamespacesBase.h | 6 ++- tests/NamespacesDerived/NamespacesDerived.cpp | 50 ++++++++++++++++++- tests/NamespacesDerived/NamespacesDerived.h | 35 ++++++++++++- 4 files changed, 127 insertions(+), 9 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index c2bfde18..3dd42d21 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -105,6 +105,43 @@ namespace CppSharp.Generators.CSharp #region Identifiers + // Takes a declaration (type, class etc.) that is referenced from a context, and the context. + // If the referenced name needs a qualification in the context, add it. Otherwise, return just the name. + public string QualifiedIdentifierIfNeeded(Declaration context, Declaration reference) + { + var refNames = new Stack(); + var ctxNames = new Stack(); + + var refCtx = reference; + while (refCtx != null) + { + if (!string.IsNullOrWhiteSpace(refCtx.Name)) + refNames.Push(refCtx.Name); + refCtx = refCtx.Namespace; + } + + var ctxCtx = context; + while (ctxCtx != null) + { + if (!string.IsNullOrWhiteSpace(ctxCtx.Name)) + ctxNames.Push(ctxCtx.Name); + ctxCtx = ctxCtx.Namespace; + } + + if (context.GenerationKind == GenerationKind.Generate && Options.GenerateLibraryNamespace) + ctxNames.Push(Options.OutputNamespace); + if (reference.GenerationKind == GenerationKind.Generate && Options.GenerateLibraryNamespace) + refNames.Push(Options.OutputNamespace); + + while (refNames.Count > 0 && ctxNames.Count > 0 &&refNames.Peek() == ctxNames.Peek()) + { + refNames.Pop(); + ctxNames.Pop(); + } + + return string.Join(".", refNames); + } + public string QualifiedIdentifier(Declaration decl) { var names = new List { decl.Name }; @@ -633,7 +670,7 @@ namespace CppSharp.Generators.CSharp bases.AddRange( from @base in @class.Bases where @base.IsClass - select QualifiedIdentifier(@base.Class)); + select QualifiedIdentifierIfNeeded(@class, @base.Class)); } if (@class.IsGenerated) @@ -1781,7 +1818,7 @@ namespace CppSharp.Generators.CSharp var hasBaseClass = @class.HasBaseClass && @class.BaseClass.IsRefType; if (hasBaseClass) WriteLineIndent(": base(({0}.Internal*) native{1})", - QualifiedIdentifier(@class.BaseClass), @class.IsAbstractImpl ? ", true" : string.Empty); + QualifiedIdentifierIfNeeded(@class, @class.BaseClass), @class.IsAbstractImpl ? ", true" : string.Empty); WriteStartBraceIndent(); @@ -1828,7 +1865,7 @@ namespace CppSharp.Generators.CSharp // Allocate memory for a new native object and call the ctor. WriteLine("var ret = Marshal.AllocHGlobal({0});", @class.Layout.Size); WriteLine("{0}.Internal.{1}(ret, new global::System.IntPtr(&native));", - QualifiedIdentifier(@class), GetFunctionNativeIdentifier(copyCtorMethod)); + QualifiedIdentifierIfNeeded(@class, @class), GetFunctionNativeIdentifier(copyCtorMethod)); WriteLine("return ({0}.Internal*) ret;", className); } else @@ -2243,7 +2280,7 @@ namespace CppSharp.Generators.CSharp if (construct == null) { WriteLine("var {0} = new {1}.Internal();", GeneratedIdentifier("ret"), - QualifiedIdentifier(retClass.OriginalClass ?? retClass)); + QualifiedIdentifierIfNeeded(function, retClass.OriginalClass ?? retClass)); } else { diff --git a/tests/NamespacesBase/NamespacesBase.h b/tests/NamespacesBase/NamespacesBase.h index 5459d8d3..0caa7020 100644 --- a/tests/NamespacesBase/NamespacesBase.h +++ b/tests/NamespacesBase/NamespacesBase.h @@ -3,7 +3,7 @@ namespace OverlappingNamespace { - enum Colors { + enum ColorsEnum { white, black, red, @@ -21,6 +21,8 @@ namespace OverlappingNamespace }; } + + class DLL_API Base { public: @@ -29,4 +31,4 @@ public: private: int b; -}; \ No newline at end of file +}; diff --git a/tests/NamespacesDerived/NamespacesDerived.cpp b/tests/NamespacesDerived/NamespacesDerived.cpp index 209262cb..88c00324 100644 --- a/tests/NamespacesDerived/NamespacesDerived.cpp +++ b/tests/NamespacesDerived/NamespacesDerived.cpp @@ -1,12 +1,60 @@ #include "NamespacesDerived.h" +OverlappingNamespace::InDerivedLib::InDerivedLib() : parentNSComponent(), color(black) +{ +} + Derived::Derived() : Base(10), baseComponent(5), nestedNSComponent(), color(OverlappingNamespace::blue) { } +Base Derived::getBase() +{ + return baseComponent; +} -OverlappingNamespace::InDerivedLib::InDerivedLib() : parentNSComponent(), color(black) +void Derived::setBase(Base b) +{ + baseComponent = b; +} + +OverlappingNamespace::InBaseLib Derived::getNestedNSComponent() +{ + return nestedNSComponent; +} + +void Derived::setNestedNSComponent(OverlappingNamespace::InBaseLib c) +{ + nestedNSComponent = c; +} + + +Base2::Base2() +{ +} + + +Derived2::Derived2() : Base2() +{ +} + +Base2 Derived2::getBase() { + return baseComponent; +} + +void Derived2::setBase(Base2 b) +{ + baseComponent = b; +} +OverlappingNamespace::InDerivedLib Derived2::getNestedNSComponent() +{ + return nestedNSComponent; +} + +void Derived2::setNestedNSComponent(OverlappingNamespace::InDerivedLib c) +{ + nestedNSComponent = c; } diff --git a/tests/NamespacesDerived/NamespacesDerived.h b/tests/NamespacesDerived/NamespacesDerived.h index 13f0d96f..5f4d5287 100644 --- a/tests/NamespacesDerived/NamespacesDerived.h +++ b/tests/NamespacesDerived/NamespacesDerived.h @@ -1,6 +1,8 @@ #include "../Tests.h" #include "../NamespacesBase/NamespacesBase.h" +// Namespace clashes with NamespacesBase.OverlappingNamespace +// Test whether qualified names turn out right. namespace OverlappingNamespace { @@ -9,21 +11,50 @@ namespace OverlappingNamespace public: InDerivedLib(); Base parentNSComponent; - Colors color; + ColorsEnum color; }; } + +// Using a type imported from a different library. class DLL_API Derived : public Base { public: Derived(); Base baseComponent; + Base getBase(); + void setBase(Base); OverlappingNamespace::InBaseLib nestedNSComponent; + OverlappingNamespace::InBaseLib getNestedNSComponent(); + void setNestedNSComponent(OverlappingNamespace::InBaseLib); - OverlappingNamespace::Colors color; + OverlappingNamespace::ColorsEnum color; private: int d; }; + + +// For reference: using a type derived in the same library +class Base2 +{ +public: + Base2(); +}; + +class Derived2 : public Base2 +{ +public: + Derived2(); + + Base2 baseComponent; + Base2 getBase(); + void setBase(Base2); + + OverlappingNamespace::InDerivedLib nestedNSComponent; + OverlappingNamespace::InDerivedLib getNestedNSComponent(); + void setNestedNSComponent(OverlappingNamespace::InDerivedLib); + +}; From 5f232201434e94941b3c5a92eb97d369cc4629da Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Fri, 6 Feb 2015 22:05:18 +0200 Subject: [PATCH 5/5] Fixed two bugs. --- src/Generator/Generators/CSharp/CSharpTextTemplate.cs | 2 +- src/Generator/Passes/RenameRootNamespaces.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 3dd42d21..b80de910 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -133,7 +133,7 @@ namespace CppSharp.Generators.CSharp if (reference.GenerationKind == GenerationKind.Generate && Options.GenerateLibraryNamespace) refNames.Push(Options.OutputNamespace); - while (refNames.Count > 0 && ctxNames.Count > 0 &&refNames.Peek() == ctxNames.Peek()) + while (refNames.Count > 1 && ctxNames.Count > 1 &&refNames.Peek() == ctxNames.Peek()) { refNames.Pop(); ctxNames.Pop(); diff --git a/src/Generator/Passes/RenameRootNamespaces.cs b/src/Generator/Passes/RenameRootNamespaces.cs index e9fdc743..565bcfd2 100644 --- a/src/Generator/Passes/RenameRootNamespaces.cs +++ b/src/Generator/Passes/RenameRootNamespaces.cs @@ -20,7 +20,9 @@ namespace CppSharp.Passes var fileName = unit.TranslationUnit.FileName; if (Driver.RootNamespaceRenames.ContainsKey(fileName)) { - unit.Name = Driver.RootNamespaceRenames[fileName].rootNamespaceName; + var rootNamespace = Driver.RootNamespaceRenames[fileName].rootNamespaceName; + if (this.Driver.Options.OutputNamespace != rootNamespace) + unit.Name = rootNamespace; } else if (unit.GenerationKind == GenerationKind.Generate) {