use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
C,
Cpp,
ObjectiveC,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Identifier(String);
impl Identifier {
pub fn new(value: impl Into<String>) -> Option<Self> {
let value = value.into();
let mut chars = value.chars();
let first = chars.next()?;
if !(first == '_' || first.is_ascii_alphabetic())
|| !chars.all(|ch| ch == '_' || ch.is_ascii_alphanumeric())
{
return None;
}
Some(Self(value))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for Identifier {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IdentifierPath(Vec<Identifier>);
impl IdentifierPath {
pub fn new(values: Vec<Identifier>) -> Option<Self> {
(!values.is_empty()).then_some(Self(values))
}
pub fn parse(value: &str) -> Option<Self> {
let values = value
.trim()
.trim_start_matches("::")
.split("::")
.map(str::trim)
.map(Identifier::new)
.collect::<Option<Vec<_>>>()?;
Self::new(values)
}
pub fn components(&self) -> &[Identifier] {
&self.0
}
pub fn last(&self) -> &Identifier {
self.0.last().expect("IdentifierPath is non-empty")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BuiltinType {
Void,
Bool,
Char,
SignedChar,
UnsignedChar,
Short,
UnsignedShort,
Int,
UnsignedInt,
Long,
UnsignedLong,
LongLong,
UnsignedLongLong,
Int128,
UnsignedInt128,
Float,
Double,
LongDouble,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NamedTypeTag {
Typedef,
Struct,
Union,
Enum,
Class,
Protocol,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct TypeQualifiers {
pub is_const: bool,
pub is_volatile: bool,
pub is_restrict: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ReferenceKind {
Lvalue,
Rvalue,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParameterState {
Unspecified,
Known,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CallingConvention {
C,
Swift,
ObjectiveCMethod,
Thiscall,
Vectorcall,
Aapcs,
AapcsVfp,
Unknown,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct FunctionQualifiers {
pub is_const: bool,
pub is_volatile: bool,
pub reference: Option<ReferenceKind>,
pub noexcept: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TemplateArgument {
Type(Type),
Integer(i64),
Identifier(IdentifierPath),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Parameter {
pub name: Identifier,
pub ty: Type,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Type {
Builtin(BuiltinType),
Named {
tag: NamedTypeTag,
path: IdentifierPath,
template_arguments: Vec<TemplateArgument>,
},
Pointer {
pointee: Box<Type>,
qualifiers: TypeQualifiers,
},
Reference {
target: Box<Type>,
kind: ReferenceKind,
},
Array {
element: Box<Type>,
count: Option<u64>,
},
Function {
return_type: Box<Type>,
parameters: Vec<Parameter>,
parameter_state: ParameterState,
variadic: bool,
calling_convention: CallingConvention,
qualifiers: FunctionQualifiers,
},
ObjectiveCObject {
name: Option<Identifier>,
protocols: Vec<Identifier>,
qualifiers: TypeQualifiers,
},
ObjectiveCBlock(Box<Type>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StorageClass {
None,
Extern,
Static,
ThreadLocal,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Linkage {
C,
Cpp,
ObjectiveC,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RecordKind {
Struct,
Union,
Class,
Enum,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Access {
Public,
Protected,
Private,
Unspecified,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Base {
pub ty: Type,
pub access: Access,
pub is_virtual: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Field {
pub name: Identifier,
pub ty: Type,
pub offset: Option<u64>,
pub bit_width: Option<u32>,
pub access: Access,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MethodKind {
Instance,
Class,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ObjectiveCMethod {
pub kind: MethodKind,
pub selector: String,
pub return_type: Type,
pub parameters: Vec<Parameter>,
pub required: Option<bool>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ObjectiveCAccess {
Public,
Protected,
Private,
Package,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ObjectiveCIvar {
pub name: Identifier,
pub ty: Type,
pub access: ObjectiveCAccess,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ObjectiveCPropertyAttribute {
Readonly,
Readwrite,
Copy,
Retain,
Strong,
Weak,
Assign,
Atomic,
Nonatomic,
Dynamic,
Class,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ObjectiveCProperty {
pub name: Identifier,
pub ty: Type,
pub attributes: Vec<ObjectiveCPropertyAttribute>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ObjectiveCForwardKind {
Class,
Protocol,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Decl {
Function {
name: Identifier,
signature: Type,
storage: StorageClass,
linkage: Linkage,
},
Variable {
name: Identifier,
ty: Type,
storage: StorageClass,
linkage: Linkage,
},
Record {
kind: RecordKind,
path: IdentifierPath,
bases: Vec<Base>,
fields: Vec<Field>,
members: Vec<Decl>,
},
Forward {
kind: RecordKind,
path: IdentifierPath,
},
Alias {
path: IdentifierPath,
target: Type,
},
ObjectiveCInterface {
name: Identifier,
superclass: Option<Identifier>,
protocols: Vec<Identifier>,
ivars: Vec<ObjectiveCIvar>,
methods: Vec<ObjectiveCMethod>,
properties: Vec<ObjectiveCProperty>,
},
ObjectiveCCategory {
name: Identifier,
extended_class: Identifier,
protocols: Vec<Identifier>,
methods: Vec<ObjectiveCMethod>,
properties: Vec<ObjectiveCProperty>,
},
ObjectiveCProtocol {
name: Identifier,
protocols: Vec<Identifier>,
methods: Vec<ObjectiveCMethod>,
properties: Vec<ObjectiveCProperty>,
},
ObjectiveCForward {
kind: ObjectiveCForwardKind,
names: Vec<Identifier>,
},
}
impl Decl {
pub fn name(&self) -> Option<&Identifier> {
match self {
Self::Function { name, .. }
| Self::Variable { name, .. }
| Self::ObjectiveCInterface { name, .. }
| Self::ObjectiveCCategory { name, .. }
| Self::ObjectiveCProtocol { name, .. } => Some(name),
Self::Record { path, .. } | Self::Forward { path, .. } | Self::Alias { path, .. } => {
Some(path.last())
}
Self::ObjectiveCForward { .. } => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TranslationUnit {
pub language: Language,
pub declarations: Vec<Decl>,
pub declaration_spans: Vec<crate::SourceSpan>,
}