Skip to content

Commit

Permalink
Add top-level constants to the adapter. (#195) (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
obi1kenobi authored Jul 12, 2023
1 parent d8630f9 commit a58598f
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 41 deletions.
20 changes: 18 additions & 2 deletions src/adapter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use rustdoc_types::Item;
use trustfall::{
provider::{
resolve_coercion_with, Adapter, ContextIterator, ContextOutcomeIterator, EdgeParameters,
Expand Down Expand Up @@ -92,6 +93,7 @@ impl<'a> Adapter<'a> for RustdocAdapter<'a> {
"Item" => properties::resolve_item_property(contexts, property_name),
"ImplOwner" | "Struct" | "StructField" | "Enum" | "Variant" | "PlainVariant"
| "TupleVariant" | "StructVariant" | "Trait" | "Function" | "Method" | "Impl"
| "Constant"
if matches!(
property_name.as_ref(),
"id" | "crate_id" | "name" | "docs" | "attrs" | "visibility_limit"
Expand Down Expand Up @@ -146,7 +148,7 @@ impl<'a> Adapter<'a> for RustdocAdapter<'a> {
match type_name.as_ref() {
"CrateDiff" => edges::resolve_crate_diff_edge(contexts, edge_name),
"Crate" => edges::resolve_crate_edge(self, contexts, edge_name, resolve_info),
"Importable" | "ImplOwner" | "Struct" | "Enum" | "Trait" | "Function"
"Importable" | "ImplOwner" | "Struct" | "Enum" | "Trait" | "Function" | "Constant"
if matches!(edge_name.as_ref(), "importable_path" | "canonical_path") =>
{
edges::resolve_importable_edge(
Expand All @@ -158,7 +160,7 @@ impl<'a> Adapter<'a> for RustdocAdapter<'a> {
}
"Item" | "ImplOwner" | "Struct" | "StructField" | "Enum" | "Variant"
| "PlainVariant" | "TupleVariant" | "StructVariant" | "Trait" | "Function"
| "Method" | "Impl"
| "Method" | "Impl" | "Constant"
if matches!(edge_name.as_ref(), "span" | "attribute") =>
{
edges::resolve_item_edge(contexts, edge_name)
Expand Down Expand Up @@ -242,3 +244,17 @@ impl<'a> Adapter<'a> for RustdocAdapter<'a> {
}
}
}

pub(crate) fn supported_item_kind(item: &Item) -> bool {
matches!(
item.inner,
rustdoc_types::ItemEnum::Struct(..)
| rustdoc_types::ItemEnum::StructField(..)
| rustdoc_types::ItemEnum::Enum(..)
| rustdoc_types::ItemEnum::Variant(..)
| rustdoc_types::ItemEnum::Function(..)
| rustdoc_types::ItemEnum::Impl(..)
| rustdoc_types::ItemEnum::Trait(..)
| rustdoc_types::ItemEnum::Constant(..)
)
}
20 changes: 3 additions & 17 deletions src/adapter/optimizations/item_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,7 @@ fn resolve_item_vertices<'a>(
origin: Origin,
items: impl Iterator<Item = &'a Item> + 'a,
) -> VertexIterator<'a, Vertex<'a>> {
Box::new(
items
.filter(|item| {
// Filter out item types that are not currently supported.
matches!(
item.inner,
rustdoc_types::ItemEnum::Struct(..)
| rustdoc_types::ItemEnum::StructField(..)
| rustdoc_types::ItemEnum::Enum(..)
| rustdoc_types::ItemEnum::Variant(..)
| rustdoc_types::ItemEnum::Function(..)
| rustdoc_types::ItemEnum::Impl(..)
| rustdoc_types::ItemEnum::Trait(..)
)
})
.map(move |value| origin.make_item_vertex(value)),
)
Box::new(items.filter_map(move |value| {
crate::adapter::supported_item_kind(value).then(|| origin.make_item_vertex(value))
}))
}
62 changes: 61 additions & 1 deletion src/adapter/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;

use anyhow::Context;
use maplit::btreemap;
use trustfall::{FieldValue, Schema};
use trustfall::{FieldValue, Schema, TryIntoStruct};

use crate::{IndexedCrate, RustdocAdapter};

Expand Down Expand Up @@ -117,3 +117,63 @@ fn rustdoc_finds_supertrait() {
results
);
}

#[test]
fn rustdoc_finds_consts() {
let path = "./localdata/test_data/consts/rustdoc.json";
let content = std::fs::read_to_string(path)
.with_context(|| format!("Could not load {path} file, did you forget to run ./scripts/regenerate_test_rustdocs.sh ?"))
.expect("failed to load rustdoc");

let crate_ = serde_json::from_str(&content).expect("failed to parse rustdoc");
let indexed_crate = IndexedCrate::new(&crate_);
let adapter = RustdocAdapter::new(&indexed_crate, None);

let query = r#"
{
Crate {
item {
... on Constant {
name @output
importable_path {
path @output
}
}
}
}
}
"#;

let variables: BTreeMap<&str, &str> = BTreeMap::default();

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,
path: Vec<String>,
}

let mut results: Vec<_> =
trustfall::execute_query(&schema, Arc::new(adapter), query, variables)
.expect("failed to run query")
.map(|row| row.try_into_struct().expect("shape mismatch"))
.collect();
results.sort_unstable();

assert_eq!(
vec![
Output {
name: "FIRST".into(),
path: vec!["consts".into(), "FIRST".into()],
},
Output {
name: "SECOND".into(),
path: vec!["consts".into(), "inner".into(), "SECOND".into()],
},
],
results
);
}
11 changes: 10 additions & 1 deletion src/adapter/vertex.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::rc::Rc;

use rustdoc_types::{
Crate, Enum, Function, Impl, Item, Path, Span, Struct, Trait, Type, Variant, VariantKind,
Constant, Crate, Enum, Function, Impl, Item, Path, Span, Struct, Trait, Type, Variant,
VariantKind,
};
use trustfall::provider::Typename;

Expand Down Expand Up @@ -53,6 +54,7 @@ impl<'a> Typename for Vertex<'a> {
rustdoc_types::ItemEnum::StructField(..) => "StructField",
rustdoc_types::ItemEnum::Impl(..) => "Impl",
rustdoc_types::ItemEnum::Trait(..) => "Trait",
rustdoc_types::ItemEnum::Constant(..) => "Constant",
_ => unreachable!("unexpected item.inner for item: {item:?}"),
},
VertexKind::Span(..) => "Span",
Expand Down Expand Up @@ -184,6 +186,13 @@ impl<'a> Vertex<'a> {
})
}

