mirror of https://github.com/mono/CppSharp.git
1 changed files with 178 additions and 0 deletions
@ -0,0 +1,178 @@
@@ -0,0 +1,178 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using CppSharp.AST; |
||||
using Type = CppSharp.AST.Type; |
||||
|
||||
namespace CppSharp.Generators.AST |
||||
{ |
||||
public class ASTRecord |
||||
{ |
||||
public ASTRecord Parent; |
||||
public object Object; |
||||
|
||||
public bool GetParent<T>(out T @out) |
||||
{ |
||||
@out = default(T); |
||||
|
||||
if (Parent == null) |
||||
return false; |
||||
|
||||
var v = Parent.Object; |
||||
if (!(v is T)) |
||||
return false; |
||||
|
||||
@out = (T) v; |
||||
return true; |
||||
} |
||||
|
||||
// Pushes ancestors into the stack until it is found one of type T.
|
||||
public bool GetAncestors<T>(ref Stack<object> ancestors) |
||||
{ |
||||
ancestors.Push(this); |
||||
|
||||
T value; |
||||
if (GetParent(out value)) |
||||
{ |
||||
ancestors.Push(value); |
||||
return true; |
||||
} |
||||
|
||||
return Parent != null |
||||
&& Parent.GetAncestors<T>(ref ancestors); |
||||
} |
||||
} |
||||
|
||||
public class ASTRecord<T> : ASTRecord |
||||
{ |
||||
public T Value |
||||
{ |
||||
get { return (T) Object; } |
||||
} |
||||
} |
||||
|
||||
public class ASTRecordStack |
||||
{ |
||||
private readonly Stack<ASTRecord> recordStack; |
||||
|
||||
public ASTRecordStack() |
||||
{ |
||||
recordStack = new Stack<ASTRecord>(); |
||||
} |
||||
|
||||
public ASTRecord<T> Push<T>(T value) |
||||
{ |
||||
ASTRecord parent = null; |
||||
|
||||
if (recordStack.Count > 0) |
||||
parent = recordStack.Peek(); |
||||
|
||||
var record = new ASTRecord<T>() |
||||
{ |
||||
Parent = parent, |
||||
Object = value |
||||
}; |
||||
recordStack.Push(record); |
||||
return record; |
||||
} |
||||
|
||||
public void Pop() |
||||
{ |
||||
recordStack.Pop(); |
||||
} |
||||
} |
||||
|
||||
static class ASTRecordExtensions |
||||
{ |
||||
public static bool IsBaseClass(this ASTRecord record) |
||||
{ |
||||
Class decl; |
||||
return record.GetParent(out decl) && decl.BaseClass == record.Object; |
||||
} |
||||
|
||||
public static bool IsFieldValueType(this ASTRecord record) |
||||
{ |
||||
var ancestors = new Stack<object>(); |
||||
if(!record.GetAncestors<Field>(ref ancestors)) |
||||
return false; |
||||
|
||||
var field = (Field)ancestors.Pop(); |
||||
|
||||
Class decl; |
||||
if (!field.Type.Desugar().IsTagDecl(out decl)) |
||||
return false; |
||||
|
||||
return decl.IsValueType; |
||||
} |
||||
} |
||||
|
||||
public class RecordCollector : AstVisitor |
||||
{ |
||||
public readonly ISet<ASTRecord<Declaration>> Declarations; |
||||
private readonly ASTRecordStack recordStack; |
||||
|
||||
public TranslationUnit translationUnit; |
||||
|
||||
public ISet<object> Visited2 { get; private set; } |
||||
public bool AlreadyVisited2(object o) |
||||
{ |
||||
return !Visited2.Add(o); |
||||
} |
||||
|
||||
public RecordCollector(TranslationUnit translationUnit) |
||||
{ |
||||
this.translationUnit = translationUnit; |
||||
Declarations = new HashSet<ASTRecord<Declaration>>(); |
||||
recordStack = new ASTRecordStack(); |
||||
Visited2 = new HashSet<object>(); |
||||
} |
||||
|
||||
public override bool VisitDeclaration(Declaration decl) |
||||
{ |
||||
if(translationUnit.FileName.Contains("Font")) |
||||
Console.Write(""); |
||||
|
||||
if (decl.IsIncomplete && decl.CompleteDeclaration != null) |
||||
decl = decl.CompleteDeclaration; |
||||
|
||||
if(AlreadyVisited2(decl)) |
||||
return ShouldVisitChilds(decl); |
||||
Visited.Remove(decl); // So Class can be revisited
|
||||
|
||||
Declarations.Add(recordStack.Push(decl)); |
||||
decl.Visit(this); |
||||
recordStack.Pop(); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool VisitType(Type type, TypeQualifiers quals) |
||||
{ |
||||
type = type.Desugar(); |
||||
|
||||
if(AlreadyVisited2(type)) |
||||
return true; |
||||
|
||||
recordStack.Push(type); |
||||
type.Visit(this); |
||||
recordStack.Pop(); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public bool ShouldVisitChilds(Declaration decl) |
||||
{ |
||||
if(decl == translationUnit) |
||||
return true; |
||||
|
||||
if (decl is TranslationUnit) |
||||
return false; |
||||
|
||||
if (decl.Namespace == null) |
||||
return true; |
||||
|
||||
// No need to continue visiting after a declaration of
|
||||
// another translation unit is encountered.
|
||||
return decl.Namespace.TranslationUnit == translationUnit; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue