#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]
#![allow(non_upper_case_globals, clippy::result_unit_err)]
extern crate clang_sys;
extern crate libc;
#[macro_use]
mod utility;
pub mod completion;
pub mod diagnostic;
pub mod documentation;
pub mod source;
pub mod token;
pub mod sonar;
use std::cmp;
use std::fmt;
use std::hash;
use std::mem;
use std::ptr;
use std::slice;
use std::collections::{HashMap};
use std::convert::TryInto;
use std::ffi::{CString};
use std::marker::{PhantomData};
use std::path::{Path, PathBuf};
use std::sync::atomic::{self, AtomicBool};
use clang_sys::*;
use libc::{c_int, c_uint, c_ulong};
use completion::{Completer, CompletionString};
use diagnostic::{Diagnostic};
use documentation::{Comment};
use source::{File, Module, SourceLocation, SourceRange};
use token::{Token};
use utility::{FromError, Nullable};
mod error;
pub use self::error::*;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Accessibility {
Private = 3,
Protected = 2,
Public = 1,
}
impl Accessibility {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=3 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Availability {
Available = 0,
Deprecated = 1,
Inaccessible = 3,
Unavailable = 2,
}
impl Availability {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
0..=3 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum CallingConvention {
Unexposed = 200,
Cdecl = 1,
Fastcall = 3,
Pascal = 5,
Stdcall = 2,
Thiscall = 4,
Vectorcall = 12,
Swift = 13,
PreserveMost = 14,
PreserveAll = 15,
Aapcs = 6,
AapcsVfp = 7,
IntelOcl = 9,
RegCall = 8,
SysV64 = 11,
Win64 = 10,
}
impl CallingConvention {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=15 | 200 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum EntityKind {
UnexposedDecl = 1,
StructDecl = 2,
UnionDecl = 3,
ClassDecl = 4,
EnumDecl = 5,
FieldDecl = 6,
EnumConstantDecl = 7,
FunctionDecl = 8,
VarDecl = 9,
ParmDecl = 10,
ObjCInterfaceDecl = 11,
ObjCCategoryDecl = 12,
ObjCProtocolDecl = 13,
ObjCPropertyDecl = 14,
ObjCIvarDecl = 15,
ObjCInstanceMethodDecl = 16,
ObjCClassMethodDecl = 17,
ObjCImplementationDecl = 18,
ObjCCategoryImplDecl = 19,
TypedefDecl = 20,
Method = 21,
Namespace = 22,
LinkageSpec = 23,
Constructor = 24,
Destructor = 25,
ConversionFunction = 26,
TemplateTypeParameter = 27,
NonTypeTemplateParameter = 28,
TemplateTemplateParameter = 29,
FunctionTemplate = 30,
ClassTemplate = 31,
ClassTemplatePartialSpecialization = 32,
NamespaceAlias = 33,
UsingDirective = 34,
UsingDeclaration = 35,
TypeAliasDecl = 36,
ObjCSynthesizeDecl = 37,
ObjCDynamicDecl = 38,
AccessSpecifier = 39,
ObjCSuperClassRef = 40,
ObjCProtocolRef = 41,
ObjCClassRef = 42,
TypeRef = 43,
BaseSpecifier = 44,
TemplateRef = 45,
NamespaceRef = 46,
MemberRef = 47,
LabelRef = 48,
OverloadedDeclRef = 49,
VariableRef = 50,
InvalidFile = 70,
InvalidDecl = 71,
NotImplemented = 72,
InvalidCode = 73,
UnexposedExpr = 100,
DeclRefExpr = 101,
MemberRefExpr = 102,
CallExpr = 103,
ObjCMessageExpr = 104,
BlockExpr = 105,
IntegerLiteral = 106,
FloatingLiteral = 107,
ImaginaryLiteral = 108,
StringLiteral = 109,
CharacterLiteral = 110,
ParenExpr = 111,
UnaryOperator = 112,
ArraySubscriptExpr = 113,
BinaryOperator = 114,
CompoundAssignOperator = 115,
ConditionalOperator = 116,
CStyleCastExpr = 117,
CompoundLiteralExpr = 118,
InitListExpr = 119,
AddrLabelExpr = 120,
StmtExpr = 121,
GenericSelectionExpr = 122,
GNUNullExpr = 123,
StaticCastExpr = 124,
DynamicCastExpr = 125,
ReinterpretCastExpr = 126,
ConstCastExpr = 127,
FunctionalCastExpr = 128,
TypeidExpr = 129,
BoolLiteralExpr = 130,
NullPtrLiteralExpr = 131,
ThisExpr = 132,
ThrowExpr = 133,
NewExpr = 134,
DeleteExpr = 135,
UnaryExpr = 136,
ObjCStringLiteral = 137,
ObjCEncodeExpr = 138,
ObjCSelectorExpr = 139,
ObjCProtocolExpr = 140,
ObjCBridgedCastExpr = 141,
PackExpansionExpr = 142,
SizeOfPackExpr = 143,
LambdaExpr = 144,
ObjCBoolLiteralExpr = 145,
ObjCSelfExpr = 146,
OmpArraySectionExpr = 147,
ObjCAvailabilityCheckExpr = 148,
FixedPointLiteral = 149,
UnexposedStmt = 200,
LabelStmt = 201,
CompoundStmt = 202,
CaseStmt = 203,
DefaultStmt = 204,
IfStmt = 205,
SwitchStmt = 206,
WhileStmt = 207,
DoStmt = 208,
ForStmt = 209,
GotoStmt = 210,
IndirectGotoStmt = 211,
ContinueStmt = 212,
BreakStmt = 213,
ReturnStmt = 214,
AsmStmt = 215,
ObjCAtTryStmt = 216,
ObjCAtCatchStmt = 217,
ObjCAtFinallyStmt = 218,
ObjCAtThrowStmt = 219,
ObjCAtSynchronizedStmt = 220,
ObjCAutoreleasePoolStmt = 221,
ObjCForCollectionStmt = 222,
CatchStmt = 223,
TryStmt = 224,
ForRangeStmt = 225,
SehTryStmt = 226,
SehExceptStmt = 227,
SehFinallyStmt = 228,
SehLeaveStmt = 247,
MsAsmStmt = 229,
NullStmt = 230,
DeclStmt = 231,
OmpParallelDirective = 232,
OmpSimdDirective = 233,
OmpForDirective = 234,
OmpSectionsDirective = 235,
OmpSectionDirective = 236,
OmpSingleDirective = 237,
OmpParallelForDirective = 238,
OmpParallelSectionsDirective = 239,
OmpTaskDirective = 240,
OmpMasterDirective = 241,
OmpCriticalDirective = 242,
OmpTaskyieldDirective = 243,
OmpBarrierDirective = 244,
OmpTaskwaitDirective = 245,
OmpFlushDirective = 246,
OmpOrderedDirective = 248,
OmpAtomicDirective = 249,
OmpForSimdDirective = 250,
OmpParallelForSimdDirective = 251,
OmpTargetDirective = 252,
OmpTeamsDirective = 253,
OmpTaskgroupDirective = 254,
OmpCancellationPointDirective = 255,
OmpCancelDirective = 256,
OmpTargetDataDirective = 257,
OmpTaskLoopDirective = 258,
OmpTaskLoopSimdDirective = 259,
OmpDistributeDirective = 260,
OmpTargetEnterDataDirective = 261,
OmpTargetExitDataDirective = 262,
OmpTargetParallelDirective = 263,
OmpTargetParallelForDirective = 264,
OmpTargetUpdateDirective = 265,
OmpDistributeParallelForDirective = 266,
OmpDistributeParallelForSimdDirective = 267,
OmpDistributeSimdDirective = 268,
OmpTargetParallelForSimdDirective = 269,
OmpTargetSimdDirective = 270,
OmpTeamsDistributeDirective = 271,
OmpTeamsDistributeSimdDirective = 272,
OmpTeamsDistributeParallelForSimdDirective = 273,
OmpTeamsDistributeParallelForDirective = 274,
OmpTargetTeamsDirective = 275,
OmpTargetTeamsDistributeDirective = 276,
OmpTargetTeamsDistributeParallelForDirective = 277,
OmpTargetTeamsDistributeParallelForSimdDirective = 278,
OmpTargetTeamsDistributeSimdDirective = 279,
BitCastExpr = 280,
OmpMasterTaskLoopDirective = 281,
OmpParallelMasterTaskLoopDirective = 282,
OmpMasterTaskLoopSimdDirective = 283,
OmpParallelMasterTaskLoopSimdDirective = 284,
OmpParallelMasterDirective = 285,
TranslationUnit = 300,
UnexposedAttr = 400,
IbActionAttr = 401,
IbOutletAttr = 402,
IbOutletCollectionAttr = 403,
FinalAttr = 404,
OverrideAttr = 405,
AnnotateAttr = 406,
AsmLabelAttr = 407,
PackedAttr = 408,
PureAttr = 409,
ConstAttr = 410,
NoDuplicateAttr = 411,
CudaConstantAttr = 412,
CudaDeviceAttr = 413,
CudaGlobalAttr = 414,
CudaHostAttr = 415,
CudaSharedAttr = 416,
VisibilityAttr = 417,
DllExport = 418,
DllImport = 419,
NSReturnsRetained = 420,
NSReturnsNotRetained = 421,
NSReturnsAutoreleased = 422,
NSConsumesSelf = 423,
NSConsumed = 424,
ObjCException = 425,
ObjCNSObject = 426,
ObjCIndependentClass = 427,
ObjCPreciseLifetime = 428,
ObjCReturnsInnerPointer = 429,
ObjCRequiresSuper = 430,
ObjCRootClass = 431,
ObjCSubclassingRestricted = 432,
ObjCExplicitProtocolImpl = 433,
ObjCDesignatedInitializer = 434,
ObjCRuntimeVisible = 435,
ObjCBoxable = 436,
FlagEnum = 437,
ConvergentAttr = 438,
WarnUnusedAttr = 439,
WarnUnusedResultAttr = 440,
AlignedAttr = 441,
PreprocessingDirective = 500,
MacroDefinition = 501,
MacroExpansion = 502,
InclusionDirective = 503,
ModuleImportDecl = 600,
TypeAliasTemplateDecl = 601,
StaticAssert = 602,
FriendDecl = 603,
OverloadCandidate = 700,
}
impl EntityKind {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=50 | 70..=73 | 100..=149 | 200..=280 | 300 | 400..=441 | 500..=503 | 600..=603
| 700 => {
Some(unsafe { mem::transmute(raw) })
}
_ => None,
}
}
fn from_raw_infallible(raw: c_int) -> Self {
Self::from_raw(raw).unwrap_or(EntityKind::NotImplemented)
}
pub fn is_valid(&self) -> bool {
!matches!(*self as c_int, 70..=75)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum EntityVisitResult {
Break = 0,
Continue = 1,
Recurse = 2,
}
#[cfg(feature="clang_3_9")]
#[derive(Clone, Debug, PartialEq)]
pub enum EvaluationResult {
Unexposed,
SignedInteger(i64),
UnsignedInteger(u64),
Float(f64),
String(CString),
ObjCString(CString),
CFString(CString),
Other(CString),
}
#[cfg(feature="clang_5_0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum ExceptionSpecification {
BasicNoexcept = 4,
ComputedNoexcept = 5,
Dynamic = 2,
DynamicAny = 3,
DynamicNone = 1,
Unevaluated = 6,
Uninstantiated = 7,
Unparsed = 8,
NoThrow = 9,
}
#[cfg(feature="clang_5_0")]
impl ExceptionSpecification {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=9 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Language {
C = 1,
Cpp = 3,
ObjectiveC = 2,
Swift = 4,
}
impl Language {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=4 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Linkage {
Automatic = 1,
Internal = 2,
External = 4,
UniqueExternal = 3,
}
impl Linkage {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=4 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum MemoryUsage {
Ast = 1,
AstSideTables = 6,
ExternalAstSourceMalloc = 9,
ExternalAstSourceMMap = 10,
GlobalCodeCompletionResults = 4,
Identifiers = 2,
PreprocessingRecord = 12,
Preprocessor = 11,
PreprocessorHeaderSearch = 14,
Selectors = 3,
SourceManagerContentCache = 5,
SourceManagerDataStructures = 13,
SourceManagerMalloc = 7,
SourceManagerMMap = 8,
}
impl MemoryUsage {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=14 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[cfg(feature="clang_8_0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Nullability {
NonNull = 0,
Nullable = 1,
Unspecified = 2,
}
#[cfg(feature="clang_8_0")]
impl Nullability {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
0..=2 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[cfg(feature="clang_7_0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum PrintingPolicyFlag {
SuppressSpecifiers = 1,
SuppressTagKeyword = 2,
IncludeTagDefinition = 3,
SuppressScope = 4,
SuppressUnwrittenScope = 5,
SuppressInitializers = 6,
PrintConstantArraySizeAsWritten = 7,
PrintAnonymousTagLocations = 8,
SuppressStrongLifetime = 9,
SuppressLifetimeQualifiers = 10,
SuppressTemplateArgsInCXXConstructors = 11,
UseBool = 12,
UseRestrict = 13,
UseAlignof = 14,
UseUnderscoreAlignof = 15,
UseVoidForZeroParams = 16,
UseTerseOutput = 17,
PolishForDeclaration = 18,
UseHalf = 19,
UseMsWchar = 20,
IncludeNewlines = 21,
UseMsvcFormatting = 22,
PrintConstantsAsWritten = 23,
SuppressImplicitBase = 24,
PrintFullyQualifiedName = 25,
}
#[cfg_attr(feature="cargo-clippy", allow(clippy::enum_variant_names))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum RefQualifier {
LValue = 1,
RValue = 2,
}
impl RefQualifier {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=2 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[cfg(feature="clang_3_6")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum StorageClass {
None = 1,
Auto = 6,
Register = 7,
Static = 3,
Extern = 2,
PrivateExtern = 4,
OpenClWorkGroupLocal = 5,
}
#[cfg(feature="clang_3_6")]
impl StorageClass {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=7 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[cfg(feature="clang_3_6")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TemplateArgument<'tu> {
Declaration,
Expression,
Null,
Nullptr,
Pack,
Template,
TemplateExpansion,
Integral(i64, u64),
Type(Type<'tu>),
}
#[cfg(feature="clang_6_0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum TlsKind {
Dynamic = 1,
Static = 2,
}
#[cfg(feature="clang_6_0")]
impl TlsKind {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=2 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum TypeKind {
Unexposed = 1,
Void = 2,
Bool = 3,
CharS = 13,
CharU = 4,
SChar = 14,
UChar = 5,
WChar = 15,
Char16 = 6,
Char32 = 7,
Short = 16,
UShort = 8,
Int = 17,
UInt = 9,
Long = 18,
ULong = 10,
LongLong = 19,
ULongLong = 11,
Int128 = 20,
UInt128 = 12,
Half = 31,
Float16 = 32,
ShortAccum = 33,
Accum = 34,
LongAccum = 35,
UShortAccum = 36,
UAccum = 37,
ULongAccum = 38,
Float = 21,
Double = 22,
LongDouble = 23,
Nullptr = 24,
Complex = 100,
Dependent = 26,
Overload = 25,
ObjCId = 27,
ObjCClass = 28,
ObjCSel = 29,
Float128 = 30,
ObjCInterface = 108,
ObjCObjectPointer = 109,
Pointer = 101,
BlockPointer = 102,
MemberPointer = 117,
LValueReference = 103,
RValueReference = 104,
Enum = 106,
Record = 105,
Typedef = 107,
FunctionPrototype = 111,
FunctionNoPrototype = 110,
ConstantArray = 112,
DependentSizedArray = 116,
IncompleteArray = 114,
VariableArray = 115,
Vector = 113,
Auto = 118,
Elaborated = 119,
Pipe = 120,
OCLImage1dRO = 121,
OCLImage1dArrayRO = 122,
OCLImage1dBufferRO = 123,
OCLImage2dRO = 124,
OCLImage2dArrayRO = 125,
OCLImage2dDepthRO = 126,
OCLImage2dArrayDepthRO = 127,
OCLImage2dMSAARO = 128,
OCLImage2dArrayMSAARO = 129,
OCLImage2dMSAADepthRO = 130,
OCLImage2dArrayMSAADepthRO = 131,
OCLImage3dRO = 132,
OCLImage1dWO = 133,
OCLImage1dArrayWO = 134,
OCLImage1dBufferWO = 135,
OCLImage2dWO = 136,
OCLImage2dArrayWO = 137,
OCLImage2dDepthWO = 138,
OCLImage2dArrayDepthWO = 139,
OCLImage2dMSAAWO = 140,
OCLImage2dArrayMSAAWO = 141,
OCLImage2dMSAADepthWO = 142,
OCLImage2dArrayMSAADepthWO = 143,
OCLImage3dWO = 144,
OCLImage1dRW = 145,
OCLImage1dArrayRW = 146,
OCLImage1dBufferRW = 147,
OCLImage2dRW = 148,
OCLImage2dArrayRW = 149,
OCLImage2dDepthRW = 150,
OCLImage2dArrayDepthRW = 151,
OCLImage2dMSAARW = 152,
OCLImage2dArrayMSAARW = 153,
OCLImage2dMSAADepthRW = 154,
OCLImage2dArrayMSAADepthRW = 155,
OCLImage3dRW = 156,
OCLSampler = 157,
OCLEvent = 158,
OCLQueue = 159,
OCLReserveID = 160,
ObjCObject = 161,
ObjCTypeParam = 162,
Attributed = 163,
OCLIntelSubgroupAVCMcePayload = 164,
OCLIntelSubgroupAVCImePayload = 165,
OCLIntelSubgroupAVCRefPayload = 166,
OCLIntelSubgroupAVCSicPayload = 167,
OCLIntelSubgroupAVCMceResult = 168,
OCLIntelSubgroupAVCImeResult = 169,
OCLIntelSubgroupAVCRefResult = 170,
OCLIntelSubgroupAVCSicResult = 171,
OCLIntelSubgroupAVCImeResultSingleRefStreamout = 172,
OCLIntelSubgroupAVCImeResultDualRefStreamout = 173,
OCLIntelSubgroupAVCImeSingleRefStreamin = 174,
OCLIntelSubgroupAVCImeDualRefStreamin = 175,
ExtVector = 176,
}
impl TypeKind {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=38 | 101..=175 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
fn from_raw_infallible(raw: c_int) -> Self {
Self::from_raw(raw).unwrap_or(TypeKind::Unexposed)
}
}
#[cfg(feature="clang_3_8")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum Visibility {
Default = 3,
Hidden = 1,
Protected = 2,
}
#[cfg(feature="clang_3_8")]
impl Visibility {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
1..=3 => Some(unsafe { mem::transmute(raw) }),
_ => None,
}
}
}
type PhantomUnsendUnsync = PhantomData<*mut ()>;
static AVAILABLE: AtomicBool = AtomicBool::new(true);
#[derive(Debug)]
pub struct Clang(PhantomUnsendUnsync);
impl Clang {
#[cfg(feature="runtime")]
pub fn new() -> Result<Clang, String> {
if AVAILABLE.swap(false, atomic::Ordering::SeqCst) {
load().map(|_| Clang(PhantomData))
} else {
Err("an instance of `Clang` already exists".into())
}
}
#[cfg(not(feature="runtime"))]
pub fn new() -> Result<Clang, String> {
if AVAILABLE.swap(false, atomic::Ordering::SeqCst) {
Ok(Clang(PhantomData))
} else {
Err("an instance of `Clang` already exists".into())
}
}
}
#[cfg(feature="runtime")]
impl Drop for Clang {
fn drop(&mut self) {
unload().unwrap();
AVAILABLE.store(true, atomic::Ordering::SeqCst);
}
}
#[cfg(not(feature="runtime"))]
impl Drop for Clang {
fn drop(&mut self) {
AVAILABLE.store(true, atomic::Ordering::SeqCst);
}
}
#[derive(Debug)]
pub struct CompilationDatabase {
ptr: CXCompilationDatabase,
}
impl CompilationDatabase {
pub fn from_directory<P: AsRef<Path>>(path: P) -> Result<CompilationDatabase, ()> {
let path = utility::from_path(path);
unsafe {
let mut error = mem::MaybeUninit::uninit();
let ptr = clang_CompilationDatabase_fromDirectory(path.as_ptr(), error.as_mut_ptr());
match error.assume_init() {
CXCompilationDatabase_NoError => Ok(CompilationDatabase { ptr }),
CXCompilationDatabase_CanNotLoadDatabase => Err(()),
_ => unreachable!(),
}
}
}
pub fn get_all_compile_commands(&self) -> CompileCommands {
unsafe {
CompileCommands::from_ptr(clang_CompilationDatabase_getAllCompileCommands(self.ptr))
}
}
pub fn get_compile_commands<P: AsRef<Path>>(&self, path: P) -> Result<CompileCommands, ()> {
let path = utility::from_path(path);
let ptr = unsafe { clang_CompilationDatabase_getCompileCommands(self.ptr, path.as_ptr()) };
ptr.map(CompileCommands::from_ptr).ok_or(())
}
}
impl Drop for CompilationDatabase {
fn drop(&mut self) {
unsafe {
clang_CompilationDatabase_dispose(self.ptr);
}
}
}
#[derive(Debug)]
pub struct CompileCommands {
ptr: CXCompileCommands,
}
impl CompileCommands {
fn from_ptr(ptr: CXCompileCommands) -> CompileCommands {
assert!(!ptr.is_null());
CompileCommands { ptr }
}
pub fn get_commands(&self) -> Vec<CompileCommand> {
iter!(
clang_CompileCommands_getSize(self.ptr),
clang_CompileCommands_getCommand(self.ptr),
)
.map(|p| CompileCommand::from_ptr(self, p))
.collect()
}
}
impl Drop for CompileCommands {
fn drop(&mut self) {
unsafe {
clang_CompileCommands_dispose(self.ptr);
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct CompileCommand<'cmds> {
ptr: CXCompileCommand,
_marker: PhantomData<&'cmds CompileCommands>,
}
impl<'cmds> CompileCommand<'cmds> {
fn from_ptr(_: &'cmds CompileCommands, ptr: CXCompileCommand) -> CompileCommand<'cmds> {
assert!(!ptr.is_null());
CompileCommand {
ptr,
_marker: PhantomData,
}
}
pub fn get_directory(&self) -> PathBuf {
utility::to_path(unsafe { clang_CompileCommand_getDirectory(self.ptr) })
}
#[cfg(feature="clang_3_8")]
pub fn get_filename(&self) -> PathBuf {
utility::to_path(unsafe { clang_CompileCommand_getFilename(self.ptr) })
}
pub fn get_arguments(&self) -> Vec<String> {
iter!(
clang_CompileCommand_getNumArgs(self.ptr),
clang_CompileCommand_getArg(self.ptr),
)
.map(utility::to_string)
.collect()
}
}
#[derive(Copy, Clone)]
pub struct Entity<'tu> {
raw: CXCursor,
tu: &'tu TranslationUnit<'tu>,
}
impl<'tu> Entity<'tu> {
fn from_raw(raw: CXCursor, tu: &'tu TranslationUnit<'tu>) -> Entity<'tu> {
Entity { raw, tu }
}
#[cfg(feature="clang_3_9")]
pub fn evaluate(&self) -> Option<EvaluationResult> {
macro_rules! string {
($eval:expr) => {
std::ffi::CStr::from_ptr(clang_EvalResult_getAsStr($eval)).to_owned()
};
}
#[cfg(feature="clang_4_0")]
unsafe fn evaluate_integer(e: CXEvalResult) -> EvaluationResult {
if clang_EvalResult_isUnsignedInt(e) != 0 {
EvaluationResult::UnsignedInteger(clang_EvalResult_getAsUnsigned(e) as u64)
} else {
EvaluationResult::SignedInteger(clang_EvalResult_getAsLongLong(e) as i64)
}
}
#[cfg(not(feature="clang_4_0"))]
unsafe fn evaluate_integer(e: CXEvalResult) -> EvaluationResult {
EvaluationResult::SignedInteger(clang_EvalResult_getAsInt(e) as i64)
}
unsafe {
clang_Cursor_Evaluate(self.raw).map(|e| {
assert!(!e.is_null());
let result = match clang_EvalResult_getKind(e) {
CXEval_UnExposed => EvaluationResult::Unexposed,
CXEval_Int => evaluate_integer(e),
CXEval_Float => EvaluationResult::Float(clang_EvalResult_getAsDouble(e) as f64),
CXEval_ObjCStrLiteral => EvaluationResult::ObjCString(string!(e)),
CXEval_StrLiteral => EvaluationResult::String(string!(e)),
CXEval_CFStr => EvaluationResult::CFString(string!(e)),
CXEval_Other => EvaluationResult::Other(string!(e)),
_ => panic!("unexpected eval result: {:?}", e),
};
clang_EvalResult_dispose(e);
result
})
}
}
pub fn get_kind(&self) -> EntityKind {
EntityKind::from_raw_infallible(unsafe { clang_getCursorKind(self.raw) })
}
pub fn get_display_name(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_getCursorDisplayName(self.raw)) }
}
#[cfg(feature="clang_7_0")]
pub fn get_pretty_printer(&self) -> PrettyPrinter {
unsafe { PrettyPrinter::from_raw(clang_getCursorPrintingPolicy(self.raw), self) }
}
pub fn get_location(&self) -> Option<SourceLocation<'tu>> {
unsafe { clang_getCursorLocation(self.raw).map(|l| SourceLocation::from_raw(l, self.tu)) }
}
pub fn get_range(&self) -> Option<SourceRange<'tu>> {
unsafe { clang_getCursorExtent(self.raw).map(|r| SourceRange::from_raw(r, self.tu)) }
}
pub fn get_accessibility(&self) -> Option<Accessibility> {
unsafe {
match clang_getCXXAccessSpecifier(self.raw) {
CX_CXXInvalidAccessSpecifier => None,
other => Accessibility::from_raw(other),
}
}
}
pub fn get_arguments(&self) -> Option<Vec<Entity<'tu>>> {
iter_option!(
clang_Cursor_getNumArguments(self.raw),
clang_Cursor_getArgument(self.raw),
).map(|i| i.map(|a| Entity::from_raw(a, self.tu)).collect())
}
pub fn get_availability(&self) -> Availability {
Availability::from_raw(unsafe {clang_getCursorAvailability(self.raw) }).unwrap()
}
pub fn get_bit_field_width(&self) -> Option<usize> {
unsafe {
let width = clang_getFieldDeclBitWidth(self.raw);
if width >= 0 {
Some(width as usize)
} else {
None
}
}
}
pub fn get_canonical_entity(&self) -> Entity<'tu> {
unsafe { Entity::from_raw(clang_getCanonicalCursor(self.raw), self.tu) }
}
pub fn get_comment(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_Cursor_getRawCommentText(self.raw)) }
}
pub fn get_parsed_comment(&self) -> Option<Comment<'tu>> {
unsafe { clang_Cursor_getParsedComment(self.raw).map(Comment::from_raw) }
}
pub fn get_comment_brief(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_Cursor_getBriefCommentText(self.raw)) }
}
pub fn get_comment_range(&self) -> Option<SourceRange<'tu>> {
unsafe { clang_Cursor_getCommentRange(self.raw).map(|r| SourceRange::from_raw(r, self.tu)) }
}
pub fn get_completion_string(&self) -> Option<CompletionString> {
unsafe { clang_getCursorCompletionString(self.raw).map(CompletionString::from_ptr) }
}
pub fn get_child(&self, mut index: usize) -> Option<Entity<'tu>> {
let mut child = None;
self.visit_children(|c, _| {
if index == 0 {
child = Some(c);
EntityVisitResult::Break
} else {
index -= 1;
EntityVisitResult::Continue
}
});
child
}
pub fn get_children(&self) -> Vec<Entity<'tu>> {
let mut children = vec![];
self.visit_children(|c, _| {
children.push(c);
EntityVisitResult::Continue
});
children
}
pub fn get_definition(&self) -> Option<Entity<'tu>> {
unsafe { clang_getCursorDefinition(self.raw).map(|p| Entity::from_raw(p, self.tu)) }
}
pub fn get_enum_constant_value(&self) -> Option<(i64, u64)> {
unsafe {
if self.get_kind() == EntityKind::EnumConstantDecl {
let signed = clang_getEnumConstantDeclValue(self.raw);
let unsigned = clang_getEnumConstantDeclUnsignedValue(self.raw);
Some((signed, unsigned))
} else {
None
}
}
}
pub fn get_enum_underlying_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getEnumDeclIntegerType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
#[cfg(feature="clang_5_0")]
pub fn get_exception_specification(&self) -> Option<ExceptionSpecification> {
unsafe {
match clang_getCursorExceptionSpecificationType(self.raw) {
-1 | CXCursor_ExceptionSpecificationKind_None => None,
other => ExceptionSpecification::from_raw(other),
}
}
}
#[cfg(feature="clang_5_0")]
pub fn get_external_symbol(&self) -> Option<ExternalSymbol> {
unsafe {
let mut language = mem::MaybeUninit::uninit();
let mut defined = mem::MaybeUninit::uninit();
let mut generated: c_uint = 0;
if clang_Cursor_isExternalSymbol(self.raw, language.as_mut_ptr(), defined.as_mut_ptr(), &mut generated) != 0 {
Some(ExternalSymbol {
language: utility::to_string(language.assume_init()),
defined: utility::to_string(defined.assume_init()),
generated: generated != 0
})
} else {
None
}
}
}
pub fn get_file(&self) -> Option<File<'tu>> {
unsafe { clang_getIncludedFile(self.raw).map(|f| File::from_ptr(f, self.tu)) }
}
pub fn get_language(&self) -> Option<Language> {
unsafe {
match clang_getCursorLanguage(self.raw) {
CXLanguage_Invalid => None,
other => Language::from_raw(other),
}
}
}
pub fn get_lexical_parent(&self) -> Option<Entity<'tu>> {
unsafe { clang_getCursorLexicalParent(self.raw).map(|p| Entity::from_raw(p, self.tu)) }
}
pub fn get_linkage(&self) -> Option<Linkage> {
unsafe {
match clang_getCursorLinkage(self.raw) {
CXLinkage_Invalid => None,
other => Linkage::from_raw(other),
}
}
}
#[cfg(feature="clang_3_6")]
pub fn get_mangled_name(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_Cursor_getMangling(self.raw)) }
}
#[cfg(feature="clang_3_8")]
pub fn get_mangled_names(&self) -> Option<Vec<String>> {
unsafe { utility::to_string_set_option(clang_Cursor_getCXXManglings(self.raw)) }
}
#[cfg(feature="clang_6_0")]
pub fn get_mangled_objc_names(&self) -> Option<Vec<String>> {
unsafe { utility::to_string_set_option(clang_Cursor_getObjCManglings(self.raw)) }
}
pub fn get_module(&self) -> Option<Module<'tu>> {
unsafe { clang_Cursor_getModule(self.raw).map(|m| Module::from_ptr(m, self.tu)) }
}
pub fn get_name(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_getCursorSpelling(self.raw)) }
}
pub fn get_name_ranges(&self) -> Vec<SourceRange<'tu>> {
unsafe {
(0..).map(|i| clang_Cursor_getSpellingNameRange(self.raw, i, 0)).take_while(|r| {
if clang_Range_isNull(*r) != 0 {
false
} else {
let range = clang_getRangeStart(*r);
let mut file = ptr::null_mut();
let null = ptr::null_mut();
clang_getSpellingLocation(range, &mut file, null, null, null);
!file.is_null()
}
}).map(|r| SourceRange::from_raw(r, self.tu)).collect()
}
}
pub fn get_objc_attributes(&self) -> Option<ObjCAttributes> {
let attributes = unsafe { clang_Cursor_getObjCPropertyAttributes(self.raw, 0) };
if attributes != 0 {
Some(ObjCAttributes::from(attributes))
} else {
None
}
}
#[cfg(feature="clang_8_0")]
pub fn get_objc_getter_name(&self) -> Option<String> {
utility::to_string_option(unsafe { clang_Cursor_getObjCPropertyGetterName(self.raw) })
}
pub fn get_objc_ib_outlet_collection_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getIBOutletCollectionType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_objc_receiver_type(&self) -> Option<Type<'tu>> {
unsafe { clang_Cursor_getReceiverType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_objc_selector_index(&self) -> Option<usize> {
let index = unsafe { clang_Cursor_getObjCSelectorIndex(self.raw) };
if index >= 0 {
Some(index as usize)
} else {
None
}
}
#[cfg(feature="clang_8_0")]
pub fn get_objc_setter_name(&self) -> Option<String> {
utility::to_string_option(unsafe { clang_Cursor_getObjCPropertySetterName(self.raw) })
}
pub fn get_objc_type_encoding(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_getDeclObjCTypeEncoding(self.raw)) }
}
pub fn get_objc_qualifiers(&self) -> Option<ObjCQualifiers> {
let qualifiers = unsafe { clang_Cursor_getObjCDeclQualifiers(self.raw) };
if qualifiers != 0 {
Some(ObjCQualifiers::from(qualifiers))
} else {
None
}
}
#[cfg(feature="clang_3_7")]
pub fn get_offset_of_field(&self) -> Result<usize, OffsetofError> {
let offsetof_ = unsafe { clang_Cursor_getOffsetOfField(self.raw) };
OffsetofError::from_error(offsetof_).map(|_| offsetof_ as usize)
}
pub fn get_overloaded_declarations(&self) -> Option<Vec<Entity<'tu>>> {
let declarations = iter!(
clang_getNumOverloadedDecls(self.raw),
clang_getOverloadedDecl(self.raw),
).map(|e| Entity::from_raw(e, self.tu)).collect::<Vec<_>>();
if !declarations.is_empty() {
Some(declarations)
} else {
None
}
}
pub fn get_overridden_methods(&self) -> Option<Vec<Entity<'tu>>> {
unsafe {
let (mut raw, mut count) = (ptr::null_mut(), 0);
clang_getOverriddenCursors(self.raw, &mut raw, &mut count);
if !raw.is_null() {
let raws = slice::from_raw_parts(raw, count as usize);
let methods = raws.iter().map(|e| Entity::from_raw(*e, self.tu)).collect();
clang_disposeOverriddenCursors(raw);
Some(methods)
} else {
None
}
}
}
pub fn get_platform_availability(&self) -> Option<Vec<PlatformAvailability>> {
if !self.is_declaration() {
return None;
}
unsafe {
let mut buffer: [CXPlatformAvailability; 32] = [CXPlatformAvailability::default(); 32];
let count = clang_getCursorPlatformAvailability(
self.raw,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
(&mut buffer).as_mut_ptr(),
buffer.len() as c_int,
);
Some((0..count as usize).map(|i| PlatformAvailability::from_raw(buffer[i])).collect())
}
}
pub fn get_reference(&self) -> Option<Entity<'tu>> {
unsafe { clang_getCursorReferenced(self.raw).map(|p| Entity::from_raw(p, self.tu)) }
}
pub fn get_semantic_parent(&self) -> Option<Entity<'tu>> {
let parent = unsafe { clang_getCursorSemanticParent(self.raw) };
parent.map(|p| Entity::from_raw(p, self.tu))
}
#[cfg(feature="clang_3_6")]
pub fn get_storage_class(&self) -> Option<StorageClass> {
unsafe {
match clang_Cursor_getStorageClass(self.raw) {
CX_SC_Invalid => None,
other => StorageClass::from_raw(other),
}
}
}
pub fn get_template(&self) -> Option<Entity<'tu>> {
let parent = unsafe { clang_getSpecializedCursorTemplate(self.raw) };
parent.map(|p| Entity::from_raw(p, self.tu))
}
#[cfg(feature="clang_3_6")]
pub fn get_template_arguments(&self) -> Option<Vec<TemplateArgument<'tu>>> {
let get_type = &clang_Cursor_getTemplateArgumentType;
let get_signed = &clang_Cursor_getTemplateArgumentValue;
let get_unsigned = &clang_Cursor_getTemplateArgumentUnsignedValue;
iter_option!(
clang_Cursor_getNumTemplateArguments(self.raw),
clang_Cursor_getTemplateArgumentKind(self.raw),
).map(|i| {
i.enumerate().map(|(i, t)| {
match t {
CXTemplateArgumentKind_Null => TemplateArgument::Null,
CXTemplateArgumentKind_Type => {
let type_ = unsafe { get_type(self.raw, i as c_uint) };
TemplateArgument::Type(Type::from_raw(type_, self.tu))
},
CXTemplateArgumentKind_Declaration => TemplateArgument::Declaration,
CXTemplateArgumentKind_NullPtr => TemplateArgument::Nullptr,
CXTemplateArgumentKind_Integral => {
let signed = unsafe { get_signed(self.raw, i as c_uint) };
let unsigned = unsafe { get_unsigned(self.raw, i as c_uint) };
TemplateArgument::Integral(signed as i64, unsigned as u64)
},
CXTemplateArgumentKind_Template => TemplateArgument::Template,
CXTemplateArgumentKind_TemplateExpansion => TemplateArgument::TemplateExpansion,
CXTemplateArgumentKind_Expression => TemplateArgument::Expression,
CXTemplateArgumentKind_Pack => TemplateArgument::Pack,
_ => unreachable!(),
}
}).collect()
})
}
pub fn get_template_kind(&self) -> Option<EntityKind> {
unsafe {
match clang_getTemplateCursorKind(self.raw) {
CXCursor_NoDeclFound => None,
other => EntityKind::from_raw(other),
}
}
}
#[cfg(feature="clang_6_0")]
pub fn get_tls_kind(&self) -> Option<TlsKind> {
unsafe {
match clang_getCursorTLSKind(self.raw) {
CXTLS_None => None,
other => TlsKind::from_raw(other),
}
}
}
pub fn get_translation_unit(&self) -> &'tu TranslationUnit<'tu> {
self.tu
}
pub fn get_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getCursorType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_typedef_underlying_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getTypedefDeclUnderlyingType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_usr(&self) -> Option<Usr> {
unsafe { utility::to_string_option(clang_getCursorUSR(self.raw)).map(Usr) }
}
#[cfg(feature="clang_3_8")]
pub fn get_visibility(&self) -> Option<Visibility> {
unsafe {
match clang_getCursorVisibility(self.raw) {
CXVisibility_Invalid => None,
other => Visibility::from_raw(other),
}
}
}
pub fn get_result_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getCursorResultType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
#[cfg(feature="clang_3_9")]
pub fn has_attributes(&self) -> bool {
unsafe { clang_Cursor_hasAttrs(self.raw) != 0 }
}
#[cfg(feature="clang_6_0")]
pub fn is_abstract_record(&self) -> bool {
unsafe { clang_CXXRecord_isAbstract(self.raw) != 0 }
}
#[cfg(feature="clang_3_7")]
pub fn is_anonymous(&self) -> bool {
unsafe { clang_Cursor_isAnonymous(self.raw) != 0 }
}
#[cfg(feature="clang_9_0")]
pub fn is_anonymous_record_decl(&self) -> bool {
unsafe { clang_Cursor_isAnonymousRecordDecl(self.raw) != 0 }
}
#[cfg(feature="clang_9_0")]
pub fn is_inline_namespace(&self) -> bool {
unsafe { clang_Cursor_isInlineNamespace(self.raw) != 0 }
}
pub fn is_bit_field(&self) -> bool {
unsafe { clang_Cursor_isBitField(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_builtin_macro(&self) -> bool {
unsafe { clang_Cursor_isMacroBuiltin(self.raw) != 0 }
}
pub fn is_const_method(&self) -> bool {
unsafe { clang_CXXMethod_isConst(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_converting_constructor(&self) -> bool {
unsafe { clang_CXXConstructor_isConvertingConstructor(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_copy_constructor(&self) -> bool {
unsafe { clang_CXXConstructor_isCopyConstructor(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_default_constructor(&self) -> bool {
unsafe { clang_CXXConstructor_isDefaultConstructor(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_defaulted(&self) -> bool {
unsafe { clang_CXXMethod_isDefaulted(self.raw) != 0 }
}
pub fn is_definition(&self) -> bool {
unsafe { clang_isCursorDefinition(self.raw) != 0 }
}
pub fn is_dynamic_call(&self) -> bool {
unsafe { clang_Cursor_isDynamicCall(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_function_like_macro(&self) -> bool {
unsafe { clang_Cursor_isMacroFunctionLike(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_inline_function(&self) -> bool {
unsafe { clang_Cursor_isFunctionInlined(self.raw) != 0 }
}
#[cfg(feature="clang_7_0")]
pub fn is_invalid_declaration(&self) -> bool {
unsafe { clang_isInvalidDeclaration(self.raw) != 0 }
}
#[cfg(feature="clang_3_9")]
pub fn is_move_constructor(&self) -> bool {
unsafe { clang_CXXConstructor_isMoveConstructor(self.raw) != 0 }
}
#[cfg(feature="clang_3_8")]
pub fn is_mutable(&self) -> bool {
unsafe { clang_CXXField_isMutable(self.raw) != 0 }
}
pub fn is_objc_optional(&self) -> bool {
unsafe { clang_Cursor_isObjCOptional(self.raw) != 0 }
}
pub fn is_pure_virtual_method(&self) -> bool {
unsafe { clang_CXXMethod_isPureVirtual(self.raw) != 0 }
}
#[cfg(feature="clang_5_0")]
pub fn is_scoped(&self) -> bool {
unsafe { clang_EnumDecl_isScoped(self.raw) != 0 }
}
pub fn is_static_method(&self) -> bool {
unsafe { clang_CXXMethod_isStatic(self.raw) != 0 }
}
pub fn is_variadic(&self) -> bool {
unsafe { clang_Cursor_isVariadic(self.raw) != 0 }
}
pub fn is_virtual_base(&self) -> bool {
unsafe { clang_isVirtualBase(self.raw) != 0 }
}
pub fn is_virtual_method(&self) -> bool {
unsafe { clang_CXXMethod_isVirtual(self.raw) != 0 }
}
pub fn visit_children<F: FnMut(Entity<'tu>, Entity<'tu>) -> EntityVisitResult>(
&self, f: F
) -> bool {
trait EntityCallback<'tu> {
fn call(&mut self, entity: Entity<'tu>, parent: Entity<'tu>) -> EntityVisitResult;
}
impl<'tu, F: FnMut(Entity<'tu>, Entity<'tu>) -> EntityVisitResult>
EntityCallback<'tu> for F {
fn call(&mut self, entity: Entity<'tu>, parent: Entity<'tu>) -> EntityVisitResult {
self(entity, parent)
}
}
extern fn visit(
cursor: CXCursor, parent: CXCursor, data: CXClientData
) -> CXChildVisitResult {
unsafe {
let &mut (tu, ref mut callback) =
&mut *(data as *mut (&TranslationUnit, Box<dyn EntityCallback>));
let entity = Entity::from_raw(cursor, tu);
let parent = Entity::from_raw(parent, tu);
callback.call(entity, parent) as c_int
}
}
let mut data = (self.tu, Box::new(f) as Box<dyn EntityCallback>);
unsafe { clang_visitChildren(self.raw, visit, utility::addressof(&mut data)) != 0 }
}
pub fn is_attribute(&self) -> bool {
unsafe { clang_isAttribute(self.raw.kind) != 0 }
}
pub fn is_declaration(&self) -> bool {
unsafe { clang_isDeclaration(self.raw.kind) != 0 }
}
pub fn is_expression(&self) -> bool {
unsafe { clang_isExpression(self.raw.kind) != 0 }
}
pub fn is_preprocessing(&self) -> bool {
unsafe { clang_isPreprocessing(self.raw.kind) != 0 }
}
pub fn is_reference(&self) -> bool {
unsafe { clang_isReference(self.raw.kind) != 0 }
}
pub fn is_statement(&self) -> bool {
unsafe { clang_isStatement(self.raw.kind) != 0 }
}
pub fn is_unexposed(&self) -> bool {
unsafe { clang_isUnexposed(self.raw.kind) != 0 }
}
pub fn is_in_main_file(&self) -> bool {
self.get_range().map_or(false, |r| r.is_in_main_file())
}
pub fn is_in_system_header(&self) -> bool {
self.get_range().map_or(false, |r| r.is_in_system_header())
}
}
impl<'tu> fmt::Debug for Entity<'tu> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("Entity")
.field("kind", &self.get_kind())
.field("display_name", &self.get_display_name())
.field("location", &self.get_location())
.finish()
}
}
impl<'tu> cmp::PartialEq for Entity<'tu> {
fn eq(&self, other: &Entity<'tu>) -> bool {
unsafe { clang_equalCursors(self.raw, other.raw) != 0 }
}
}
impl<'tu> cmp::Eq for Entity<'tu> { }
impl<'tu> hash::Hash for Entity<'tu> {
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
unsafe {
let integer = clang_hashCursor(self.raw);
let bytes = (&integer as *const c_uint) as *const u8;
let slice = slice::from_raw_parts(bytes, mem::size_of_val(&integer));
hasher.write(slice);
}
}
}
#[cfg(feature="clang_5_0")]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ExternalSymbol {
pub language: String,
pub defined: String,
pub generated: bool,
}
pub struct Index<'c> {
ptr: CXIndex,
_marker: PhantomData<&'c Clang>,
}
impl<'c> Index<'c> {
fn from_ptr(ptr: CXIndex) -> Index<'c> {
assert!(!ptr.is_null());
Index { ptr, _marker: PhantomData }
}
pub fn new(_: &'c Clang, exclude: bool, diagnostics: bool) -> Index<'c> {
unsafe { Index::from_ptr(clang_createIndex(exclude as c_int, diagnostics as c_int)) }
}
pub fn parser<F: Into<PathBuf>>(&'c self, f: F) -> Parser<'c> {
Parser::new(self, f)
}
#[cfg(feature="clang_6_0")]
pub fn set_invocation_emission_path<P: AsRef<Path>>(&'c self, path: P) {
let path = utility::from_path(path);
unsafe { clang_CXIndex_setInvocationEmissionPathOption(self.ptr, path.as_ptr()); }
}
pub fn get_thread_options(&self) -> ThreadOptions {
unsafe { ThreadOptions::from(clang_CXIndex_getGlobalOptions(self.ptr)) }
}
pub fn set_thread_options(&mut self, options: ThreadOptions) {
unsafe { clang_CXIndex_setGlobalOptions(self.ptr, options.into()); }
}
}
impl<'c> Drop for Index<'c> {
fn drop(&mut self) {
unsafe { clang_disposeIndex(self.ptr); }
}
}
impl<'c> fmt::Debug for Index<'c> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("Index")
.field("thread_options", &self.get_thread_options())
.finish()
}
}
options! {
options ObjCAttributes: CXObjCPropertyAttrKind {
pub readonly: CXObjCPropertyAttr_readonly,
pub getter: CXObjCPropertyAttr_getter,
pub assign: CXObjCPropertyAttr_assign,
pub readwrite: CXObjCPropertyAttr_readwrite,
pub retain: CXObjCPropertyAttr_retain,
pub copy: CXObjCPropertyAttr_copy,
pub nonatomic: CXObjCPropertyAttr_nonatomic,
pub setter: CXObjCPropertyAttr_setter,
pub atomic: CXObjCPropertyAttr_atomic,
pub weak: CXObjCPropertyAttr_weak,
pub strong: CXObjCPropertyAttr_strong,
pub unsafe_retained: CXObjCPropertyAttr_unsafe_unretained,
}, objcattributes: #[feature="clang_3_9"] {
pub class: CXObjCPropertyAttr_class,
}
}
options! {
options ObjCQualifiers: CXObjCDeclQualifierKind {
pub in_: CXObjCDeclQualifier_In,
pub inout: CXObjCDeclQualifier_Inout,
pub out: CXObjCDeclQualifier_Out,
pub bycopy: CXObjCDeclQualifier_Bycopy,
pub byref: CXObjCDeclQualifier_Byref,
pub oneway: CXObjCDeclQualifier_Oneway,
}
}
builder! {
builder Parser: CXTranslationUnit_Flags {
index: &'tu Index<'tu>,
file: PathBuf,
arguments: Vec<CString>,
unsaved: Vec<Unsaved>;
OPTIONS:
pub cache_completion_results: CXTranslationUnit_CacheCompletionResults,
pub detailed_preprocessing_record: CXTranslationUnit_DetailedPreprocessingRecord,
pub briefs_in_completion_results: CXTranslationUnit_IncludeBriefCommentsInCodeCompletion,
pub incomplete: CXTranslationUnit_Incomplete,
pub skip_function_bodies: CXTranslationUnit_SkipFunctionBodies,
#[cfg(feature="clang_3_9")]
pub keep_going: CXTranslationUnit_KeepGoing,
#[cfg(feature="clang_5_0")]
pub single_file_parse: CXTranslationUnit_SingleFileParse,
#[cfg(feature="clang_7_0")]
pub limit_skip_function_bodies_to_preamble: CXTranslationUnit_LimitSkipFunctionBodiesToPreamble,
#[cfg(feature="clang_8_0")]
pub include_attributed_types: CXTranslationUnit_IncludeAttributedTypes,
#[cfg(feature="clang_8_0")]
pub visit_implicit_attributes: CXTranslationUnit_VisitImplicitAttributes,
#[cfg(feature="clang_9_0")]
pub ignore_non_errors_from_included_files: CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles,
#[cfg(feature="clang_10_0")]
pub retain_excluded_conditional_blocks: CXTranslationUnit_RetainExcludedConditionalBlocks,
}
}
impl<'tu> Parser<'tu> {
fn new<F: Into<PathBuf>>(index: &'tu Index<'tu>, file: F) -> Parser<'tu> {
let flags: CXTranslationUnit_Flags = 0;
Parser { index, file: file.into(), arguments: vec![], unsaved: vec![], flags }
}
pub fn arguments<S: AsRef<str>>(&mut self, arguments: &[S]) -> &mut Parser<'tu> {
self.arguments = arguments.iter().map(utility::from_string).collect();
self
}
pub fn unsaved(&mut self, unsaved: &[Unsaved]) -> &mut Parser<'tu> {
self.unsaved = unsaved.into();
self
}
pub fn parse(&self) -> Result<TranslationUnit<'tu>, SourceError> {
let arguments = self.arguments.iter().map(|a| a.as_ptr()).collect::<Vec<_>>();
let unsaved = self.unsaved.iter().map(|u| u.as_raw()).collect::<Vec<_>>();
unsafe {
let mut ptr = ptr::null_mut();
let code = clang_parseTranslationUnit2(
self.index.ptr,
utility::from_path(&self.file).as_ptr(),
arguments.as_ptr(),
arguments.len() as c_int,
unsaved.as_ptr() as *mut CXUnsavedFile,
unsaved.len() as c_uint,
self.flags,
&mut ptr,
);
SourceError::from_error(code).map(|_| TranslationUnit::from_ptr(ptr))
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PlatformAvailability {
pub platform: String,
pub unavailable: bool,
pub introduced: Option<Version>,
pub deprecated: Option<Version>,
pub obsoleted: Option<Version>,
pub message: Option<String>,
}
impl PlatformAvailability {
fn from_raw(raw: CXPlatformAvailability) -> PlatformAvailability {
PlatformAvailability {
platform: utility::to_string(raw.Platform),
unavailable: raw.Unavailable != 0,
introduced: raw.Introduced.map(Version::from_raw),
deprecated: raw.Deprecated.map(Version::from_raw),
obsoleted: raw.Obsoleted.map(Version::from_raw),
message: utility::to_string_option(raw.Message),
}
}
}
#[cfg(feature="clang_7_0")]
#[derive(Debug)]
pub struct PrettyPrinter<'e> {
ptr: CXPrintingPolicy,
entity: &'e Entity<'e>,
}
#[cfg(feature="clang_7_0")]
impl<'e> PrettyPrinter<'e> {
fn from_raw(ptr: CXPrintingPolicy, entity: &'e Entity<'e>) -> Self {
assert!(!ptr.is_null());
PrettyPrinter { ptr, entity }
}
pub fn get_flag(&self, flag: PrintingPolicyFlag) -> bool {
unsafe { clang_PrintingPolicy_getProperty(self.ptr, flag as c_int) != 0 }
}
pub fn set_flag(&self, flag: PrintingPolicyFlag, value: bool) -> &Self {
let value = if value { 1 } else { 0 };
unsafe { clang_PrintingPolicy_setProperty(self.ptr, flag as c_int, value); }
self
}
pub fn get_indentation_amount(&self) -> u8 {
unsafe { clang_PrintingPolicy_getProperty(self.ptr, CXPrintingPolicy_Indentation) as u8 }
}
pub fn set_indentation_amount(&self, value: u8) -> &Self {
unsafe {
clang_PrintingPolicy_setProperty(self.ptr, CXPrintingPolicy_Indentation, value.into());
}
self
}
pub fn print(&self) -> String {
unsafe { utility::to_string(clang_getCursorPrettyPrinted(self.entity.raw, self.ptr)) }
}
}
#[cfg(feature="clang_7_0")]
impl<'e> Drop for PrettyPrinter<'e> {
fn drop(&mut self) {
unsafe { clang_PrintingPolicy_dispose(self.ptr) }
}
}
#[cfg(feature="clang_5_0")]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Target {
pub triple: String,
pub pointer_width: usize,
}
#[cfg(feature="clang_5_0")]
impl Target {
fn from_raw(raw: CXTargetInfo) -> Target {
unsafe {
let target = Target {
triple: utility::to_string(clang_TargetInfo_getTriple(raw)),
pointer_width: clang_TargetInfo_getPointerWidth(raw) as usize,
};
clang_TargetInfo_dispose(raw);
target
}
}
}
options! {
#[derive(Default)]
options ThreadOptions: CXGlobalOptFlags {
pub editing: CXGlobalOpt_ThreadBackgroundPriorityForEditing,
pub indexing: CXGlobalOpt_ThreadBackgroundPriorityForIndexing,
}
}
pub struct TranslationUnit<'i> {
ptr: CXTranslationUnit,
_marker: PhantomData<&'i Index<'i>>,
}
impl<'i> TranslationUnit<'i> {
fn from_ptr(ptr: CXTranslationUnit) -> TranslationUnit<'i> {
assert!(!ptr.is_null());
TranslationUnit { ptr, _marker: PhantomData }
}
pub fn from_ast<F: AsRef<Path>>(
index: &'i Index, file: F
) -> Result<TranslationUnit<'i>, ()> {
let path = utility::from_path(file);
let ptr = unsafe { clang_createTranslationUnit(index.ptr, path.as_ptr()) };
ptr.map(TranslationUnit::from_ptr).ok_or(())
}
pub fn get_diagnostics(&'i self) -> Vec<Diagnostic<'i>> {
iter!(clang_getNumDiagnostics(self.ptr), clang_getDiagnostic(self.ptr),).map(|d| {
Diagnostic::from_ptr(d, self)
}).collect()
}
pub fn get_entity(&'i self) -> Entity<'i> {
unsafe { Entity::from_raw(clang_getTranslationUnitCursor(self.ptr), self) }
}
pub fn get_file<F: AsRef<Path>>(&'i self, file: F) -> Option<File<'i>> {
let file = unsafe { clang_getFile(self.ptr, utility::from_path(file).as_ptr()) };
file.map(|f| File::from_ptr(f, self))
}
pub fn get_memory_usage(&self) -> HashMap<MemoryUsage, usize> {
unsafe {
let raw = clang_getCXTUResourceUsage(self.ptr);
let raws = slice::from_raw_parts(raw.entries, raw.numEntries as usize);
let usage = raws
.iter()
.flat_map(|u| MemoryUsage::from_raw(u.kind).map(|kind| (kind, u.amount as usize)))
.collect();
clang_disposeCXTUResourceUsage(raw);
usage
}
}
#[cfg(feature="clang_4_0")]
pub fn get_skipped_ranges(&'i self) -> Vec<SourceRange<'i>> {
unsafe {
let raw = clang_getAllSkippedRanges(self.ptr);
let raws = slice::from_raw_parts((*raw).ranges, (*raw).count as usize);
let ranges = raws.iter().map(|r| SourceRange::from_raw(*r, self)).collect();
clang_disposeSourceRangeList(raw);
ranges
}
}
#[cfg(feature="clang_5_0")]
pub fn get_target(&self) -> Target {
unsafe { Target::from_raw(clang_getTranslationUnitTargetInfo(self.ptr)) }
}
pub fn annotate(&'i self, tokens: &[Token<'i>]) -> Vec<Option<Entity<'i>>> {
unsafe {
let mut cursors = vec![CXCursor::default(); tokens.len()];
let mut tokens = tokens.iter().map(|t| t.raw).collect::<Vec<_>>();
clang_annotateTokens(self.ptr, tokens.as_mut_ptr(), tokens.len() as c_uint, cursors.as_mut_ptr());
cursors.iter().map(|e| e.map(|e| Entity::from_raw(e, self))).collect()
}
}
pub fn completer<F: Into<PathBuf>>(&self, file: F, line: u32, column: u32) -> Completer {
Completer::new(self, file, line, column)
}
pub fn save<F: AsRef<Path>>(&self, file: F) -> Result<(), SaveError> {
let file = utility::from_path(file);
let flags = CXSaveTranslationUnit_None;
let code = unsafe { clang_saveTranslationUnit(self.ptr, file.as_ptr(), flags) };
SaveError::from_error(code)
}
pub fn reparse(self, unsaved: &[Unsaved]) -> Result<TranslationUnit<'i>, SourceError> {
let unsaved = unsaved.iter().map(|u| u.as_raw()).collect::<Vec<_>>();
unsafe {
let code = clang_reparseTranslationUnit(
self.ptr,
unsaved.len() as c_uint,
unsaved.as_ptr() as *mut CXUnsavedFile,
CXReparse_None,
);
SourceError::from_error(code).map(|_| self)
}
}
}
impl<'i> Drop for TranslationUnit<'i> {
fn drop(&mut self) {
unsafe { clang_disposeTranslationUnit(self.ptr); }
}
}
impl<'i> fmt::Debug for TranslationUnit<'i> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let spelling = unsafe { clang_getTranslationUnitSpelling(self.ptr) };
formatter.debug_struct("TranslationUnit")
.field("spelling", &utility::to_string(spelling))
.finish()
}
}
#[derive(Copy, Clone)]
pub struct Type<'tu> {
raw: CXType,
tu: &'tu TranslationUnit<'tu>,
}
impl<'tu> Type<'tu> {
fn from_raw(raw: CXType, tu: &'tu TranslationUnit<'tu>) -> Type<'tu> {
Type { raw, tu }
}
pub fn get_kind(&self) -> TypeKind {
TypeKind::from_raw_infallible(self.raw.kind)
}
pub fn get_display_name(&self) -> String {
unsafe { utility::to_string(clang_getTypeSpelling(self.raw)) }
}
pub fn get_alignof(&self) -> Result<usize, AlignofError> {
let alignof_ = unsafe { clang_Type_getAlignOf(self.raw) };
AlignofError::from_error(alignof_).map(|_| alignof_ as usize)
}
pub fn get_offsetof<F: AsRef<str>>(&self, field: F) -> Result<usize, OffsetofError> {
let field = utility::from_string(field);
let offsetof_ = unsafe { clang_Type_getOffsetOf(self.raw, field.as_ptr()) };
OffsetofError::from_error(offsetof_).map(|_| offsetof_ as usize)
}
pub fn get_sizeof(&self) -> Result<usize, SizeofError> {
let sizeof_ = unsafe { clang_Type_getSizeOf(self.raw) };
SizeofError::from_error(sizeof_).map(|_| sizeof_ as usize)
}
#[cfg(feature="clang_5_0")]
pub fn get_address_space(&self) -> usize {
unsafe { clang_getAddressSpace(self.raw) as usize }
}
pub fn get_argument_types(&self) -> Option<Vec<Type<'tu>>> {
iter_option!(
clang_getNumArgTypes(self.raw),
clang_getArgType(self.raw),
).map(|i| i.map(|t| Type::from_raw(t, self.tu)).collect())
}
pub fn get_calling_convention(&self) -> Option<CallingConvention> {
unsafe {
match clang_getFunctionTypeCallingConv(self.raw) {
CXCallingConv_Invalid => None,
other => CallingConvention::from_raw(other),
}
}
}
pub fn get_canonical_type(&self) -> Type<'tu> {
unsafe { Type::from_raw(clang_getCanonicalType(self.raw), self.tu) }
}
pub fn get_class_type(&self) -> Option<Type<'tu>> {
unsafe { clang_Type_getClassType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_declaration(&self) -> Option<Entity<'tu>> {
unsafe { clang_getTypeDeclaration(self.raw).map(|e| Entity::from_raw(e, self.tu)) }
}
#[cfg(feature="clang_3_9")]
pub fn get_elaborated_type(&self) -> Option<Type<'tu>> {
unsafe { clang_Type_getNamedType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_element_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getElementType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
#[cfg(feature="clang_5_0")]
pub fn get_exception_specification(&self) -> Option<ExceptionSpecification> {
unsafe {
match clang_getExceptionSpecificationType(self.raw) {
-1 | CXCursor_ExceptionSpecificationKind_None => None,
other => ExceptionSpecification::from_raw(other),
}
}
}
#[cfg(feature="clang_3_7")]
pub fn get_fields(&self) -> Option<Vec<Entity<'tu>>> {
if self.get_kind() == TypeKind::Record {
let mut fields = vec![];
self.visit_fields(|e| {
fields.push(e);
true
});
Some(fields)
} else {
None
}
}
#[cfg(feature="clang_8_0")]
pub fn get_modified_type(&self) -> Option<Type<'tu>> {
unsafe { clang_Type_getModifiedType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
#[cfg(feature="clang_8_0")]
pub fn get_nullability(&self) -> Option<Nullability> {
unsafe {
match clang_Type_getNullability(self.raw) {
CXTypeNullability_Invalid => None,
other => Nullability::from_raw(other),
}
}
}
#[cfg(feature="clang_3_9")]
pub fn get_objc_encoding(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_Type_getObjCEncoding(self.raw)) }
}
#[cfg(feature="clang_8_0")]
pub fn get_objc_object_base_type(&self) -> Option<Type> {
unsafe { clang_Type_getObjCObjectBaseType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
#[cfg(feature="clang_8_0")]
pub fn get_objc_protocol_declarations(&self) -> Vec<Entity<'tu>> {
iter!(
clang_Type_getNumObjCProtocolRefs(self.raw),
clang_Type_getObjCProtocolDecl(self.raw),
).map(|c| Entity::from_raw(c, self.tu)).collect()
}
#[cfg(feature="clang_8_0")]
pub fn get_objc_type_arguments(&self) -> Vec<Type<'tu>> {
iter!(
clang_Type_getNumObjCTypeArgs(self.raw),
clang_Type_getObjCTypeArg(self.raw),
).map(|t| Type::from_raw(t, self.tu)).collect()
}
pub fn get_pointee_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getPointeeType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_ref_qualifier(&self) -> Option<RefQualifier> {
unsafe {
match clang_Type_getCXXRefQualifier(self.raw) {
CXRefQualifier_None => None,
other => RefQualifier::from_raw(other),
}
}
}
pub fn get_result_type(&self) -> Option<Type<'tu>> {
unsafe { clang_getResultType(self.raw).map(|t| Type::from_raw(t, self.tu)) }
}
pub fn get_size(&self) -> Option<usize> {
let size = unsafe { clang_getNumElements(self.raw) };
if size >= 0 {
Some(size as usize)
} else {
None
}
}
pub fn get_template_argument_types(&self) -> Option<Vec<Option<Type<'tu>>>> {
iter_option!(
clang_Type_getNumTemplateArguments(self.raw),
clang_Type_getTemplateArgumentAsType(self.raw),
).map(|i| i.map(|t| t.map(|t| Type::from_raw(t, self.tu))).collect())
}
#[cfg(feature="clang_5_0")]
pub fn get_typedef_name(&self) -> Option<String> {
unsafe { utility::to_string_option(clang_getTypedefName(self.raw)) }
}
pub fn is_const_qualified(&self) -> bool {
unsafe { clang_isConstQualifiedType(self.raw) != 0 }
}
pub fn is_elaborated(&self) -> Option<bool> {
if self.raw.kind == 119 {
Some(true)
} else if cfg!(feature="clang_3_9") {
Some(false)
} else {
None
}
}
pub fn is_pod(&self) -> bool {
unsafe { clang_isPODType(self.raw) != 0 }
}
pub fn is_restrict_qualified(&self) -> bool {
unsafe { clang_isRestrictQualifiedType(self.raw) != 0 }
}
#[cfg(feature="clang_5_0")]
pub fn is_transparent_tag(&self) -> bool {
unsafe { clang_Type_isTransparentTagTypedef(self.raw) != 0 }
}
pub fn is_variadic(&self) -> bool {
unsafe { clang_isFunctionTypeVariadic(self.raw) != 0 }
}
pub fn is_volatile_qualified(&self) -> bool {
unsafe { clang_isVolatileQualifiedType(self.raw) != 0 }
}
#[cfg(feature="clang_3_7")]
pub fn visit_fields<F: FnMut(Entity<'tu>) -> bool>(&self, f: F) -> Option<bool> {
if self.get_kind() != TypeKind::Record {
return None;
}
trait Callback<'tu> {
fn call(&mut self, field: Entity<'tu>) -> bool;
}
impl<'tu, F: FnMut(Entity<'tu>) -> bool> Callback<'tu> for F {
fn call(&mut self, field: Entity<'tu>) -> bool {
self(field)
}
}
extern fn visit(cursor: CXCursor, data: CXClientData) -> CXVisitorResult {
unsafe {
let &mut (tu, ref mut callback) =
&mut *(data as *mut (&TranslationUnit, Box<dyn Callback>));
if callback.call(Entity::from_raw(cursor, tu)) {
CXVisit_Continue
} else {
CXVisit_Break
}
}
}
let mut data = (self.tu, Box::new(f) as Box<dyn Callback>);
unsafe {
let data = utility::addressof(&mut data);
Some(clang_Type_visitFields(self.raw, visit, data) == CXVisit_Break)
}
}
pub fn is_integer(&self) -> bool {
self.raw.kind >= CXType_Bool && self.raw.kind <= CXType_Int128
}
pub fn is_signed_integer(&self) -> bool {
self.raw.kind >= CXType_Char_S && self.raw.kind <= CXType_Int128
}
pub fn is_unsigned_integer(&self) -> bool {
self.raw.kind >= CXType_Bool && self.raw.kind <= CXType_UInt128
}
}
impl<'tu> fmt::Debug for Type<'tu> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("Type")
.field("kind", &self.get_kind())
.field("display_name", &self.get_display_name())
.finish()
}
}
impl<'tu> cmp::PartialEq for Type<'tu> {
fn eq(&self, other: &Type<'tu>) -> bool {
unsafe { clang_equalTypes(self.raw, other.raw) != 0 }
}
}
impl<'tu> cmp::Eq for Type<'tu> { }
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Unsaved {
path: CString,
contents: CString,
}
impl Unsaved {
pub fn new<P: AsRef<Path>, C: AsRef<str>>(path: P, contents: C) -> Unsaved {
Unsaved { path: utility::from_path(path), contents: utility::from_string(contents) }
}
fn as_raw(&self) -> CXUnsavedFile {
CXUnsavedFile {
Filename: self.path.as_ptr(),
Contents: self.contents.as_ptr(),
Length: self.contents.as_bytes().len() as c_ulong,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Usr(pub String);
impl Usr {
pub fn from_objc_category<C: AsRef<str>>(class: C, category: C) -> Usr {
let class = utility::from_string(class);
let category = utility::from_string(category);
let raw = unsafe { clang_constructUSR_ObjCCategory(class.as_ptr(), category.as_ptr()) };
Usr(utility::to_string(raw))
}
pub fn from_objc_class<C: AsRef<str>>(class: C) -> Usr {
let class = utility::from_string(class);
unsafe { Usr(utility::to_string(clang_constructUSR_ObjCClass(class.as_ptr()))) }
}
pub fn from_objc_ivar<N: AsRef<str>>(class: &Usr, name: N) -> Usr {
utility::with_string(&class.0, |s| {
let name = utility::from_string(name);
unsafe { Usr(utility::to_string(clang_constructUSR_ObjCIvar(name.as_ptr(), s))) }
})
}
pub fn from_objc_method<N: AsRef<str>>(class: &Usr, name: N, instance: bool) -> Usr {
utility::with_string(&class.0, |s| {
let name = utility::from_string(name);
let instance = instance as c_uint;
let raw = unsafe { clang_constructUSR_ObjCMethod(name.as_ptr(), instance, s) };
Usr(utility::to_string(raw))
})
}
pub fn from_objc_property<N: AsRef<str>>(class: &Usr, name: N) -> Usr {
utility::with_string(&class.0, |s| {
let name = utility::from_string(name);
unsafe { Usr(utility::to_string(clang_constructUSR_ObjCProperty(name.as_ptr(), s))) }
})
}
pub fn from_objc_protocol<P: AsRef<str>>(protocol: P) -> Usr {
let string = utility::from_string(protocol);
unsafe { Usr(utility::to_string(clang_constructUSR_ObjCProtocol(string.as_ptr()))) }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Version {
pub x: u32,
pub y: Option<u32>,
pub z: Option<u32>,
}
impl Version {
fn from_raw(raw: CXVersion) -> Version {
Version {
x: raw.Major as u32,
y: raw.Minor.try_into().ok(),
z: raw.Subminor.try_into().ok()
}
}
}
pub fn get_version() -> String {
unsafe { utility::to_string(clang_getClangVersion()) }
}