pub(super) fn as_constant(&self) -> Option<&'a Constant> {
self.as_item().and_then(|item| match &item.inner {
rustdoc_types::ItemEnum::Constant(c) => Some(c),
_ => None,
})
}

pub(super) fn as_attribute(&self) -> Option<&'_ Attribute<'a>> {
match &self.kind {
VertexKind::Attribute(attr) => Some(attr),
Expand Down
26 changes: 9 additions & 17 deletions src/indexed_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{

use rustdoc_types::{Crate, Id, Item};

use crate::visibility_tracker::VisibilityTracker;
use crate::{adapter::supported_item_kind, visibility_tracker::VisibilityTracker};

/// The rustdoc for a crate, together with associated indexed data to speed up common operations.
///
Expand Down Expand Up @@ -53,19 +53,11 @@ impl<'a> IndexedCrate<'a> {

let mut imports_index: HashMap<ImportablePath, Vec<&Item>> =
HashMap::with_capacity(crate_.index.len());
for item in crate_.index.values().filter_map(|item| {
matches!(
item.inner,
rustdoc_types::ItemEnum::Struct(..)
| rustdoc_types::ItemEnum::StructField(..)
| rustdoc_types::ItemEnum::Enum(..)
| rustdoc_types::ItemEnum::Variant(..)
| rustdoc_types::ItemEnum::Function(..)
| rustdoc_types::ItemEnum::Impl(..)
| rustdoc_types::ItemEnum::Trait(..)
)
.then_some(item)
}) {
for item in crate_
.index
.values()
.filter_map(|item| supported_item_kind(item).then_some(item))
{
for importable_path in value.publicly_importable_names(&item.id) {
imports_index
.entry(ImportablePath::new(importable_path))
Expand Down Expand Up @@ -1337,7 +1329,7 @@ expected exactly one importable path for `Foo` items in this crate but got: {act
);
}

all_importable_paths.extend(actual_items.into_iter());
all_importable_paths.extend(actual_items);
}

all_importable_paths.sort_unstable();
Expand Down Expand Up @@ -1402,7 +1394,7 @@ expected exactly one importable path for `Foo` items in this crate but got: {act
_ => unreachable!("unexpected value for {deduplicated_actual_items:?}"),
};

all_importable_paths.extend(actual_items.into_iter());
all_importable_paths.extend(actual_items);
}

all_importable_paths.sort_unstable();
Expand Down Expand Up @@ -1468,7 +1460,7 @@ expected exactly one importable path for `Foo` items in this crate but got: {act
_ => unreachable!("unexpected value for {deduplicated_actual_items:?}"),
};

all_importable_paths.extend(actual_items.into_iter());
all_importable_paths.extend(actual_items);
}

all_importable_paths.sort_unstable();
Expand Down
23 changes: 23 additions & 0 deletions src/rustdoc_schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,29 @@ type Method implements Item & FunctionLike {
parameter: [FunctionParameter!]
}

"""
https://docs.rs/rustdoc-types/0.11.0/rustdoc_types/struct.Item.html
https://docs.rs/rustdoc-types/0.11.0/rustdoc_types/enum.ItemEnum.html
https://docs.rs/rustdoc-types/latest/rustdoc_types/struct.Constant.html
"""
type Constant implements Item & Importable {
# properties from Item
id: String!
crate_id: Int!
name: String
docs: String
attrs: [String!]!
visibility_limit: String!

# edges from Item
span: Span
attribute: [Attribute!]

# edges from Importable
importable_path: [ImportablePath!]
canonical_path: Path
}

"""
A specific attribute applied to an Item.
"""
Expand Down
12 changes: 9 additions & 3 deletions src/visibility_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,13 @@ fn resolve_crate_names(crate_: &Crate) -> NameResolution<'_> {
let mut result = NameResolution::default();

for item in crate_.index.values() {
let ItemEnum::Module(module_item) = &item.inner else { continue; };
let ItemEnum::Module(module_item) = &item.inner else {
continue;
};
for inner_id in &module_item.items {
let Some(inner_item) = crate_.index.get(inner_id) else { continue; };
let Some(inner_item) = crate_.index.get(inner_id) else {
continue;
};

if let ItemEnum::Import(imp) = &inner_item.inner {
if imp.glob {
Expand Down Expand Up @@ -345,7 +349,9 @@ fn resolve_crate_names(crate_: &Crate) -> NameResolution<'_> {
break Some(&underlying_item.id);
}
};
let Some(final_underlying_id) = final_underlying_id else { continue; };
let Some(final_underlying_id) = final_underlying_id else {
continue;
};
let definition = Definition::new(inner_id, final_underlying_id);

result
Expand Down
9 changes: 9 additions & 0 deletions test_crates/consts/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
publish = false
name = "consts"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
11 changes: 11 additions & 0 deletions test_crates/consts/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub const FIRST: u32 = 1;

pub mod inner {
pub const SECOND: i64 = 2;
}

pub struct Base;

impl Base {
pub const ASSOCIATED: &'static str = "associated";
}

0 comments on commit a58598f

Please sign in to comment.