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.
 
 
 
 
 

588 lines
17 KiB

using System;
using System.Collections.Generic;
namespace CppSharp.AST
{
public interface IAstVisited
{
ISet<object> Visited { get; }
bool AlreadyVisited(Declaration decl);
bool AlreadyVisited(Type type);
}
public interface IAstVisitor<out T> : ITypeVisitor<T>, IDeclVisitor<T>
{
}
public class AstVisitorOptions
{
public bool VisitDeclaration = true;
public bool VisitClassBases = true;
public bool VisitClassFields = true;
public bool VisitClassProperties = true;
public bool VisitClassMethods = true;
public bool VisitNamespaceEnums = true;
public bool VisitNamespaceTemplates = true;
public bool VisitNamespaceTypedefs = true;
public bool VisitNamespaceEvents = true;
public bool VisitNamespaceVariables = true;
public bool VisitFunctionReturnType = true;
public bool VisitFunctionParameters = true;
public bool VisitEventParameters = true;
public bool VisitTemplateArguments = true;
}
/// <summary>
/// Base class for AST visitors.
/// You can override the methods to customize the behaviour, by default
/// this will visit all the nodes in a default way that should be useful
/// for a lot of applications.
/// </summary>
public abstract class AstVisitor : IAstVisitor<bool>, IAstVisited
{
public ISet<object> Visited { get; private set; }
public AstVisitorOptions VisitOptions { get; private set; }
protected AstVisitor()
{
Visited = new HashSet<object>();
VisitOptions = new AstVisitorOptions();
}
public bool AlreadyVisited(Type type)
{
return !Visited.Add(type);
}
public bool AlreadyVisited(Declaration decl)
{
return !Visited.Add(decl);
}
#region Type Visitors
public virtual bool VisitType(Type type, TypeQualifiers quals)
{
return true;
}
public virtual bool VisitTagType(TagType tag, TypeQualifiers quals)
{
if (!VisitType(tag, quals))
return false;
return tag.Declaration.Visit(this);
}
public virtual bool VisitArrayType(ArrayType array, TypeQualifiers quals)
{
if (!VisitType(array, quals))
return false;
// FIXME: Remove this once array dependent types are processed.
if (array.SizeType == ArrayType.ArraySize.Dependent)
return false;
return array.QualifiedType.Visit(this);
}
public virtual bool VisitFunctionType(FunctionType function, TypeQualifiers quals)
{
if (!VisitType(function, quals))
return false;
if (function.ReturnType.Type != null)
function.ReturnType.Visit(this);
if (VisitOptions.VisitFunctionParameters)
foreach (var param in function.Parameters)
param.Visit(this);
return true;
}
public virtual bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
{
if (!VisitType(pointer, quals))
return false;
if (pointer.Pointee == null)
return false;
return pointer.Pointee.Visit(this, quals);
}
public virtual bool VisitMemberPointerType(MemberPointerType member,
TypeQualifiers quals)
{
if (!VisitType(member, quals))
return false;
return member.QualifiedPointee.Visit(this);
}
public virtual bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals)
{
if (!VisitType(builtin, quals))
return false;
return VisitPrimitiveType(builtin.Type, quals);
}
public virtual bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
{
if (!VisitType(typedef, quals))
return false;
return typedef.Declaration.Visit(this);
}
public bool VisitAttributedType(AttributedType attributed, TypeQualifiers quals)
{
if (!VisitType(attributed, quals))
return false;
return attributed.Modified.Visit(this);
}
public virtual bool VisitDecayedType(DecayedType decayed, TypeQualifiers quals)
{
if (!VisitType(decayed, quals))
return false;
return decayed.Decayed.Visit(this);
}
public virtual bool VisitTemplateSpecializationType(TemplateSpecializationType template,
TypeQualifiers quals)
{
if (!VisitType(template, quals))
return false;
if (VisitOptions.VisitTemplateArguments)
{
foreach (var arg in template.Arguments)
{
switch (arg.Kind)
{
case TemplateArgument.ArgumentKind.Type:
var type = arg.Type.Type;
if (type != null)
type.Visit(this, arg.Type.Qualifiers);
break;
case TemplateArgument.ArgumentKind.Declaration:
arg.Declaration.Visit(this);
break;
}
}
}
if (template.IsDependent)
return template.Template.Visit(this);
var specialization = template.GetClassTemplateSpecialization();
return specialization != null && specialization.Visit(this);
}
public bool VisitDependentTemplateSpecializationType(
DependentTemplateSpecializationType template, TypeQualifiers quals)
{
if (!VisitType(template, quals))
return false;
if (VisitOptions.VisitTemplateArguments)
{
foreach (var arg in template.Arguments)
{
switch (arg.Kind)
{
case TemplateArgument.ArgumentKind.Type:
var type = arg.Type.Type;
if (type != null)
type.Visit(this, arg.Type.Qualifiers);
break;
case TemplateArgument.ArgumentKind.Declaration:
arg.Declaration.Visit(this);
break;
}
}
}
if (template.Desugared.Type != null)
return template.Desugared.Visit(this);
return false;
}
public virtual bool VisitTemplateParameterType(TemplateParameterType param,
TypeQualifiers quals)
{
return VisitType(param, quals);
}
public virtual bool VisitTemplateParameterSubstitutionType(
TemplateParameterSubstitutionType param, TypeQualifiers quals)
{
if (!VisitType(param, quals))
return false;
return param.Replacement.Type.Visit(this, quals);
}
public virtual bool VisitInjectedClassNameType(InjectedClassNameType injected,
TypeQualifiers quals)
{
if (!VisitType(injected, quals))
return false;
return true;
}
public virtual bool VisitDependentNameType(DependentNameType dependent,
TypeQualifiers quals)
{
if (!VisitType(dependent, quals))
return false;
return true;
}
public bool VisitPackExpansionType(PackExpansionType packExpansionType, TypeQualifiers quals)
{
return true;
}
public bool VisitUnaryTransformType(UnaryTransformType unaryTransformType, TypeQualifiers quals)
{
return true;
}
public bool VisitVectorType(VectorType vectorType, TypeQualifiers quals)
{
return true;
}
public virtual bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals)
{
return true;
}
public virtual bool VisitCILType(CILType type, TypeQualifiers quals)
{
if (!VisitType(type, quals))
return false;
return true;
}
#endregion
#region Decl Visitors
public virtual bool VisitDeclaration(Declaration decl, TypeQualifiers quals)
{
return VisitDeclaration(decl);
}
public virtual bool VisitDeclaration(Declaration decl)
{
return !AlreadyVisited(decl);
}
public virtual bool VisitClassDecl(Class @class)
{
if (!VisitDeclarationContext(@class))
return false;
if (VisitOptions.VisitClassBases)
foreach (var baseClass in @class.Bases)
if (baseClass.IsClass)
baseClass.Class.Visit(this);
if (VisitOptions.VisitClassFields)
foreach (var field in @class.Fields)
VisitFieldDecl(field);
if (VisitOptions.VisitClassProperties)
foreach (var property in @class.Properties)
VisitProperty(property);
if (VisitOptions.VisitClassMethods)
{
var methods = @class.Methods.ToArray();
foreach (var method in methods)
VisitMethodDecl(method);
}
return true;
}
public virtual bool VisitFieldDecl(Field field)
{
if (!VisitDeclaration(field))
return false;
return field.Type.Visit(this, field.QualifiedType.Qualifiers);
}
public virtual bool VisitProperty(Property property)
{
if (!VisitDeclaration(property))
return false;
if (VisitOptions.VisitFunctionReturnType)
return property.Type.Visit(this);
return true;
}
public bool VisitFriend(Friend friend)
{
if (!VisitDeclaration(friend))
return false;
return friend.Declaration.Visit(this);
}
public virtual bool VisitFunctionDecl(Function function)
{
if (!VisitDeclaration(function))
return false;
var retType = function.ReturnType;
if (VisitOptions.VisitFunctionReturnType && retType.Type != null)
retType.Type.Visit(this, retType.Qualifiers);
if (VisitOptions.VisitFunctionParameters)
foreach (var param in function.Parameters)
param.Visit(this);
return true;
}
public virtual bool VisitMethodDecl(Method method)
{
return VisitFunctionDecl(method);
}
public virtual bool VisitParameterDecl(Parameter parameter)
{
if (!VisitDeclaration(parameter))
return false;
return parameter.Type.Visit(this, parameter.QualifiedType.Qualifiers);
}
public virtual bool VisitTypedefDecl(TypedefDecl typedef)
{
if (!VisitDeclaration(typedef))
return false;
if (typedef.Type == null)
return false;
return typedef.Type.Visit(this, typedef.QualifiedType.Qualifiers);
}
public bool VisitTypeAliasDecl(TypeAlias typeAlias)
{
if (!VisitDeclaration(typeAlias))
return false;
if (typeAlias.Type == null)
return false;
return typeAlias.Type.Visit(this, typeAlias.QualifiedType.Qualifiers);
}
public virtual bool VisitEnumDecl(Enumeration @enum)
{
if (!VisitDeclaration(@enum))
return false;
foreach (var item in @enum.Items)
VisitEnumItemDecl(item);
return true;
}
public virtual bool VisitVariableDecl(Variable variable)
{
if (!VisitDeclaration(variable))
return false;
return variable.Type.Visit(this, variable.QualifiedType.Qualifiers);
}
public virtual bool VisitEnumItemDecl(Enumeration.Item item)
{
return true;
}
public virtual bool VisitTypeAliasTemplateDecl(TypeAliasTemplate template)
{
if (!VisitDeclaration(template))
return false;
foreach (var templateParameter in template.Parameters)
templateParameter.Visit(this);
return true;
}
public virtual bool VisitClassTemplateDecl(ClassTemplate template)
{
if (!VisitDeclaration(template))
return false;
foreach (var templateParameter in template.Parameters)
templateParameter.Visit(this);
foreach (var specialization in template.Specializations)
specialization.Visit(this);
template.TemplatedClass.Visit(this);
return true;
}
public virtual bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization)
{
return VisitClassDecl(specialization);
}
public virtual bool VisitFunctionTemplateDecl(FunctionTemplate template)
{
if (!VisitDeclaration(template))
return false;
foreach (var templateParameter in template.Parameters)
templateParameter.Visit(this);
foreach (var specialization in template.Specializations)
specialization.Visit(this);
template.TemplatedFunction.Visit(this);
return true;
}
public virtual bool VisitFunctionTemplateSpecializationDecl(FunctionTemplateSpecialization specialization)
{
return specialization.SpecializedFunction.Visit(this);
}
public bool VisitVarTemplateDecl(VarTemplate template)
{
if (!VisitDeclaration(template))
return false;
foreach (var templateParameter in template.Parameters)
templateParameter.Visit(this);
foreach (var specialization in template.Specializations)
specialization.Visit(this);
template.TemplatedVariable.Visit(this);
return true;
}
public bool VisitVarTemplateSpecializationDecl(VarTemplateSpecialization specialization)
{
return VisitVariableDecl(specialization);
}
public virtual bool VisitMacroDefinition(MacroDefinition macro)
{
return false;
}
public virtual bool VisitNamespace(Namespace @namespace)
{
return VisitDeclarationContext(@namespace);
}
public virtual bool VisitDeclarationContext(DeclarationContext context)
{
if (!VisitDeclaration(context))
return false;
foreach (var decl in context.Classes)
decl.Visit(this);
foreach (var decl in context.Functions)
decl.Visit(this);
if (VisitOptions.VisitNamespaceEnums)
foreach (var decl in context.Enums)
decl.Visit(this);
if (VisitOptions.VisitNamespaceTemplates)
foreach (var decl in context.Templates)
decl.Visit(this);
if (VisitOptions.VisitNamespaceTypedefs)
foreach (var decl in context.Typedefs)
decl.Visit(this);
if (VisitOptions.VisitNamespaceVariables)
foreach (var decl in context.Variables)
decl.Visit(this);
if (VisitOptions.VisitNamespaceEvents)
foreach (var decl in context.Events)
decl.Visit(this);
foreach (var decl in context.Namespaces)
decl.Visit(this);
return true;
}
public virtual bool VisitEvent(Event @event)
{
if (!VisitDeclaration(@event))
return false;
if (VisitOptions.VisitEventParameters)
foreach (var param in @event.Parameters)
param.Visit(this);
return true;
}
public bool VisitTemplateTemplateParameterDecl(TemplateTemplateParameter templateTemplateParameter)
{
if (!VisitDeclaration(templateTemplateParameter))
return false;
foreach (var templateParameter in templateTemplateParameter.Parameters)
templateParameter.Visit(this);
return true;
}
public virtual bool VisitTemplateParameterDecl(TypeTemplateParameter templateParameter)
{
if (!VisitDeclaration(templateParameter))
return false;
return true;
}
public bool VisitNonTypeTemplateParameterDecl(NonTypeTemplateParameter nonTypeTemplateParameter)
{
if (!VisitDeclaration(nonTypeTemplateParameter))
return false;
return true;
}
#endregion
}
}