Browse Source

Move the GenerateInclude logic to GetTypeReference (#1319)

Improve generation of forward references and includes in C++/CLI.

Move the GenerateInclude logic to GetTypeReference so that an include is also generated for visited types of an ASTRecord that are forward declared, and come from typedef of ignored class template.

Co-authored-by: Build Agent <admin@sage.com>
pull/1322/head
Ali Alamiri 5 years ago committed by GitHub
parent
commit
344656c787
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      build/Tests.lua
  2. 63
      src/Generator/Generators/CLI/CLITypeReferences.cs
  3. 3
      src/Generator/Types/Std/Stdlib.cs
  4. 9
      tests/CLI/CLI.Tests.cs
  5. 54
      tests/CLI/CLI.cs
  6. 3
      tests/CLI/CLI.h
  7. 6
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp
  8. 10
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h
  9. 4
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h
  10. 13
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp
  11. 13
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h
  12. 13
      tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h
  13. 2
      tests/CLI/premake4.lua

4
build/Tests.lua

@ -31,10 +31,10 @@ function SetupTestCSharp(name)
SetupTestProjectsCSharp(name) SetupTestProjectsCSharp(name)
end end
function SetupTestCLI(name) function SetupTestCLI(name, extraFiles, suffix)
SetupTestGeneratorProject(name) SetupTestGeneratorProject(name)
SetupTestNativeProject(name) SetupTestNativeProject(name)
SetupTestProjectsCLI(name) SetupTestProjectsCLI(name, extraFiles, suffix)
end end
function SetupManagedTestProject() function SetupManagedTestProject()

63
src/Generator/Generators/CLI/CLITypeReferences.cs

@ -48,12 +48,27 @@ namespace CppSharp.Generators.CLI
if (typeReferences.ContainsKey(decl)) if (typeReferences.ContainsKey(decl))
return typeReferences[decl]; return typeReferences[decl];
var translationUnit = decl.Namespace.TranslationUnit;
if (ShouldIncludeTranslationUnit(translationUnit) && decl.IsGenerated && !IsBuiltinTypedef(decl))
{
var @ref = new CLITypeReference { Declaration = decl }; var @ref = new CLITypeReference { Declaration = decl };
@ref.Include = new CInclude
{
File = GetIncludePath(translationUnit),
TranslationUnit = translationUnit,
Kind = translationUnit.IsGenerated ? CInclude.IncludeKind.Quoted : CInclude.IncludeKind.Angled
};
typeReferences.Add(decl, @ref); typeReferences.Add(decl, @ref);
return @ref; return @ref;
} }
return null;
}
static Namespace GetEffectiveNamespace(Declaration decl) static Namespace GetEffectiveNamespace(Declaration decl)
{ {
if (decl == null || decl.Namespace == null) if (decl == null || decl.Namespace == null)
@ -104,39 +119,27 @@ namespace CppSharp.Generators.CLI
if (decl.Namespace == null) if (decl.Namespace == null)
return; return;
var typedefType = record.Value as TypedefNameDecl;
// Find a type map for the declaration and use it if it exists. // Find a type map for the declaration and use it if it exists.
TypeMap typeMap; TypeMap typeMap;
if (TypeMapDatabase.FindTypeMap(record.Value, out typeMap)) if (TypeMapDatabase.FindTypeMap(record.Value, out typeMap)
|| (typedefType != null && TypeMapDatabase.FindTypeMap(typedefType.Type.Desugar(), out typeMap)))
{ {
typeMap.CLITypeReference(this, record); typeMap.CLITypeReference(this, record);
return; return;
} }
var translationUnit = decl.Namespace.TranslationUnit;
if (translationUnit.IsSystemHeader || !translationUnit.IsValid)
return;
if (!decl.IsGenerated)
return;
if (IsBuiltinTypedef(decl))
return;
var typeRef = GetTypeReference(decl); var typeRef = GetTypeReference(decl);
if (typeRef.Include.TranslationUnit == null) if(typeRef != null)
{ {
typeRef.Include = new CInclude typeRef.Include.InHeader |= IsIncludeInHeader(record);
{ }
File = GetIncludePath(translationUnit),
TranslationUnit = translationUnit,
Kind = translationUnit.IsGenerated
? CInclude.IncludeKind.Quoted
: CInclude.IncludeKind.Angled,
};
} }
typeRef.Include.InHeader |= IsIncludeInHeader(record); private bool ShouldIncludeTranslationUnit(TranslationUnit unit)
{
return !unit.IsSystemHeader && unit.IsValid && !unit.Ignore;
} }
private string GetIncludePath(TranslationUnit translationUnit) private string GetIncludePath(TranslationUnit translationUnit)
@ -168,7 +171,7 @@ namespace CppSharp.Generators.CLI
return typedefType.Declaration.Type is BuiltinType; return typedefType.Declaration.Type is BuiltinType;
} }
private bool IsIncludeInHeader(ASTRecord<Declaration> record) public bool IsIncludeInHeader(ASTRecord<Declaration> record)
{ {
if (TranslationUnit == record.Value.Namespace.TranslationUnit) if (TranslationUnit == record.Value.Namespace.TranslationUnit)
return false; return false;
@ -198,7 +201,12 @@ namespace CppSharp.Generators.CLI
var @ref = $"{keywords} {@class.Name};"; var @ref = $"{keywords} {@class.Name};";
GetTypeReference(@class).FowardReference = @ref; var typeRef = GetTypeReference(@class);
if (typeRef != null)
{
typeRef.FowardReference = @ref;
}
return false; return false;
} }
@ -217,7 +225,12 @@ namespace CppSharp.Generators.CLI
var @ref = $"{enumKind} {@enum.Name}{@base};"; var @ref = $"{enumKind} {@enum.Name}{@base};";
GetTypeReference(@enum).FowardReference = @ref; var typeRef = GetTypeReference(@enum);
if (typeRef != null)
{
typeRef.FowardReference = @ref;
}
return false; return false;
} }

