mirror of https://github.com/mono/CppSharp.git
6 changed files with 191 additions and 288 deletions
@ -1,235 +0,0 @@
@@ -1,235 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using CppSharp.AST; |
||||
using CppSharp.Types; |
||||
|
||||
namespace CppSharp.Generators.CLI |
||||
{ |
||||
public struct CLIForwardReference |
||||
{ |
||||
public Declaration Declaration; |
||||
public Namespace Namespace; |
||||
public string Text; |
||||
} |
||||
|
||||
public class CLIForwardReferencePrinter : IDeclVisitor<bool> |
||||
{ |
||||
public readonly IList<string> Includes; |
||||
public readonly IList<CLIForwardReference> Refs; |
||||
private readonly TypeRefsVisitor TypeRefs; |
||||
public TypeReference CurrentTypeReference; |
||||
private readonly ITypeMapDatabase TypeMapDatabase; |
||||
|
||||
public CLIForwardReferencePrinter(TypeRefsVisitor typeRefs, ITypeMapDatabase typeMapDatabase) |
||||
{ |
||||
Includes = new List<string>(); |
||||
Refs = new List<CLIForwardReference>(); |
||||
TypeRefs = typeRefs; |
||||
TypeMapDatabase = typeMapDatabase; |
||||
} |
||||
|
||||
public void Process() |
||||
{ |
||||
foreach (var typeRef in TypeRefs.References) |
||||
{ |
||||
CurrentTypeReference = typeRef; |
||||
typeRef.Declaration.Visit(this); |
||||
} |
||||
|
||||
foreach (var baseClass in TypeRefs.Bases) |
||||
VisitBaseClass(baseClass); |
||||
} |
||||
|
||||
public void VisitBaseClass(Class @class) |
||||
{ |
||||
if (@class.IsIncomplete) |
||||
@class = @class.CompleteDeclaration as Class; |
||||
|
||||
if (@class == null) |
||||
return; |
||||
|
||||
Includes.Add(GetHeaderFromDecl(@class)); |
||||
} |
||||
|
||||
public bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitClassDecl(Class @class) |
||||
{ |
||||
var completeDecl = @class.CompleteDeclaration as Class; |
||||
if (@class.IsIncomplete && completeDecl != null) |
||||
return VisitClassDecl(completeDecl); |
||||
|
||||
if (@class.IsValueType) |
||||
{ |
||||
Refs.Add(new CLIForwardReference() |
||||
{ |
||||
Declaration = @class, |
||||
Namespace = CurrentTypeReference.Namespace, |
||||
Text = string.Format("value struct {0};", @class.Name) |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Refs.Add(new CLIForwardReference() |
||||
{ |
||||
Declaration = @class, |
||||
Namespace = CurrentTypeReference.Namespace, |
||||
Text = string.Format("ref class {0};", @class.Name) |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public bool VisitFieldDecl(Field field) |
||||
{ |
||||
Class @class; |
||||
if (field.Type.IsTagDecl(out @class)) |
||||
{ |
||||
if (@class.IsValueType) |
||||
Includes.Add(GetHeaderFromDecl(@class)); |
||||
else |
||||
VisitClassDecl(@class); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Enumeration @enum; |
||||
if (field.Type.IsTagDecl(out @enum)) |
||||
return VisitEnumDecl(@enum); |
||||
|
||||
Includes.Add(GetHeaderFromDecl(field)); |
||||
return true; |
||||
} |
||||
|
||||
public bool VisitFunctionDecl(Function function) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMethodDecl(Method method) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitParameterDecl(Parameter parameter) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public string GetHeaderFromDecl(Declaration decl) |
||||
{ |
||||
var @namespace = decl.Namespace; |
||||
var unit = @namespace.TranslationUnit; |
||||
|
||||
if (unit.Ignore) |
||||
return string.Empty; |
||||
|
||||
if (unit.IsSystemHeader) |
||||
return string.Empty; |
||||
|
||||
return Path.GetFileNameWithoutExtension(unit.FileName); |
||||
} |
||||
|
||||
public bool VisitTypedefDecl(TypedefDecl typedef) |
||||
{ |
||||
FunctionType function; |
||||
if (typedef.Type.IsPointerTo<FunctionType>(out function)) |
||||
{ |
||||
Includes.Add(GetHeaderFromDecl(typedef)); |
||||
return true; |
||||
} |
||||
|
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
Includes.Add(GetHeaderFromDecl(@enum)); |
||||
|
||||
if (@enum.Type.IsPrimitiveType(PrimitiveType.Int32)) |
||||
{ |
||||
Refs.Add(new CLIForwardReference() |
||||
{ |
||||
Declaration = @enum, |
||||
Namespace = CurrentTypeReference.Namespace, |
||||
Text = string.Format("enum struct {0};", @enum.Name) |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Refs.Add(new CLIForwardReference() |
||||
{ |
||||
Declaration = @enum, |
||||
Namespace = CurrentTypeReference.Namespace, |
||||
Text = string.Format("enum struct {0} : {1};", @enum.Name, @enum.Type) |
||||
}); |
||||
return true; |
||||
} |
||||
|
||||
public bool VisitVariableDecl(Variable variable) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitClassTemplateDecl(ClassTemplate template) |
||||
{ |
||||
var decl = template.TemplatedDecl; |
||||
|
||||
TypeMap typeMap = null; |
||||
if (TypeMapDatabase.FindTypeMap(decl, out typeMap)) |
||||
{ |
||||
typeMap.Declaration = decl; |
||||
typeMap.CLIForwardReference(this); |
||||
return true; |
||||
} |
||||
|
||||
if(decl.Ignore) |
||||
return true; |
||||
|
||||
Includes.Add(GetHeaderFromDecl(template)); |
||||
|
||||
var @params = string.Empty; |
||||
for(var i = 0; i < template.Parameters.Count; i++) |
||||
@params = string.Format("{0}{1}typename {2}", @params, (i>0)? ", " : "", template.Parameters[i].Name); |
||||
|
||||
Refs.Add(new CLIForwardReference() |
||||
{ |
||||
Declaration = template, |
||||
Namespace = CurrentTypeReference.Namespace, |
||||
Text = string.Format("generic<{0}> ref class {1};", @params, template.TemplatedClass.QualifiedName) |
||||
}); |
||||
return true; |
||||
} |
||||
|
||||
public bool VisitFunctionTemplateDecl(FunctionTemplate template) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitMacroDefinition(MacroDefinition macro) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitNamespace(Namespace @namespace) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitEvent(Event @event) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool VisitProperty(Property property) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
using System.Collections.Generic; |
||||
using CppSharp.AST; |
||||
using CppSharp.Generators.AST; |
||||
using CppSharp.Types; |
||||
|
||||
namespace CppSharp.Generators.CLI |
||||
{ |
||||
public class CLITypeReference |
||||
{ |
||||
public Include Include; |
||||
public string FowardReference; |
||||
} |
||||
|
||||
public class CLITypeReferenceCollector : AstVisitor |
||||
{ |
||||
private Dictionary<Declaration, CLITypeReference> typeReferences; |
||||
private readonly ITypeMapDatabase TypeMapDatabase; |
||||
private TranslationUnit TranslationUnit; |
||||
|
||||
public IEnumerable<CLITypeReference> TypeReferences |
||||
{ |
||||
get { return typeReferences.Values; } |
||||
} |
||||
|
||||
public CLITypeReferenceCollector(ITypeMapDatabase typeMapDatabase) |
||||
{ |
||||
TypeMapDatabase = typeMapDatabase; |
||||
typeReferences = new Dictionary<Declaration,CLITypeReference>(); |
||||
} |
||||
|
||||
public CLITypeReference GetTypeReference(Declaration decl) |
||||
{ |
||||
if(typeReferences.ContainsKey(decl)) |
||||
return typeReferences[decl]; |
||||
|
||||
var @ref = new CLITypeReference(); |
||||
typeReferences.Add(decl, @ref); |
||||
return @ref; |
||||
} |
||||
|
||||
public void Process(Namespace @namespace) |
||||
{ |
||||
var collector = new RecordCollector(@namespace.TranslationUnit); |
||||
@namespace.Visit(collector); |
||||
|
||||
TranslationUnit = @namespace.TranslationUnit; |
||||
|
||||
foreach (var record in collector.Declarations) |
||||
{ |
||||
record.Value.Visit(this); |
||||
GenerateInclude(record); |
||||
ProcessTypeMap(record); |
||||
} |
||||
} |
||||
|
||||
private void ProcessTypeMap(ASTRecord<Declaration> record) |
||||
{ |
||||
TypeMap typeMap; |
||||
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); |
||||
} |
||||
|
||||
private void GenerateInclude(ASTRecord<Declaration> record) |
||||
{ |
||||
var decl = record.Value; |
||||
if(decl.Namespace == null) |
||||
return; |
||||
|
||||
var declFile = decl.Namespace.TranslationUnit.FileName; |
||||
|
||||
if(decl.Namespace.TranslationUnit.IsSystemHeader) |
||||
return; |
||||
|
||||
if(decl.Ignore) |
||||
return; |
||||
|
||||
if(IsBuiltinTypedef(decl)) |
||||
return; |
||||
|
||||
if (declFile.Contains("String")) |
||||
return; |
||||
|
||||
GetTypeReference(decl).Include = new Include() |
||||
{ |
||||
File = declFile, |
||||
Kind = Include.IncludeKind.Quoted, |
||||
InHeader = IsIncludeInHeader(record) |
||||
}; |
||||
} |
||||
|
||||
private bool IsBuiltinTypedef(Declaration decl) |
||||
{ |
||||
var typedefDecl = decl as TypedefDecl; |
||||
if(typedefDecl == null) return false; |
||||
if(typedefDecl.Type is BuiltinType) return true; |
||||
|
||||
var typedefType = typedefDecl.Type as TypedefType; |
||||
if(typedefType == null) return false; |
||||
if(typedefType.Declaration == null) return false; |
||||
|
||||
return typedefType.Declaration.Type is BuiltinType; |
||||
} |
||||
|
||||
private bool IsIncludeInHeader(ASTRecord<Declaration> record) |
||||
{ |
||||
return record.IsBaseClass() || record.IsFieldValueType(); |
||||
} |
||||
|
||||
public override bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
return ShouldVisitDecl(decl); |
||||
} |
||||
|
||||
public override bool VisitClassDecl(Class @class) |
||||
{ |
||||
if(!ShouldVisitDecl(@class)) |
||||
return false; |
||||
|
||||
if (@class.IsIncomplete && @class.CompleteDeclaration != null) |
||||
@class = (Class) @class.CompleteDeclaration; |
||||
|
||||
var keywords = @class.IsValueType? "value struct" : "ref class"; |
||||
var @ref = string.Format("{0} {1};", keywords, @class.Name); |
||||
|
||||
GetTypeReference(@class).FowardReference = @ref; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool VisitEnumDecl(Enumeration @enum) |
||||
{ |
||||
if(!ShouldVisitDecl(@enum)) |
||||
return false; |
||||
|
||||
var @base = ""; |
||||
if(!@enum.Type.IsPrimitiveType(PrimitiveType.Int32)) |
||||
@base = string.Format(" : {0}", @enum.Type); |
||||
|
||||
var @ref = string.Format("enum struct {0}{1};", @enum.Name, @base); |
||||
|
||||
GetTypeReference(@enum).FowardReference = @ref; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private bool ShouldVisitDecl(Declaration decl) |
||||
{ |
||||
if(decl.Namespace != null && decl.Namespace.TranslationUnit.IsSystemHeader) |
||||
return false; |
||||
|
||||
if (decl.Ignore) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue