You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix a few issues with infinite recursions if the content contains cyclic curation (#898)
* Add functions to operate on directed graphs
* Update topic graph to use sequences for graph traversal
* Avoid computing full paths to determine if a symbol is manually curated
* Fix an infinite recursion determining the paths to a node when there's cyclic curation
rdar://126974763
* Avoid computing all paths when the caller only needs the shortest path
* Avoid computing all paths when the caller only needs the roots/leaves
* Avoid computing all paths when the caller only needs know if a certain node is encountered
* Avoid computing all paths when the caller only needs to visit each reachable node once
* Rename 'pathsTo(_:options:)' to 'finitePaths(to:options:)
* Fix another infinite recursion when pages are curated in cycles
rdar://126974763
* Fix correctness issue where symbol has two auto curated parents
* Address code review feedback:
- Rename neighbors parameter to edges for DirectedGraph initializer
- Rename GraphPathIterator and move it to DirectedGraph+Paths file
- Add convenience properties for topic graph directed graph "views
- Elaborate on breadcrumbs path documentation and implementation comments
- Elaborate on graph cycle documentation with concrete examples
- Fix missing edge in directed graph test data
- Use preconditionFailure for topic graph node that should always exist
- Add additional graph cycle tests
* Explicitly exit (trap) if trying to dump a topic graph with cyclic paths
/// Finds all finite (acyclic) paths, also called "breadcrumbs", to the given reference in the topic graph.
21
+
///
22
+
/// Each path is a list of references that describe a walk through the topic graph from a leaf node up to, but not including, the given `reference`.
23
+
///
24
+
/// The first path is the canonical path to the node. The other paths are sorted by increasing length (number of components).
25
+
///
26
+
/// > Note:
27
+
/// If all paths from the given reference are infinite (cycle back on themselves) then this function will return an empty list, because there are no _finite_ paths in the topic graph from that reference.
28
+
///
29
+
/// - Parameters:
30
+
/// - reference: The reference to find paths to.
31
+
/// - options: Options for how the context produces node breadcrumbs.
32
+
/// - Returns: A list of finite paths to the given reference in the topic graph.
// Graph traversal typically happens from the starting point outwards, but the callers of `finitePaths(to:options:)`
37
+
// expect paths going inwards from the leaves to the starting point, excluding the starting point itself.
38
+
// To match the caller's expectations we remove the starting point and then flip the paths.
39
+
.map{ $0.dropFirst().reversed()}
40
+
.sorted{(lhs, rhs)->Boolin
41
+
// Order a path rooted in a technology as the canonical one.
42
+
if options.contains(.preferTechnologyRoot),let first = lhs.first {
43
+
returntry!entity(with: first).semantic is Technology
44
+
}
45
+
46
+
returnbreadcrumbsAreInIncreasingOrder(lhs, rhs)
47
+
}
48
+
}
49
+
50
+
/// Finds the shortest finite (acyclic) path, also called "breadcrumb", to the given reference in the topic graph.
51
+
///
52
+
/// The path is a list of references that describe a walk through the topic graph from a leaf node up to, but not including, the given `reference`.
53
+
///
54
+
/// > Note:
55
+
/// If all paths from the given reference are infinite (cycle back on themselves) then this function will return `nil`, because there are no _finite_ paths in the topic graph from that reference.
56
+
///
57
+
/// - Parameter reference: The reference to find the shortest path to.
58
+
/// - Returns: The shortest path to the given reference, or `nil` if all paths to the reference are infinite (contain cycles).
// Graph traversal typically happens from the starting point outwards, but the callers of `shortestFinitePaths(to:)`
63
+
// expect paths going inwards from the leaves to the starting point, excluding the starting point itself.
64
+
// To match the caller's expectations we remove the starting point and then flip the paths.
65
+
.map{ $0.dropFirst().reversed()}
66
+
.min(by: breadcrumbsAreInIncreasingOrder)
67
+
}
68
+
69
+
/// Finds all the reachable root node references from the given reference.
70
+
///
71
+
/// > Note:
72
+
/// If all paths from the given reference are infinite (cycle back on themselves) then this function will return an empty set, because there are no reachable roots in the topic graph from that reference.
73
+
///
74
+
/// - Parameter reference: The reference to find reachable root node references from.
75
+
/// - Returns: The references of the root nodes that are reachable fro the given reference, or `[]` if all paths from the reference are infinite (contain cycles).
/// Compares two breadcrumbs for sorting so that the breadcrumb with fewer components come first and breadcrumbs with the same number of components are sorted alphabetically.
0 commit comments