3
src/Generator/Types/Std/Stdlib.cs

@ -690,6 +690,8 @@ namespace CppSharp.Types.Std
{ {
var typeRef = collector.GetTypeReference(loc.Value); var typeRef = collector.GetTypeReference(loc.Value);
if (typeRef != null)
{
var include = new CInclude var include = new CInclude
{ {
File = "cstddef", File = "cstddef",
@ -699,6 +701,7 @@ namespace CppSharp.Types.Std
typeRef.Include = include; typeRef.Include = include;
} }
} }
}
[TypeMap("FILE", GeneratorKind = GeneratorKind.CSharp)] [TypeMap("FILE", GeneratorKind = GeneratorKind.CSharp)]
public class FILE : TypeMap public class FILE : TypeMap

9
tests/CLI/CLI.Tests.cs

@ -26,4 +26,13 @@ public class CLITests : GeneratorTestFixture
Assert.AreEqual(EnumParam.E1, byRefEnumParam.GetPassedEnumParam(EnumParam.E1)); Assert.AreEqual(EnumParam.E1, byRefEnumParam.GetPassedEnumParam(EnumParam.E1));
} }
} }
[Test]
public void GetEmployeeNameFromOrgTest()
{
using (EmployeeOrg org = new EmployeeOrg())
{
Assert.AreEqual("Employee", org.Employee.Name);
}
}
} }

54
tests/CLI/CLI.cs

