Skip to content

Commit 2034a0f

Browse files
authored
clang: Clean up source order sorting. (#2557)
This doesn't change behavior but is easier to debug and reason about (because you have the relevant cursors there).
1 parent 74917da commit 2034a0f

File tree

2 files changed

+55
-73
lines changed

2 files changed

+55
-73
lines changed

bindgen/clang.rs

+53-69
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
525+
.sort_by(|child1, child2| child1.cmp_by_source_order(child2, ctx));
534526
for child in children {
535527
visitor(ctx, child);
536528
}
537529
}
538530

531+
/// Compare source order of two cursors, considering `#include` directives.
532+
///
533+
/// Built-in items provided by the compiler (which don't have a source file),
534+
/// are sorted first. Remaining files are sorted by their position in the source file.
535+
/// If the items' source files differ, they are sorted by the position of the first
536+
/// `#include` for their source file. If no source files are included, `None` is returned.
537+
fn cmp_by_source_order(
538+
&self,
539+
other: &Self,
540+
ctx: &BindgenContext,
541+
) -> cmp::Ordering {
542+
let (file, _, _, offset) = self.location().location();
543+
let (other_file, _, _, other_offset) = other.location().location();
544+
545+
let (file, other_file) = match (file.name(), other_file.name()) {
546+
(Some(file), Some(other_file)) => (file, other_file),
547+
// Built-in definitions should come first.
548+
(Some(_), None) => return cmp::Ordering::Greater,
549+
(None, Some(_)) => return cmp::Ordering::Less,
550+
(None, None) => return cmp::Ordering::Equal,
551+
};
552+
553+
if file == other_file {
554+
// Both items are in the same source file, compare by byte offset.
555+
return offset.cmp(&other_offset);
556+
}
557+
558+
let include_location = ctx.included_file_location(&file);
559+
let other_include_location = ctx.included_file_location(&other_file);
560+
match (include_location, other_include_location) {
561+
(Some((file2, offset2)), _) if file2 == other_file => {
562+
offset2.cmp(&other_offset)
563+
}
564+
(Some(_), None) => cmp::Ordering::Greater,
565+
(_, Some((other_file2, other_offset2))) if file == other_file2 => {
566+
offset.cmp(&other_offset2)
567+
}
568+
(None, Some(_)) => cmp::Ordering::Less,
569+
(Some((file2, offset2)), Some((other_file2, other_offset2))) => {
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

+2-4
Original file line numberDiff line numberDiff line change
@@ -1084,12 +1084,11 @@ fn parse_one(
10841084
ctx: &mut BindgenContext,
10851085
cursor: clang::Cursor,
10861086
parent: Option<ItemId>,
1087-
) -> clang_sys::CXChildVisitResult {
1087+
) {
10881088
if !filter_builtins(ctx, &cursor) {
1089-
return CXChildVisit_Continue;
1089+
return;
10901090
}
10911091

1092-
use clang_sys::CXChildVisit_Continue;
10931092
match Item::parse(cursor, parent, ctx) {
10941093
Ok(..) => {}
10951094
Err(ParseError::Continue) => {}
@@ -1098,7 +1097,6 @@ fn parse_one(
10981097
.visit_sorted(ctx, |ctx, child| parse_one(ctx, child, parent));
10991098
}
11001099
}
1101-
CXChildVisit_Continue
11021100
}
11031101

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

0 commit comments

Comments
 (0)