mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
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.
414 lines
12 KiB
414 lines
12 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
|
|
namespace CppSharp.AST |
|
{ |
|
public interface IRedeclarableDecl |
|
{ |
|
Declaration PreviousDecl { get; } |
|
} |
|
|
|
public interface ITypedDecl |
|
{ |
|
Type Type { get; } |
|
QualifiedType QualifiedType { get; } |
|
} |
|
|
|
public interface INamedDecl |
|
{ |
|
string Name { get; set; } |
|
} |
|
|
|
public interface IMangledDecl |
|
{ |
|
string Mangled { get; set; } |
|
} |
|
|
|
/// <summary> |
|
/// Kind of the generated declaration |
|
/// </summary> |
|
public enum GenerationKind |
|
{ |
|
/// <summary> |
|
/// Declaration is not generated. |
|
/// </summary> |
|
None, |
|
/// <summary> |
|
/// Declaration is generated. |
|
/// </summary> |
|
Generate, |
|
/// <summary> |
|
/// Declaration is generated to be used internally. |
|
/// </summary> |
|
Internal |
|
} |
|
|
|
/// <summary> |
|
/// Represents a C++ declaration. |
|
/// </summary> |
|
public abstract class Declaration : INamedDecl |
|
{ |
|
public SourceLocation Location; |
|
|
|
public int LineNumberStart { get; set; } |
|
public int LineNumberEnd { get; set; } |
|
public bool IsImplicit { get; set; } |
|
|
|
private DeclarationContext @namespace; |
|
public DeclarationContext OriginalNamespace; |
|
|
|
// Namespace the declaration is contained in. |
|
public DeclarationContext Namespace |
|
{ |
|
get { return @namespace; } |
|
set |
|
{ |
|
@namespace = value; |
|
if (OriginalNamespace == null) |
|
OriginalNamespace = @namespace; |
|
} |
|
} |
|
|
|
public TranslationUnit TranslationUnit |
|
{ |
|
get |
|
{ |
|
if (this is TranslationUnit) |
|
return this as TranslationUnit; |
|
return Namespace.TranslationUnit; |
|
} |
|
} |
|
|
|
public virtual string OriginalName { get; set; } |
|
|
|
// Name of the declaration. |
|
private string name; |
|
|
|
public virtual string Name |
|
{ |
|
get { return name; } |
|
set |
|
{ |
|
name = value; |
|
if (OriginalName == null) |
|
OriginalName = name; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// The effective name of a declaration is the logical name |
|
/// for the declaration. We need this to make the distiction between |
|
/// the real and the "effective" name of the declaration to properly |
|
/// support things like inline namespaces when handling type maps. |
|
/// </summary> |
|
public virtual string LogicalName |
|
{ |
|
get { return Name; } |
|
} |
|
|
|
/// <summary> |
|
/// The effective original name of a declaration is the logical |
|
/// original name for the declaration. |
|
/// </summary> |
|
public virtual string LogicalOriginalName |
|
{ |
|
get { return OriginalName; } |
|
} |
|
|
|
public string GetQualifiedName(Func<Declaration, string> getName, |
|
Func<Declaration, DeclarationContext> getNamespace) |
|
{ |
|
if (Namespace == null) |
|
return getName(this); |
|
|
|
if (Namespace.IsRoot) |
|
return getName(this); |
|
|
|
var namespaces = GatherNamespaces(getNamespace(this)); |
|
namespaces.Reverse(); |
|
|
|
var names = namespaces.Select(getName).ToList(); |
|
names.Add(getName(this)); |
|
names = names.Where(s => !string.IsNullOrWhiteSpace(s)).ToList(); |
|
|
|
return string.Join("::", names); |
|
} |
|
|
|
private List<Declaration> GatherNamespaces(DeclarationContext @namespace) |
|
{ |
|
var namespaces = new List<Declaration>(); |
|
|
|
var currentNamespace = @namespace; |
|
while (currentNamespace != null) |
|
{ |
|
namespaces.Add(currentNamespace); |
|
currentNamespace = currentNamespace.Namespace; |
|
} |
|
|
|
return namespaces; |
|
} |
|
|
|
public string QualifiedName |
|
{ |
|
get |
|
{ |
|
return GetQualifiedName(decl => decl.Name, decl => decl.Namespace); |
|
} |
|
} |
|
|
|
public string QualifiedOriginalName |
|
{ |
|
get |
|
{ |
|
return GetQualifiedName( |
|
decl => decl.OriginalName, decl => decl.OriginalNamespace); |
|
} |
|
} |
|
|
|
public string QualifiedLogicalName |
|
{ |
|
get |
|
{ |
|
return GetQualifiedName( |
|
decl => decl.LogicalName, decl => decl.Namespace); |
|
} |
|
} |
|
|
|
public string QualifiedLogicalOriginalName |
|
{ |
|
get |
|
{ |
|
return GetQualifiedName( |
|
decl => decl.LogicalOriginalName, decl => decl.OriginalNamespace); |
|
} |
|
} |
|
|
|
// Comment associated with declaration. |
|
public RawComment Comment; |
|
|
|
private GenerationKind? generationKind; |
|
|
|
public GenerationKind GenerationKind |
|
{ |
|
get |
|
{ |
|
if (generationKind.HasValue) |
|
return generationKind.Value; |
|
|
|
if (Namespace != null) |
|
// fields in nested classes have to always be generated |
|
return !Namespace.IsGenerated && this is Field ? GenerationKind.Internal : Namespace.GenerationKind; |
|
|
|
return GenerationKind.Generate; |
|
} |
|
set { generationKind = value; } |
|
} |
|
|
|
/// <summary> |
|
/// Whether the declaration should be generated. |
|
/// </summary> |
|
public virtual bool IsGenerated |
|
{ |
|
get |
|
{ |
|
return GenerationKind == GenerationKind.Generate; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Whether the declaration was explicitly set to be generated via |
|
/// the GenerationKind propery as opposed to the default generated state. |
|
/// </summary> |
|
public virtual bool IsExplicitlyGenerated |
|
{ |
|
get |
|
{ |
|
return generationKind.HasValue && generationKind.Value == GenerationKind.Generate; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Whether the declaration internal bindings should be generated. |
|
/// </summary> |
|
public bool IsInternal |
|
{ |
|
get |
|
{ |
|
return GenerationKind == GenerationKind.Internal; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Whether a binded version of this declaration is available. |
|
/// </summary> |
|
public bool IsDeclared |
|
{ |
|
get |
|
{ |
|
var k = GenerationKind; |
|
return k == GenerationKind.Generate |
|
|| k == GenerationKind.Internal; |
|
} |
|
} |
|
|
|
public void ExplicitlyIgnore() |
|
{ |
|
GenerationKind = GenerationKind.None; |
|
} |
|
|
|
[Obsolete("Replace set by ExplicitlyIgnore(). Replace get by GenerationKind == GenerationKind.None.")] |
|
public bool ExplicityIgnored |
|
{ |
|
get { return GenerationKind == GenerationKind.None; } |
|
set { if (value) ExplicitlyIgnore(); } |
|
} |
|
|
|
public virtual bool Ignore |
|
{ |
|
get { return GenerationKind == GenerationKind.None; } |
|
set { if (value) ExplicitlyIgnore(); } |
|
} |
|
|
|
public AccessSpecifier Access { get; set; } |
|
|
|
// Contains debug text about the declaration. |
|
public string DebugText; |
|
|
|
// True if the declaration is incomplete (no definition). |
|
public bool IsIncomplete; |
|
|
|
// True if the declaration is dependent. |
|
public bool IsDependent; |
|
|
|
// Keeps a reference to the complete version of this declaration. |
|
public Declaration CompleteDeclaration; |
|
|
|
// Tracks the original declaration definition order. |
|
public uint DefinitionOrder; |
|
|
|
// Passes that should not be run on this declaration. |
|
public ISet<System.Type> ExcludeFromPasses; |
|
|
|
// List of preprocessed entities attached to this declaration. |
|
public IList<PreprocessedEntity> PreprocessedEntities; |
|
|
|
// Pointer to the original declaration from Clang. |
|
public IntPtr OriginalPtr; |
|
|
|
// The Unified Symbol Resolution (USR) for the declaration. |
|
// A Unified Symbol Resolution (USR) is a string that identifies a |
|
// particular entity (function, class, variable, etc.) within a program. |
|
// USRs can be compared across translation units to determine, e.g., |
|
// when references in one translation refer to an entity defined in |
|
// another translation unit. |
|
public string USR; |
|
|
|
public List<Attribute> Attributes { get; private set; } |
|
|
|
protected Declaration() |
|
{ |
|
Access = AccessSpecifier.Public; |
|
ExcludeFromPasses = new HashSet<System.Type>(); |
|
PreprocessedEntities = new List<PreprocessedEntity>(); |
|
Attributes = new List<Attribute>(); |
|
} |
|
|
|
protected Declaration(string name) |
|
: this() |
|
{ |
|
this.name = name; |
|
} |
|
|
|
protected Declaration(Declaration declaration) |
|
: this() |
|
{ |
|
Namespace = declaration.Namespace; |
|
OriginalNamespace = declaration.OriginalNamespace; |
|
OriginalName = declaration.OriginalName; |
|
name = declaration.Name; |
|
Comment = declaration.Comment; |
|
generationKind = declaration.generationKind; |
|
Access = declaration.Access; |
|
DebugText = declaration.DebugText; |
|
IsIncomplete = declaration.IsIncomplete; |
|
IsDependent = declaration.IsDependent; |
|
CompleteDeclaration = declaration.CompleteDeclaration; |
|
DefinitionOrder = declaration.DefinitionOrder; |
|
ExcludeFromPasses = new HashSet<System.Type>( |
|
declaration.ExcludeFromPasses); |
|
PreprocessedEntities = new List<PreprocessedEntity>( |
|
declaration.PreprocessedEntities); |
|
OriginalPtr = declaration.OriginalPtr; |
|
LineNumberStart = declaration.LineNumberStart; |
|
LineNumberEnd = declaration.LineNumberEnd; |
|
IsImplicit = declaration.IsImplicit; |
|
} |
|
|
|
public override string ToString() |
|
{ |
|
return OriginalName; |
|
} |
|
|
|
public abstract T Visit<T>(IDeclVisitor<T> visitor); |
|
} |
|
|
|
/// <summary> |
|
/// Base class for declarations which introduce a typedef-name. |
|
/// </summary> |
|
public abstract class TypedefNameDecl : Declaration, ITypedDecl |
|
{ |
|
public Type Type { get { return QualifiedType.Type; } } |
|
public QualifiedType QualifiedType { get; set; } |
|
public bool IsSynthetized { get; set; } |
|
} |
|
|
|
/// <summary> |
|
/// Represents a type definition in C++. |
|
/// </summary> |
|
public class TypedefDecl : TypedefNameDecl |
|
{ |
|
public override T Visit<T>(IDeclVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTypedefDecl(this); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Represents a type alias in C++. |
|
/// </summary> |
|
public class TypeAlias : TypedefNameDecl |
|
{ |
|
public TypeAliasTemplate DescribedAliasTemplate { get; set; } |
|
|
|
public override T Visit<T>(IDeclVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTypeAliasDecl(this); |
|
} |
|
} |
|
|
|
public interface IDeclVisitor<out T> |
|
{ |
|
T VisitDeclaration(Declaration decl); |
|
T VisitClassDecl(Class @class); |
|
T VisitFieldDecl(Field field); |
|
T VisitFunctionDecl(Function function); |
|
T VisitMethodDecl(Method method); |
|
T VisitParameterDecl(Parameter parameter); |
|
T VisitTypedefDecl(TypedefDecl typedef); |
|
T VisitTypeAliasDecl(TypeAlias typeAlias); |
|
T VisitEnumDecl(Enumeration @enum); |
|
T VisitVariableDecl(Variable variable); |
|
T VisitClassTemplateDecl(ClassTemplate template); |
|
T VisitFunctionTemplateDecl(FunctionTemplate template); |
|
T VisitMacroDefinition(MacroDefinition macro); |
|
T VisitNamespace(Namespace @namespace); |
|
T VisitEvent(Event @event); |
|
T VisitProperty(Property @property); |
|
T VisitFriend(Friend friend); |
|
T VisitTemplateTemplateParameterDecl(TemplateTemplateParameter templateTemplateParameter); |
|
T VisitTemplateParameterDecl(TypeTemplateParameter templateParameter); |
|
T VisitNonTypeTemplateParameterDecl(NonTypeTemplateParameter nonTypeTemplateParameter); |
|
T VisitTypeAliasTemplateDecl(TypeAliasTemplate typeAliasTemplate); |
|
} |
|
}
|
|
|