Browse Source

Reworked the CLI type references collector and generation code.

We now properly handle type references to namespaces that do not exist in the referencing translation unit. We do this by collecting all the references for all namespaces in the translation unit and generate a block with all the forward references.
pull/86/head
triton 12 years ago
parent
commit
b91ac99576
  1. 19
      src/AST/Namespace.cs
  2. 3
      src/AST/TranslationUnit.cs
  3. 68
      src/Generator/Generators/CLI/CLIHeadersTemplate.cs
  4. 31
      src/Generator/Generators/CLI/CLITypeReferences.cs

19
src/AST/Namespace.cs

@ -19,6 +19,7 @@ namespace CppSharp.AST @@ -19,6 +19,7 @@ namespace CppSharp.AST
public List<TypedefDecl> Typedefs;
public List<Variable> Variables;
public List<Event> Events;
public List<TypeReference> TypeReferences;
// Used to keep track of anonymous declarations.
public Dictionary<ulong, Declaration> Anonymous;
@ -44,9 +45,27 @@ namespace CppSharp.AST @@ -44,9 +45,27 @@ namespace CppSharp.AST
Typedefs = new List<TypedefDecl>();
Variables = new List<Variable>();
Events = new List<Event>();
TypeReferences = new List<TypeReference>();
Anonymous = new Dictionary<ulong, Declaration>();
}
public IEnumerable<DeclarationContext> GatherParentNamespaces()
{
var children = new List<DeclarationContext>();
var currentNamespace = this;
while (currentNamespace != null)
{
if (!(currentNamespace is TranslationUnit))
children.Add(currentNamespace);
currentNamespace = currentNamespace.Namespace;
}
children.Reverse();
return children;
}
public Declaration FindAnonymous(ulong key)
{
return Anonymous.ContainsKey(key) ? Anonymous[key] : null;

3
src/AST/TranslationUnit.cs

@ -57,8 +57,5 @@ namespace CppSharp.AST @@ -57,8 +57,5 @@ namespace CppSharp.AST
/// Contains the include path.
public string IncludePath;
/// Type references object.
public object TypeReferences;
}
}

68
src/Generator/Generators/CLI/CLIHeadersTemplate.cs

