summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-02-07 14:33:57 -0800
committerNick Fitzgerald <fitzgen@gmail.com>2017-02-08 10:04:08 -0800
commit775c15c3dcfa488c0ca4236805606f345fbbc2e2 (patch)
tree8ee4421cfbad6a1192d7031d3628b75f1dbf1842
parent910b0d6458f51e553b0e229af41fa313b3d3f10c (diff)
Introduce a CanonicalDeclaration type
The `CanonicalTypeDeclaration` type exists as proof-by-construction that its cursor is the canonical declaration for its type. If you have a `CanonicalTypeDeclaration` instance, you know for sure that the type and cursor match up in a canonical declaration relationship, and it simply cannot be otherwise.
-rw-r--r--src/clang.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/clang.rs b/src/clang.rs
index b35d2187..6474db2c 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -684,6 +684,31 @@ impl Type {
}
}
+ /// Get the canonical declaration of this type, if it is available.
+ pub fn canonical_declaration(&self,
+ location: Option<&Cursor>)
+ -> Option<CanonicalTypeDeclaration> {
+ let mut declaration = self.declaration();
+ if !declaration.is_valid() {
+ if let Some(location) = location {
+ let mut location = *location;
+ if let Some(referenced) = location.referenced() {
+ location = referenced;
+ }
+ if location.is_template_like() {
+ declaration = location;
+ }
+ }
+ }
+
+ let canonical = declaration.canonical();
+ if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound {
+ Some(CanonicalTypeDeclaration(*self, canonical))
+ } else {
+ None
+ }
+ }
+
/// Get a raw display name for this type.
pub fn spelling(&self) -> String {
unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) }
@@ -874,6 +899,26 @@ impl Type {
}
}
+/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
+/// cursor is the canonical declaration for its type. If you have a
+/// `CanonicalTypeDeclaration` instance, you know for sure that the type and
+/// cursor match up in a canonical declaration relationship, and it simply
+/// cannot be otherwise.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct CanonicalTypeDeclaration(Type, Cursor);
+
+impl CanonicalTypeDeclaration {
+ /// Get the type.
+ pub fn ty(&self) -> &Type {
+ &self.0
+ }
+
+ /// Get the type's canonical declaration cursor.
+ pub fn cursor(&self) -> &Cursor {
+ &self.1
+ }
+}
+
/// An iterator for a type's template arguments.
pub struct TypeTemplateArgIterator {
x: CXType,