@ -1,9 +1,58 @@
using CppSharp.AST; using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators; using CppSharp.Generators;
using CppSharp.Passes;
using CppSharp.Types;
using CppSharp.Utils; using CppSharp.Utils;
namespace CppSharp.Tests namespace CppSharp.Tests
{ {
[TypeMap("IgnoredClassTemplateForEmployee")]
public class IgnoredClassTemplateForEmployeeMap : TypeMap
{
public override Type CLISignatureType(TypePrinterContext ctx)
{
return new CustomType("CLI::Employee^");
}
public override void CLIMarshalToManaged(MarshalContext ctx)
{
ctx.Return.Write($"gcnew CLI::Employee({ctx.ReturnVarName}.m_employee)");
}
}
public class CompleteIgnoredClassTemplateForEmployeeTypedefPass : TranslationUnitPass
{
public override bool VisitTypedefDecl(TypedefDecl typedef)
{
var templateType = GetDesugaredFinalPointeeElseType(typedef?.Type?.Desugar()) as TemplateSpecializationType;
bool isTemplateTypedef = IsTemplateTypedef(templateType?.Template?.OriginalName);
if (isTemplateTypedef)
{
Class @class;
if (templateType.TryGetClass(out @class))
{
@class.IsIncomplete = false;
return true;
}
}
return base.VisitTypedefDecl(typedef);
}
private bool IsTemplateTypedef(string templateName)
{
return !string.IsNullOrEmpty(templateName) && "IgnoredClassTemplateForEmployee" == templateName;
}
public Type GetDesugaredFinalPointeeElseType(Type t)
{
Type finalPointee = t.GetFinalPointee();
return finalPointee != null ? finalPointee.Desugar() : t;
}
}
public class CLITestsGenerator : GeneratorTest public class CLITestsGenerator : GeneratorTest
{ {
public CLITestsGenerator(GeneratorKind kind) public CLITestsGenerator(GeneratorKind kind)
@ -22,6 +71,11 @@ namespace CppSharp.Tests
{ {
} }
public override void SetupPasses(Driver driver)
{
driver.AddTranslationUnitPass(new CompleteIgnoredClassTemplateForEmployeeTypedefPass());
}
public static void Main(string[] args) public static void Main(string[] args)
{ {
ConsoleDriver.Run(new CLITestsGenerator(GeneratorKind.CLI)); ConsoleDriver.Run(new CLITestsGenerator(GeneratorKind.CLI));

3
tests/CLI/CLI.h

@ -1,5 +1,8 @@
#include "../Tests.h" #include "../Tests.h"
#include "UseTemplateTypeFromIgnoredClassTemplate/Employee.h"
#include "UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h"
#include <ostream> #include <ostream>
// Tests for C++ types // Tests for C++ types

6
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp

@ -0,0 +1,6 @@
#include "Employee.h"
std::string Employee::GetName()
{
return "Employee";
}

10
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h

@ -0,0 +1,10 @@
#pragma once
#include "../../Tests.h"
#include <string>
class DLL_API Employee
{
public:
virtual std::string GetName();
};

4
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h

@ -0,0 +1,4 @@
#include "IgnoredClassTemplateForEmployee.h"
class Employee;
typedef IgnoredClassTemplateForEmployee<Employee> EmployeeTypedef;

13
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp

@ -0,0 +1,13 @@
#include "EmployeeOrg.h"
#include "Employee.h"
EmployeeTypedef EmployeeOrg::GetEmployee()
{
return IgnoredClassTemplateForEmployee<Employee>(new Employee());
}
void EmployeeOrg::DoSomething()
{
}

13
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h

@ -0,0 +1,13 @@
#pragma once
#include "../../Tests.h"
#include "EmployeeForwardDecl.h"
class DLL_API EmployeeOrg
{
public:
void DoSomething();
EmployeeTypedef GetEmployee();
};

13
tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h

@ -0,0 +1,13 @@
#pragma once
template<typename EmployeeT>
class IgnoredClassTemplateForEmployee
{
public:
IgnoredClassTemplateForEmployee<EmployeeT>(EmployeeT* employee)
: m_employee(employee)
{
}
EmployeeT* m_employee;
};

2
tests/CLI/premake4.lua

@ -1,2 +1,2 @@
group "Tests/CLI" group "Tests/CLI"
SetupTestCLI("CLI") SetupTestCLI("CLI", { "Employee", "EmployeeOrg" })
Loading…
Cancel
Save