Tools and libraries to glue C/C++ APIs to high-level languages
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

304 lines
9.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
namespace CppSharp.AST
{
// A C++ access specifier.
public enum AccessSpecifier
{
Private,
Protected,
Public
}
// A C++ access specifier declaration.
public class AccessSpecifierDecl : Declaration
{
public override T Visit<T>(IDeclVisitor<T> visitor)
{
throw new NotImplementedException();
}
}
// Represents a base class of a C++ class.
public class BaseClassSpecifier
{
public AccessSpecifier Access { get; set; }
public bool IsVirtual { get; set; }
public Type Type { get; set; }
public Class Class
{
get
{
Class @class;
if (!Type.IsTagDecl(out @class))
throw new NotSupportedException();
return @class;
}
}
public bool IsClass
{
get
{
Class @class;
return Type.IsTagDecl(out @class);
}
}
public BaseClassSpecifier()
{
}
}
public enum ClassType
{
ValueType,
RefType,
Interface
}
// Represents a C++ record Decl.
public class Class : DeclarationContext
{
public List<BaseClassSpecifier> Bases;
public List<Field> Fields;
public List<Property> Properties;
public List<Method> Methods;
public List<AccessSpecifierDecl> Specifiers;
// True if the record is a POD (Plain Old Data) type.
public bool IsPOD;
// Semantic type of the class.
public ClassType Type;
// ABI-specific class layout.
public ClassLayout Layout;
// True if class provides pure virtual methods.
public bool IsAbstract;
// True if the type is to be treated as a union.
public bool IsUnion;
// True if the type is to be treated as opaque.
public bool IsOpaque;
// True if the class is dynamic.
public bool IsDynamic;
// True if the class is polymorphic.
public bool IsPolymorphic;
// True if the class has a non trivial default constructor.
public bool HasNonTrivialDefaultConstructor;
// True if the class has a non trivial copy constructor.
public bool HasNonTrivialCopyConstructor;
public Class()
{
Bases = new List<BaseClassSpecifier>();
Fields = new List<Field>();
Properties = new List<Property>();
Methods = new List<Method>();
Specifiers = new List<AccessSpecifierDecl>();
IsAbstract = false;
IsUnion = false;
IsOpaque = false;
IsPOD = false;
Type = ClassType.RefType;
Layout = new ClassLayout();
}
public bool HasBase
{
get { return Bases.Count > 0; }
}
public bool HasBaseClass
{
get { return BaseClass != null; }
}
public Class BaseClass
{
get
{
foreach (var @base in Bases)
{
if (@base.IsClass && !@base.Class.Ignore)
return @base.Class;
}
return null;
}
}
public Class OriginalClass { get; set; }
public bool IsValueType
{
get { return Type == ClassType.ValueType || IsUnion; }
}
public bool IsRefType
{
get { return Type == ClassType.RefType && !IsUnion; }
}
public bool IsInterface
{
get { return Type == ClassType.Interface; }
}
public IEnumerable<Method> Constructors
{
get
{
return Methods.Where(
method => method.IsConstructor || method.IsCopyConstructor);
}
}
public IEnumerable<Method> Operators
{
get
{
return Methods.Where(method => method.IsOperator);
}
}
public IEnumerable<Method> FindOperator(CXXOperatorKind kind)
{
return Operators.Where(method => method.OperatorKind == kind);
}
public IEnumerable<Method> FindMethodByOriginalName(string name)
{
return Methods.Where(method => method.OriginalName == name);
}
public IEnumerable<Variable> FindVariableByOriginalName(string originalName)
{
return Variables.Where(v => v.OriginalName == originalName);
}
public override IEnumerable<Function> GetFunctionOverloads(Function function)
{
if (function.IsOperator)
return FindOperator(function.OperatorKind);
return Methods.Where(method => method.Name == function.Name);
}
public IEnumerable<T> FindHierarchy<T>(Func<Class, IEnumerable<T>> func)
where T : Declaration
{
foreach (var elem in func(this))
yield return elem;
foreach (var @base in Bases)
{
if (!@base.IsClass) continue;
foreach(var elem in @base.Class.FindHierarchy<T>(func))
yield return elem;
}
}
public Method GetRootBaseMethod(Method @override, bool onlyFirstBase = false)
{
return (from @base in Bases
where @base.IsClass && (!onlyFirstBase || !@base.Class.IsInterface)
let baseMethod = (
from method in @base.Class.Methods
where
method.Name == @override.Name &&
method.ReturnType == @override.ReturnType &&
method.Parameters.Count == @override.Parameters.Count &&
method.Parameters.SequenceEqual(@override.Parameters,
new ParameterTypeComparer())
select method).FirstOrDefault()
let rootBaseMethod = @base.Class.GetRootBaseMethod(@override) ?? baseMethod
where rootBaseMethod != null || onlyFirstBase
select rootBaseMethod).FirstOrDefault();
}
public Property GetRootBaseProperty(Property @override, bool onlyFirstBase = false)
{
return (from @base in Bases
where (!onlyFirstBase || !@base.Class.IsInterface) && @base.IsClass
let baseProperty = (
from property in @base.Class.Properties
where
property.Name == @override.Name &&
property.Parameters.Count == @override.Parameters.Count &&
property.Parameters.SequenceEqual(@override.Parameters,
new ParameterTypeComparer())
select property).FirstOrDefault()
let rootBaseProperty = @base.Class.GetRootBaseProperty(@override) ?? baseProperty
where rootBaseProperty != null || onlyFirstBase
select rootBaseProperty).FirstOrDefault();
}
public Property GetPropertyByName(string propertyName)
{
Property property = Properties.FirstOrDefault(m => m.Name == propertyName);
if (property != null)
return property;
Declaration decl;
foreach (var baseClassSpecifier in Bases.Where(
b => b.Type.IsTagDecl(out decl) && !b.Class.Ignore))
{
property = baseClassSpecifier.Class.GetPropertyByName(propertyName);
if (property != null)
return property;
}
return null;
}
public Property GetPropertyByConstituentMethod(Method method)
{
var property = Properties.FirstOrDefault(p => p.GetMethod == method);
if (property != null)
return property;
property = Properties.FirstOrDefault(p => p.SetMethod == method);
if (property != null)
return property;
Declaration decl;
foreach (BaseClassSpecifier @base in Bases.Where(b => b.Type.IsTagDecl(out decl)))
{
property = @base.Class.GetPropertyByConstituentMethod(method);
if (property != null)
return property;
}
return null;
}
public Method GetMethodByName(string methodName)
{
var method = Methods.FirstOrDefault(
// HACK: because of the non-shared v-table entries bug one copy may have been renamed and the other not
m => string.Compare(m.Name, methodName, StringComparison.OrdinalIgnoreCase) == 0);
if (method != null)
return method;
Declaration decl;
foreach (BaseClassSpecifier @base in Bases.Where(b => b.Type.IsTagDecl(out decl)))
{
method = @base.Class.GetMethodByName(methodName);
if (method != null)
return method;
}
return null;
}
public override T Visit<T>(IDeclVisitor<T> visitor)
{
return visitor.VisitClassDecl(this);
}
}
}