From 87a862dc2a0e6a0a6f290f93fd6dd32f80495cd0 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski Date: Wed, 18 Dec 2024 00:43:49 +0000 Subject: [PATCH] Fix crate item lookup by import path for `@optional` import paths. --- src/adapter/optimizations/item_lookup.rs | 4 +- src/adapter/tests.rs | 60 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/adapter/optimizations/item_lookup.rs b/src/adapter/optimizations/item_lookup.rs index 8778fc6..53bb2f6 100644 --- a/src/adapter/optimizations/item_lookup.rs +++ b/src/adapter/optimizations/item_lookup.rs @@ -18,9 +18,9 @@ pub(crate) fn resolve_crate_items<'a, V: AsVertex> + 'a>( ) -> ContextOutcomeIterator<'a, V, VertexIterator<'a, Vertex<'a>>> { let destination = resolve_info.destination(); - // Is the `importable_path` edge being resolved in a subsequent step? + // Is the `importable_path` edge being resolved in a mandatory fashion in a subsequent step? if let Some(neighbor_info) = destination - .first_edge("importable_path") + .first_mandatory_edge("importable_path") .as_ref() .map(|x| x.destination()) { diff --git a/src/adapter/tests.rs b/src/adapter/tests.rs index 1c183b9..a0836b5 100644 --- a/src/adapter/tests.rs +++ b/src/adapter/tests.rs @@ -3941,3 +3941,63 @@ fn extern_fn() { expected_results.sort_unstable(); similar_asserts::assert_eq!(expected_results, results); } + +#[test] +fn item_lookup_by_path_optimization() { + // Any test crate with non-public top-level items would work for this test. + get_test_data!(data, associated_consts); + let adapter = RustdocAdapter::new(&data, None); + let adapter = Arc::new(&adapter); + + let query = r#" +{ + Crate { + item { + ... on Function { + name @output + + # Since this edge is optional, this query matches: + # - functions with an importable path matching the filter, and + # - functions that *do not have* importable paths at all. + # + # Failure to return both of these means we have a bug in + # the "item lookup by importable path" optimization code path. + importable_path @optional { + public_api @output + path @output @filter(op: "=", value: ["$path"]) + } + } + } + } +} + "#; + + let variables = btreemap! { + "path" => vec!["associated_consts", "will_not_match", "anything"], + }; + + let schema = + Schema::parse(include_str!("../rustdoc_schema.graphql")).expect("schema failed to parse"); + + #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, serde::Deserialize)] + struct Output { + name: String, + public_api: Option, + path: Option>, + } + + let mut results: Vec<_> = + trustfall::execute_query(&schema, adapter.clone(), query, variables.clone()) + .expect("failed to run query") + .map(|row| row.try_into_struct().expect("shape mismatch")) + .collect(); + results.sort_unstable(); + + let mut expected_results = vec![Output { + name: "min_batch_size".into(), + public_api: None, + path: None, + }]; + expected_results.sort_unstable(); + similar_asserts::assert_eq!(expected_results, results); +}