Skip to content

Commit 5180ee4

Browse files
committed
clang: Clean up source order sorting.
This doesn't change behavior but is easier to debug and reason about (because you have the relevant cursors there).
1 parent 264075a commit 5180ee4

File tree

2 files changed

+56
-79
lines changed

2 files changed

+56
-79
lines changed

bindgen/clang.rs

Lines changed: 53 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -498,23 +498,21 @@ impl Cursor {
498498
}
499499
}
500500

501-
/// Traverse this curser's children, sorted by where they appear in source code.
501+
/// Traverse all of this cursor's children, sorted by where they appear in source code.
502502
///
503503
/// Call the given function on each AST node traversed.
504504
pub(crate) fn visit_sorted<Visitor>(
505505
&self,
506506
ctx: &mut BindgenContext,
507507
mut visitor: Visitor,
508508
) where
509-
Visitor: FnMut(&mut BindgenContext, Cursor) -> CXChildVisitResult,
509+
Visitor: FnMut(&mut BindgenContext, Cursor),
510510
{
511511
let mut children = self.collect_children();
512-
513512
for child in &children {
514513
if child.kind() == CXCursor_InclusionDirective {
515514
if let Some(included_file) = child.get_included_file_name() {
516515
let location = child.location();
517-
518516
let (source_file, _, _, offset) = location.location();
519517

520518
if let Some(source_file) = source_file.name() {
@@ -523,19 +521,62 @@ impl Cursor {
523521
}
524522
}
525523
}
526-
527-
children.sort_by(|child1, child2| {
528-
child1
529-
.location()
530-
.partial_cmp_with_context(&child2.location(), ctx)
531-
.unwrap_or(std::cmp::Ordering::Equal)
532-
});
533-
524+
children.sort_by(|child1, child2| child1.cmp_by_source_order(child2, ctx));
534525
for child in children {
535526
visitor(ctx, child);
536527
}
537528
}
538529

530+
/// Compare source order of two cursors, considering `#include` directives.
531+
///
532+
/// Built-in items provided by the compiler (which don't have a source file),
533+
/// are sorted first. Remaining files are sorted by their position in the source file.
534+
/// If the items' source files differ, they are sorted by the position of the first
535+
/// `#include` for their source file. If no source files are included, `None` is returned.
536+
fn cmp_by_source_order(&self, other: &Self, ctx: &BindgenContext) -> cmp::Ordering {
537+
let (file, _, _, offset) = self.location().location();
538+
let (other_file, _, _, other_offset) = other.location().location();
539+
540+
let (file, other_file) = match (file.name(), other_file.name()) {
541+
(Some(file), Some(other_file)) => (file, other_file),
542+
// Built-in definitions should come first.
543+
(Some(_), None) => return cmp::Ordering::Greater,
544+
(None, Some(_)) => return cmp::Ordering::Less,
545+
(None, None) => return cmp::Ordering::Equal,
546+
};
547+
548+
if file == other_file {
549+
// Both items are in the same source file, compare by byte offset.
550+
return offset.cmp(&other_offset);
551+
}
552+
553+
let include_location = ctx.included_file_location(&file);
554+
let other_include_location = ctx.included_file_location(&other_file);
555+
match (include_location, other_include_location) {
556+
(Some((file2, offset2)), _) if file2 == other_file => {
557+
offset2.cmp(&other_offset)
558+
}
559+
(Some(_), None) => cmp::Ordering::Greater,
560+
(_, Some((other_file2, other_offset2)))
561+
if file == other_file2 =>
562+
{
563+
offset.cmp(&other_offset2)
564+
}
565+
(None, Some(_)) => cmp::Ordering::Less,
566+
(
567+
Some((file2, offset2)),
568+
Some((other_file2, other_offset2)),
569+
) => {
570+
if file2 == other_file2 {
571+
offset2.cmp(&other_offset2)
572+
} else {
573+
cmp::Ordering::Equal
574+
}
575+
}
576+
(None, None) => cmp::Ordering::Equal,
577+
}
578+
}
579+
539580
/// Collect all of this cursor's children into a vec and return them.
540581
pub(crate) fn collect_children(&self) -> Vec<Cursor> {
541582
let mut children = vec![];
@@ -1564,63 +1605,6 @@ impl SourceLocation {
15641605
}
15651606
}
15661607

1567-
impl SourceLocation {
1568-
/// Compare source locations, also considering `#include` directives.
1569-
///
1570-
/// Built-in items provided by the compiler (which don't have a source file),
1571-
/// are sorted first. Remaining files are sorted by their position in the source file.
1572-
/// If the items' source files differ, they are sorted by the position of the first
1573-
/// `#include` for their source file. If no source files are included, `None` is returned.
1574-
pub(crate) fn partial_cmp_with_context(
1575-
&self,
1576-
other: &Self,
1577-
ctx: &BindgenContext,
1578-
) -> Option<cmp::Ordering> {
1579-
let (file, _, _, offset) = self.location();
1580-
let (other_file, _, _, other_offset) = other.location();
1581-
1582-
match (file.name(), other_file.name()) {
1583-
(Some(file), Some(other_file)) => {
1584-
if file == other_file {
1585-
return offset.partial_cmp(&other_offset);
1586-
}
1587-
1588-
let include_location = ctx.included_file_location(&file);
1589-
let other_include_location =
1590-
ctx.included_file_location(&other_file);
1591-
1592-
match (include_location, other_include_location) {
1593-
(Some((file2, offset2)), _) if file2 == other_file => {
1594-
offset2.partial_cmp(&other_offset)
1595-
}
1596-
(Some(_), None) => Some(cmp::Ordering::Greater),
1597-
(_, Some((other_file2, other_offset2)))
1598-
if file == other_file2 =>
1599-
{
1600-
offset.partial_cmp(&other_offset2)
1601-
}
1602-
(None, Some(_)) => Some(cmp::Ordering::Less),
1603-
(
1604-
Some((file2, offset2)),
1605-
Some((other_file2, other_offset2)),
1606-
) => {
1607-
if file2 == other_file2 {
1608-
offset2.partial_cmp(&other_offset2)
1609-
} else {
1610-
None
1611-
}
1612-
}
1613-
(None, None) => Some(cmp::Ordering::Equal),
1614-
}
1615-
}
1616-
// Built-in definitions should come first.
1617-
(Some(_), None) => Some(cmp::Ordering::Greater),
1618-
(None, Some(_)) => Some(cmp::Ordering::Less),
1619-
(None, None) => Some(cmp::Ordering::Equal),
1620-
}
1621-
}
1622-
}
1623-
16241608
impl fmt::Display for SourceLocation {
16251609
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16261610
let (file, line, col, _) = self.location();

bindgen/lib.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,25 +1080,18 @@ fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
10801080
}
10811081

10821082
/// Parse one `Item` from the Clang cursor.
1083-
fn parse_one(
1084-
ctx: &mut BindgenContext,
1085-
cursor: clang::Cursor,
1086-
parent: Option<ItemId>,
1087-
) -> clang_sys::CXChildVisitResult {
1083+
fn parse_one(ctx: &mut BindgenContext, cursor: clang::Cursor, parent: Option<ItemId>) {
10881084
if !filter_builtins(ctx, &cursor) {
1089-
return CXChildVisit_Continue;
1085+
return;
10901086
}
10911087

1092-
use clang_sys::CXChildVisit_Continue;
10931088
match Item::parse(cursor, parent, ctx) {
10941089
Ok(..) => {}
10951090
Err(ParseError::Continue) => {}
10961091
Err(ParseError::Recurse) => {
1097-
cursor
1098-
.visit_sorted(ctx, |ctx, child| parse_one(ctx, child, parent));
1092+
cursor.visit_sorted(ctx, |ctx, child| parse_one(ctx, child, parent));
10991093
}
11001094
}
1101-
CXChildVisit_Continue
11021095
}
11031096

11041097
/// Parse the Clang AST into our `Item` internal representation.

0 commit comments

Comments
 (0)