@ -30,13 +30,18 @@ namespace CppSharp.Generators.CLI @@ -30,13 +30,18 @@ namespace CppSharp.Generators.CLI
if (Options.OutputInteropIncludes)
WriteLine("#include \"CppSharp.h\"");
// Generate #include forward references.
PushBlock(CLIBlockKind.IncludesForwardReferences);
WriteLine("#include <{0}>", TranslationUnit.IncludePath);
GenerateIncludeForwardRefs();
PopBlock(NewLineKind.BeforeNextBlock);
PopBlock(NewLineKind.Always);
// Generate namespace for forward references.
PushBlock(CLIBlockKind.ForwardReferences);
GenerateForwardRefs();
PopBlock(NewLineKind.BeforeNextBlock);
GenerateNamespace(TranslationUnit);
PushBlock(BlockKind.Footer);
@ -72,27 +77,61 @@ namespace CppSharp.Generators.CLI @@ -72,27 +77,61 @@ namespace CppSharp.Generators.CLI
WriteLine(include);
}
public void GenerateForwardRefs(Namespace @namespace)
private Namespace FindCreateNamespace(Namespace @namespace, Declaration decl)
{
var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase);
typeReferenceCollector.Process(@namespace, filterNamespaces: true);
if (decl.Namespace is TranslationUnit)
return @namespace;
// Use a set to remove duplicate entries.
var forwardRefs = new SortedSet<string>(StringComparer.InvariantCulture);
var childNamespaces = decl.Namespace.GatherParentNamespaces();
var currentNamespace = @namespace;
foreach (var typeRef in typeReferenceCollector.TypeReferences)
foreach (var child in childNamespaces)
currentNamespace = currentNamespace.FindCreateNamespace(child.Name);
return currentNamespace;
}
public Namespace ConvertForwardReferencesToNamespaces(
IEnumerable<CLITypeReference> typeReferences)
{
// Create a new tree of namespaces out of the type references found.
var rootNamespace = new Namespace();
foreach (var typeRef in typeReferences)
{
var @ref = typeRef.FowardReference;
if(!string.IsNullOrEmpty(@ref) && !typeRef.Include.InHeader)
forwardRefs.Add(@ref);
if (string.IsNullOrWhiteSpace(typeRef.FowardReference))
continue;
var declaration = typeRef.Declaration;
if (!(declaration.Namespace is Namespace))
continue;
var @namespace = FindCreateNamespace(rootNamespace, declaration);
@namespace.TypeReferences.Add(typeRef);
}
foreach (var forwardRef in forwardRefs)
WriteLine(forwardRef);
return rootNamespace;
}
public void GenerateForwardRefs()
{
var typeReferenceCollector = new CLITypeReferenceCollector(Driver.TypeDatabase);
typeReferenceCollector.Process(TranslationUnit);
var typeReferences = typeReferenceCollector.TypeReferences;
var @namespace = ConvertForwardReferencesToNamespaces(typeReferences);
GenerateDeclContext(@namespace);
}
public void GenerateDeclContext(DeclarationContext decl)
{
// Generate all the type references for the module.
foreach (var typeRef in decl.TypeReferences)
{
WriteLine(typeRef.FowardReference);
}
// Generate all the enum declarations for the module.
foreach (var @enum in decl.Enums)
{
@ -142,11 +181,6 @@ namespace CppSharp.Generators.CLI @@ -142,11 +181,6 @@ namespace CppSharp.Generators.CLI
WriteStartBraceIndent();
}
// Generate the forward references.
PushBlock(CLIBlockKind.ForwardReferences);
GenerateForwardRefs(@namespace);
PopBlock(NewLineKind.BeforeNextBlock);
GenerateDeclContext(@namespace);
if (generateNamespace)

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

@ -5,23 +5,25 @@ using CppSharp.Types; @@ -5,23 +5,25 @@ using CppSharp.Types;
namespace CppSharp.Generators.CLI
{
public class CLITypeReference
public class CLITypeReference : TypeReference
{
public Include Include;
public string FowardReference;
public override string ToString()
{
return FowardReference;
if (!string.IsNullOrWhiteSpace(FowardReference))
return FowardReference;
return Include.ToString();
}
}
public class CLITypeReferenceCollector : AstVisitor
{
private Dictionary<Declaration, CLITypeReference> typeReferences;
private readonly ITypeMapDatabase TypeMapDatabase;
private TranslationUnit TranslationUnit;
private Dictionary<Declaration, CLITypeReference> typeReferences;
public IEnumerable<CLITypeReference> TypeReferences
{
get { return typeReferences.Values; }
@ -38,8 +40,9 @@ namespace CppSharp.Generators.CLI @@ -38,8 +40,9 @@ namespace CppSharp.Generators.CLI
if(typeReferences.ContainsKey(decl))
return typeReferences[decl];
var @ref = new CLITypeReference();
var @ref = new CLITypeReference { Declaration = decl };
typeReferences.Add(decl, @ref);
return @ref;
}
@ -55,13 +58,13 @@ namespace CppSharp.Generators.CLI @@ -55,13 +58,13 @@ namespace CppSharp.Generators.CLI
return GetEffectiveNamespace(@namespace);
}
public void Process(Namespace @namespace, bool filterNamespaces)
public void Process(Namespace @namespace, bool filterNamespaces = false)
{
var collector = new RecordCollector(@namespace.TranslationUnit);
@namespace.Visit(collector);
TranslationUnit = @namespace.TranslationUnit;
var collector = new RecordCollector(TranslationUnit);
@namespace.Visit(collector);
foreach (var record in collector.Declarations)
{
if (record.Value is Namespace)
@ -69,7 +72,7 @@ namespace CppSharp.Generators.CLI @@ -69,7 +72,7 @@ namespace CppSharp.Generators.CLI
if (filterNamespaces)
{
var declNamespace = GetEffectiveNamespace(record.Value.Namespace);
var declNamespace = GetEffectiveNamespace(record.Value);
var isSameNamespace = declNamespace == @namespace;
if (declNamespace != null)
@ -88,10 +91,9 @@ namespace CppSharp.Generators.CLI @@ -88,10 +91,9 @@ namespace CppSharp.Generators.CLI
private void ProcessTypeMap(ASTRecord<Declaration> record)
{
TypeMap typeMap;
if (!TypeMapDatabase.FindTypeMap(record.Value, out typeMap)) return;
if (!TypeMapDatabase.FindTypeMap(record.Value, out typeMap))
return;
// Typemap must explicitly set the include file when one is required.
GetTypeReference(record.Value).Include.File = "";
typeMap.Declaration = record.Value;
typeMap.CLITypeReference(this, record);
@ -114,9 +116,6 @@ namespace CppSharp.Generators.CLI @@ -114,9 +116,6 @@ namespace CppSharp.Generators.CLI
if(IsBuiltinTypedef(decl))
return;
if (declFile.Contains("String"))
return;
var typeRef = GetTypeReference(decl);
typeRef.Include = new Include()
{

Loading…
Cancel
Save