class Cursor
Represents a cursor in the abstract syntax tree (AST).
Nested
Definitions
attr_reader :cursor
Signature
-
attribute
FFI::Lib::CXCursor The underlying libclang cursor structure.
attr_reader :translation_unit
Signature
-
attribute
TranslationUnit The translation unit this cursor belongs to.
def self.null_cursor
Get a null cursor.
Signature
-
returns
Cursor A null cursor instance.
Implementation
def self.null_cursor
Cursor.new Lib.get_null_cursor, nil
end
def self.kind_spelling(kind)
Get the spelling of a cursor kind.
Signature
-
parameter
kindSymbol The cursor kind.
-
returns
String The string representation of the cursor kind.
Implementation
def self.kind_spelling(kind)
Lib.extract_string Lib.get_cursor_kind_spelling(kind)
end
def kind_spelling
Get the spelling of the cursor kind.
Signature
-
returns
String The cursor kind spelling.
Implementation
def kind_spelling
Cursor.kind_spelling @cursor[:kind]
end
def initialize(cxcursor, translation_unit)
Initialize a cursor with a libclang cursor structure.
Signature
-
parameter
cxcursorLib::CXCursor The libclang cursor.
-
parameter
translation_unitTranslationUnit The parent translation unit.
Implementation
def initialize(cxcursor, translation_unit)
@cursor = cxcursor
@translation_unit = translation_unit
end
def null?
Check if this cursor is null.
Signature
-
returns
Boolean True if the cursor is null.
Implementation
def null?
Lib.cursor_is_null(@cursor) != 0
end
def raw_comment_text
Get the raw comment text associated with this cursor.
Signature
-
returns
String The raw comment text.
Implementation
def raw_comment_text
Lib.extract_string Lib.cursor_get_raw_comment_text(@cursor)
end
def comment
Get the parsed comment associated with this cursor.
Signature
-
returns
Comment The parsed comment structure.
Implementation
def comment
Comment.build_from Lib.cursor_get_parsed_comment(@cursor)
end
def comment_range
Get the source range of the comment.
Signature
-
returns
SourceRange The comment source range.
Implementation
def comment_range
SourceRange.new(Lib.cursor_get_comment_range(@cursor))
end
def completion
Get the code completion string for this cursor.
Signature
-
returns
CodeCompletion::String The completion string.
Implementation
def completion
CodeCompletion::String.new Lib.get_cursor_completion_string(@cursor)
end
def anonymous?
Check if this cursor is anonymous.
Signature
-
returns
Boolean True if the cursor is anonymous.
Implementation
def anonymous?
Lib.cursor_is_anonymous(@cursor) != 0
end
def anonymous_record_declaration?
Check if this cursor is an anonymous record declaration.
Signature
-
returns
Boolean True if it's an anonymous record declaration.
Implementation
def anonymous_record_declaration?
Lib.cursor_is_anonymous_record_decl(@cursor) != 0
end
def declaration?
Check if this cursor is a declaration.
Signature
-
returns
Boolean True if it's a declaration.
Implementation
def declaration?
Lib.is_declaration(kind) != 0
end
def reference?
Check if this cursor is a reference.
Signature
-
returns
Boolean True if it's a reference.
Implementation
def reference?
Lib.is_reference(kind) != 0
end
def expression?
Check if this cursor is an expression.
Signature
-
returns
Boolean True if it's an expression.
Implementation
def expression?
Lib.is_expression(kind) != 0
end
def statement?
Check if this cursor is a statement.
Signature
-
returns
Boolean True if it's a statement.
Implementation
def statement?
Lib.is_statement(kind) != 0
end
def attribute?
Check if this cursor is an attribute.
Signature
-
returns
Boolean True if it's an attribute.
Implementation
def attribute?
Lib.is_attribute(kind) != 0
end
def public?
Check if this cursor has public access.
Signature
-
returns
Boolean True if the cursor is public.
Implementation
def public?
Lib.cxx_get_access_specifier(@cursor) == :public
end
def private?
Check if this cursor has private access.
Signature
-
returns
Boolean True if the cursor is private.
Implementation
def private?
Lib.cxx_get_access_specifier(@cursor) == :private
end
def protected?
Check if this cursor has protected access.
Signature
-
returns
Boolean True if the cursor is protected.
Implementation
def protected?
Lib.cxx_get_access_specifier(@cursor) == :protected
end
def invalid?
Check if this cursor is invalid.
Signature
-
returns
Boolean True if the cursor is invalid.
Implementation
def invalid?
Lib.is_invalid(kind) != 0
end
def translation_unit?
Check if this cursor is a translation unit.
Signature
-
returns
Boolean True if it's a translation unit.
Implementation
def translation_unit?
Lib.is_translation_unit(kind) != 0
end
def preprocessing?
Check if this cursor is a preprocessing directive.
Signature
-
returns
Boolean True if it's a preprocessing directive.
Implementation
def preprocessing?
Lib.is_preprocessing(kind) != 0
end
def unexposed?
Check if this cursor is unexposed.
Signature
-
returns
Boolean True if the cursor is unexposed.
Implementation
def unexposed?
Lib.is_unexposed(kind) != 0
end
def expansion_location
Get the expansion location of this cursor.
Signature
-
returns
ExpansionLocation The expansion location.
Implementation
def expansion_location
ExpansionLocation.new(Lib.get_cursor_location(@cursor))
end
def presumed_location
Get the presumed location of this cursor.
Signature
-
returns
PresumedLocation The presumed location.
Implementation
def presumed_location
PresumedLocation.new(Lib.get_cursor_location(@cursor))
end
def spelling_location
Get the spelling location of this cursor.
Signature
-
returns
SpellingLocation The spelling location.
Implementation
def spelling_location
SpellingLocation.new(Lib.get_cursor_location(@cursor))
end
def file_location
Get the file location of this cursor.
Signature
-
returns
FileLocation The file location.
Implementation
def file_location
FileLocation.new(Lib.get_cursor_location(@cursor))
end
def extent
Get the source extent of this cursor.
Signature
-
returns
SourceRange The source extent.
Implementation
def extent
SourceRange.new(Lib.get_cursor_extent(@cursor))
end
def display_name
Get the display name of this cursor.
Signature
-
returns
String The display name.
Implementation
def display_name
Lib.extract_string Lib.get_cursor_display_name(@cursor)
end
def qualified_display_name
Get the qualified display name including parent scope.
Signature
-
returns
String | Nil The qualified display name, or
nilfor translation units.-
raises
ArgumentError If the semantic parent is invalid.
Implementation
def qualified_display_name
if self.kind != :cursor_translation_unit
if self.semantic_parent.kind == :cursor_invalid_file
raise(ArgumentError, "Invalid semantic parent: #{self}")
end
result = self.semantic_parent.qualified_display_name
result ? "#{result}::#{self.display_name}" : self.display_name
end
end
def qualified_name
Get the fully qualified name of this cursor.
Signature
-
returns
String | Nil The qualified name, or
nilfor translation units.-
raises
ArgumentError If the semantic parent is invalid.
Implementation
def qualified_name
if self.kind != :cursor_translation_unit
if self.semantic_parent.kind == :cursor_invalid_file
raise(ArgumentError, "Invalid semantic parent: #{self}")
end
result = self.semantic_parent.qualified_name
result ? "#{result}::#{self.spelling}" : self.spelling
end
end
def spelling
Get the spelling (name) of this cursor.
Signature
-
returns
String The cursor spelling.
Implementation
def spelling
Lib.extract_string Lib.get_cursor_spelling(@cursor)
end
def printing_policy
Get the printing policy for this cursor.
Signature
-
returns
PrintingPolicy The printing policy.
Implementation
def printing_policy
PrintingPolicy.new(cursor)
end
def usr
Get the Unified Symbol Resolution (USR) for this cursor.
Signature
-
returns
String The USR string.
Implementation
def usr
Lib.extract_string Lib.get_cursor_usr(@cursor)
end
def kind
Get the kind of this cursor.
Signature
-
returns
Symbol | Nil The cursor kind.
Implementation
def kind
@cursor ? @cursor[:kind] : nil
end
def type
Get the type of this cursor.
Signature
-
returns
Types::Type The cursor type.
Implementation
def type
Types::Type.create Lib.get_cursor_type(@cursor), @translation_unit
end
def result_type
Get the result type for a function cursor.
Signature
-
returns
Types::Type The result type.
Implementation
def result_type
Types::Type.create Lib.get_cursor_result_type(@cursor), @translation_unit
end
def underlying_type
Get the underlying type for a typedef cursor.
Signature
-
returns
Types::Type The underlying type.
Implementation
def underlying_type
Types::Type.create Lib.get_typedef_decl_underlying_type(@cursor), @translation_unit
end
def virtual_base?
Check if this cursor is a virtual base class.
Signature
-
returns
Boolean True if it's a virtual base.
Implementation
def virtual_base?
Lib.is_virtual_base(@cursor) != 0
end
def dynamic_call?
Check if this cursor is a dynamic call.
Signature
-
returns
Boolean True if it's a dynamic call.
Implementation
def dynamic_call?
Lib.is_dynamic_call(@cursor) != 0
end
def variadic?
Check if this cursor is variadic.
Signature
-
returns
Boolean True if the cursor is variadic.
Implementation
def variadic?
Lib.is_variadic(@cursor) != 0
end
def definition?
Check if this cursor is a definition.
Signature
-
returns
Boolean True if the cursor is a definition.
Implementation
def definition?
Lib.is_definition(@cursor) != 0
end
def static?
Check if this is a static method.
Signature
-
returns
Boolean True if the method is static.
Implementation
def static?
Lib.cxx_method_is_static(@cursor) != 0
end
def virtual?
Check if this is a virtual method.
Signature
-
returns
Boolean True if the method is virtual.
Implementation
def virtual?
Lib.cxx_method_is_virtual(@cursor) != 0
end
def pure_virtual?
Check if this is a pure virtual method.
Signature
-
returns
Boolean True if the method is pure virtual.
Implementation
def pure_virtual?
Lib.cxx_method_is_pure_virtual(@cursor) != 0
end
def enum_value
Get the value of an enum constant.
Signature
-
returns
Integer The enum value.
Implementation
def enum_value
Lib.get_enum_value @cursor
end
def enum_unsigned_value
Get the unsigned value of an enum constant.
Signature
-
returns
Integer The unsigned enum value.
Implementation
def enum_unsigned_value
Lib.get_enum_unsigned_value @cursor
end
def enum_type
Get the integer type of an enum declaration.
Signature
-
returns
Types::Type The enum's underlying integer type.
Implementation
def enum_type
Types::Type.create Lib.get_enum_decl_integer_type(@cursor), @translation_unit
end
def specialized_template
Get the template that this cursor specializes.
Signature
-
returns
Cursor The specialized template cursor.
Implementation
def specialized_template
Cursor.new Lib.get_specialized_cursor_template(@cursor), @translation_unit
end
def canonical
Get the canonical cursor for this cursor.
Signature
-
returns
Cursor The canonical cursor.
Implementation
def canonical
Cursor.new Lib.get_canonical_cursor(@cursor), @translation_unit
end
def definition
Get the definition cursor for this cursor.
Signature
-
returns
Cursor The definition cursor.
Implementation
def definition
Cursor.new Lib.get_cursor_definition(@cursor), @translation_unit
end
def opaque_declaration?
Check if this is an opaque declaration without a definition.
Signature
-
returns
Boolean True if it's an opaque declaration.
Implementation
def opaque_declaration?
# Is this a declaration that does not have a definition in the translation unit
self.declaration? && !self.definition? && self.definition.invalid?
end
def forward_declaration?
Check if this is a forward declaration.
Signature
-
returns
Boolean True if it's a forward declaration.
Implementation
def forward_declaration?
# Is this a forward declaration for a definition contained in the same translation_unit?
# https://joshpeterson.github.io/identifying-a-forward-declaration-with-libclang
#
# Possible alternate implementations?
# self.declaration? && !self.definition? && self.definition
# !self.definition? && self.definition
self.declaration? && !self.eql?(self.definition) && !self.definition.invalid?
end
def referenced
Get the cursor referenced by this cursor.
Signature
-
returns
Cursor The referenced cursor.
Implementation
def referenced
Cursor.new Lib.get_cursor_referenced(@cursor), @translation_unit
end
def semantic_parent
Get the semantic parent of this cursor.
Signature
-
returns
Cursor The semantic parent cursor.
Implementation
def semantic_parent
Cursor.new Lib.get_cursor_semantic_parent(@cursor), @translation_unit
end
def lexical_parent
Get the lexical parent of this cursor.
Signature
-
returns
Cursor The lexical parent cursor.
Implementation
def lexical_parent
Cursor.new Lib.get_cursor_lexical_parent(@cursor), @translation_unit
end
def template_kind
Get the template cursor kind.
Signature
-
returns
Symbol The template cursor kind.
Implementation
def template_kind
Lib.get_template_cursor_kind @cursor
end
def access_specifier
Get the C++ access specifier.
Signature
-
returns
Symbol The access specifier (
:public,:private, or:protected).
Implementation
def access_specifier
Lib.get_cxx_access_specifier @cursor
end
def language
Get the programming language of this cursor.
Signature
-
returns
Symbol The language symbol.
Implementation
def language
Lib.get_language @cursor
end
def num_args
Get the number of arguments for this cursor.
Signature
-
returns
Integer The number of arguments.
Implementation
def num_args
Lib.get_num_args @cursor
end
def each(recurse = true, &block)
Iterate over child cursors.
Signature
-
parameter
recurseBoolean Whether to recurse into children by default.
-
yields
{|cursor, parent| ...} Each child cursor with its parent.
-
parameter
cursorCursor The child cursor.
-
parameter
parentCursor The parent cursor.
-
parameter
-
returns
Enumerator If no block is given.
Implementation
def each(recurse = true, &block)
return to_enum(:each, recurse) unless block_given?
adapter = Proc.new do |cxcursor, parent_cursor, unused|
# Call the block and capture the result. This lets advanced users
# modify the recursion on a case by case basis if needed
result = block.call Cursor.new(cxcursor, @translation_unit), Cursor.new(parent_cursor, @translation_unit)
case result
when :continue
:continue
when :recurse
:recurse
else
recurse ? :recurse : :continue
end
end
Lib.visit_children(@cursor, adapter, nil)
end
def visit_children(&block)
Visit only direct children without recursing.
Signature
-
yields
{|cursor, parent| ...} Each direct child cursor.
-
parameter
cursorCursor The child cursor.
-
parameter
parentCursor The parent cursor.
-
parameter
Implementation
def visit_children(&block)
each(false, &block)
end
def ancestors_by_kind(*kinds)
Find ancestors of this cursor by kind.
Signature
-
parameter
kindsArray(Symbol) The cursor kinds to search for.
-
returns
Array(Cursor) Array of ancestor cursors matching the kinds.
Implementation
def ancestors_by_kind(*kinds)
result = Array.new
parent = self
while parent != self.semantic_parent
parent = self.semantic_parent
if kinds.include?(parent.kind)
result << parent
end
end
result
end
def find_by_kind(recurse, *kinds)
Find child cursors by kind.
Signature
-
parameter
recurseBoolean | Nil Whether to recurse into children.
-
parameter
kindsArray(Symbol) The cursor kinds to search for.
-
returns
Array(Cursor) Array of matching cursors.
-
raises
RuntimeError If recurse parameter is not nil or boolean.
Implementation
def find_by_kind(recurse, *kinds)
unless (recurse == nil || recurse == true || recurse == false)
raise("Recurse parameter must be nil or a boolean value. Value was: #{recurse}")
end
result = Array.new
self.each(recurse) do |child, parent|
if kinds.include?(child.kind)
result << child
end
end
result
end
def find_references_in_file(file = nil, &block)
Find all references to this cursor in a file.
Signature
-
parameter
fileString | Nil The file path, or
nilto use the translation unit file.-
yields
{|cursor, range| ...} Each reference with its cursor and source range.
-
parameter
cursorCursor The reference cursor.
-
parameter
rangeSourceRange The source range of the reference.
-
parameter
Implementation
def find_references_in_file(file = nil, &block)
file ||= Lib.extract_string Lib.get_translation_unit_spelling(@translation_unit)
visit_adapter = Proc.new do |unused, cxcursor, cxsource_range|
block.call Cursor.new(cxcursor, @translation_unit), SourceRange.new(cxsource_range)
end
visitor = FFI::Clang::Lib::CXCursorAndRangeVisitor.new
visitor[:visit] = visit_adapter
Lib.find_references_in_file(@cursor, Lib.get_file(@translation_unit, file), visitor)
end
def linkage
Get the linkage of this cursor.
Signature
-
returns
Symbol The linkage kind.
Implementation
def linkage
Lib.get_cursor_linkage(@cursor)
end
def exception_specification
Get the exception specification type for this cursor.
Signature
-
returns
Symbol The exception specification type.
Implementation
def exception_specification
Lib.get_cursor_exception_specification_type(@cursor)
end
def availability
Get the availability of this cursor.
Signature
-
returns
Symbol The availability status.
Implementation
def availability
Lib.get_cursor_availability(@cursor)
end
def included_file
Get the file included by this cursor.
Signature
-
returns
File The included file.
Implementation
def included_file
File.new Lib.get_included_file(@cursor), @translation_unit
end
def platform_availability(max_availability_size = 4)
Get platform availability information for this cursor.
Signature
-
parameter
max_availability_sizeInteger Maximum number of platforms to query.
-
returns
Hash Platform availability information.
Implementation
def platform_availability(max_availability_size = 4)
availability_ptr = FFI::MemoryPointer.new(Lib::CXPlatformAvailability, max_availability_size)
always_deprecated_ptr = FFI::MemoryPointer.new :int
always_unavailable_ptr = FFI::MemoryPointer.new :int
deprecated_message_ptr = FFI::MemoryPointer.new Lib::CXString
unavailable_message_ptr = FFI::MemoryPointer.new Lib::CXString
actual_availability_size = Lib.get_cursor_platform_availability(
@cursor,
always_deprecated_ptr, deprecated_message_ptr,
always_unavailable_ptr, unavailable_message_ptr,
availability_ptr, max_availability_size)
availability = []
cur_ptr = availability_ptr
[actual_availability_size, max_availability_size].min.times {availability << PlatformAvailability.new(cur_ptr)
cur_ptr += Lib::CXPlatformAvailability.size
}
# return as Hash
{
always_deprecated: always_deprecated_ptr.get_int(0),
always_unavailable: always_unavailable_ptr.get_int(0),
deprecated_message: Lib.extract_string(Lib::CXString.new(deprecated_message_ptr)),
unavailable_message: Lib.extract_string(Lib::CXString.new(unavailable_message_ptr)),
availability: availability
}
end
def overriddens
Get all cursors that this cursor overrides.
Signature
-
returns
Array(Cursor) Array of overridden cursors.
Implementation
def overriddens
cursor_ptr = FFI::MemoryPointer.new :pointer
num_ptr = FFI::MemoryPointer.new :uint
Lib.get_overridden_cursors(@cursor, cursor_ptr, num_ptr)
num = num_ptr.get_uint(0)
cur_ptr = cursor_ptr.get_pointer(0)
overriddens = []
num.times {overriddens << Cursor.new(cur_ptr, @translation_unit)
cur_ptr += Lib::CXCursor.size
}
Lib.dispose_overridden_cursors(cursor_ptr.get_pointer(0)) if num != 0
overriddens
end
def bitfield?
Check if this cursor represents a bitfield.
Signature
-
returns
Boolean True if it's a bitfield.
Implementation
def bitfield?
Lib.is_bit_field(@cursor) != 0
end
def bitwidth
Get the bit width of a bitfield.
Signature
-
returns
Integer The bitfield width.
Implementation
def bitwidth
Lib.get_field_decl_bit_width(@cursor)
end
def overloaded_decl(i)
Get an overloaded declaration by index.
Signature
-
parameter
iInteger The index of the overloaded declaration.
-
returns
Cursor The overloaded declaration cursor.
Implementation
def overloaded_decl(i)
Cursor.new Lib.get_overloaded_decl(@cursor, i), @translation_unit
end
def num_overloaded_decls
Get the number of overloaded declarations.
Signature
-
returns
Integer The number of overloaded declarations.
Implementation
def num_overloaded_decls
Lib.get_num_overloaded_decls(@cursor)
end
def objc_type_encoding
Get the Objective-C type encoding.
Signature
-
returns
String The Objective-C type encoding.
Implementation
def objc_type_encoding
Lib.extract_string Lib.get_decl_objc_type_encoding(@cursor)
end
def argument(i)
Get a function or method argument by index.
Signature
-
parameter
iInteger The argument index.
-
returns
Cursor The argument cursor.
Implementation
def argument(i)
Cursor.new Lib.cursor_get_argument(@cursor, i), @translation_unit
end
def num_arguments
Get the number of arguments.
Signature
-
returns
Integer The number of arguments.
Implementation
def num_arguments
Lib.cursor_get_num_arguments(@cursor)
end
def eql?(other)
Check if this cursor equals another cursor.
Signature
-
parameter
otherCursor The cursor to compare with.
-
returns
Boolean True if the cursors are equal.
Implementation
def eql?(other)
Lib.are_equal(@cursor, other.cursor) != 0
end
def hash
Get the hash code for this cursor.
Signature
-
returns
Integer The hash code.
Implementation
def hash
Lib.get_cursor_hash(@cursor)
end
def to_s
Get a string representation of this cursor.
Signature
-
returns
String The cursor string representation.
Implementation
def to_s
"Cursor <#{self.kind.to_s.gsub(/^cursor_/, '')}: #{self.spelling}>"
end
def references(file = nil)
Find all references to this cursor.
Signature
-
parameter
fileString | Nil The file to search in, or
nilfor the translation unit file.-
returns
Array(Cursor) Array of reference cursors.
Implementation
def references(file = nil)
refs = []
self.find_references_in_file(file) do |cursor, unused|
refs << cursor
:continue
end
refs
end
def converting_constructor?
Check if this is a converting constructor.
Signature
-
returns
Boolean True if it's a converting constructor.
Implementation
def converting_constructor?
Lib.is_converting_constructor(@cursor) != 0
end
def copy_constructor?
Check if this is a copy constructor.
Signature
-
returns
Boolean True if it's a copy constructor.
Implementation
def copy_constructor?
Lib.is_copy_constructor(@cursor) != 0
end
def default_constructor?
Check if this is a default constructor.
Signature
-
returns
Boolean True if it's a default constructor.
Implementation
def default_constructor?
Lib.is_default_constructor(@cursor) != 0
end
def move_constructor?
Check if this is a move constructor.
Signature
-
returns
Boolean True if it's a move constructor.
Implementation
def move_constructor?
Lib.is_move_constructor(@cursor) != 0
end
def mutable?
Check if this cursor is mutable.
Signature
-
returns
Boolean True if it's mutable.
Implementation
def mutable?
Lib.is_mutable(@cursor) != 0
end
def defaulted?
Check if this cursor is defaulted.
Signature
-
returns
Boolean True if it's defaulted.
Implementation
def defaulted?
Lib.is_defaulted(@cursor) != 0
end
def deleted?
Check if this cursor is deleted.
Signature
-
returns
Boolean True if it's deleted.
Implementation
def deleted?
Lib.is_deleted(@cursor) != 0
end
def copy_assignment_operator?
Check if this is a copy assignment operator.
Signature
-
returns
Boolean True if it's a copy assignment operator.
Implementation
def copy_assignment_operator?
Lib.is_copy_assignment_operator(@cursor) != 0
end
def move_assignment_operator?
Check if this is a move assignment operator.
Signature
-
returns
Boolean True if it's a move assignment operator.
Implementation
def move_assignment_operator?
Lib.is_move_assignment_operator(@cursor) != 0
end
def explicit?
Check if this cursor is explicit.
Signature
-
returns
Boolean True if it's explicit.
Implementation
def explicit?
Lib.is_explicit(@cursor) != 0
end
def abstract?
Check if this cursor is abstract.
Signature
-
returns
Boolean True if it's abstract.
Implementation
def abstract?
Lib.is_abstract(@cursor) != 0
end
def enum_scoped?
Check if this is a scoped enum.
Signature
-
returns
Boolean True if it's a scoped enum.
Implementation
def enum_scoped?
Lib.is_enum_scoped(@cursor) != 0
end
def const?
Check if this cursor is const-qualified.
Signature
-
returns
Boolean True if it's const.
Implementation
def const?
Lib.is_const(@cursor) != 0
end