Skip to content

Commit

Permalink
Collect additional breadcrumbs to reduce the situations where we can'…
Browse files Browse the repository at this point in the history
…t identify an external rustdoc JSON crate. (#188)

It significantly mitigates #133.
  • Loading branch information
LukeMathWalker authored Feb 9, 2024
1 parent 26cd09f commit d14d2f8
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 97 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Do NOT edit this code.
//! It was automatically generated by Pavex.
//! All manual edits will be lost next time the code is generated.
extern crate alloc;
struct ServerState {
router: pavex_matchit::Router<u32>,
#[allow(dead_code)]
application_state: ApplicationState,
}
pub struct ApplicationState {}
pub async fn build_application_state() -> crate::ApplicationState {
crate::ApplicationState {}
}
pub fn run(
server_builder: pavex::server::Server,
application_state: ApplicationState,
) -> pavex::server::ServerHandle {
let server_state = std::sync::Arc::new(ServerState {
router: build_router(),
application_state,
});
server_builder.serve(route_request, server_state)
}
fn build_router() -> pavex_matchit::Router<u32> {
let mut router = pavex_matchit::Router::new();
router.insert("/home", 0u32).unwrap();
router
}
async fn route_request(
request: http::Request<hyper::body::Incoming>,
server_state: std::sync::Arc<ServerState>,
) -> pavex::response::Response {
let (request_head, request_body) = request.into_parts();
#[allow(unused)]
let request_body = pavex::request::body::RawIncomingBody::from(request_body);
let request_head: pavex::request::RequestHead = request_head.into();
let matched_route = match server_state.router.at(&request_head.target.path()) {
Ok(m) => m,
Err(_) => {
let allowed_methods: pavex::router::AllowedMethods = pavex::router::MethodAllowList::from_iter(
vec![],
)
.into();
return route_1::handler(&allowed_methods).await;
}
};
let route_id = matched_route.value;
#[allow(unused)]
let url_params: pavex::request::path::RawPathParams<'_, '_> = matched_route
.params
.into();
match route_id {
0u32 => {
match &request_head.method {
&pavex::http::Method::GET => route_0::handler().await,
_ => {
let allowed_methods: pavex::router::AllowedMethods = pavex::router::MethodAllowList::from_iter([
pavex::http::Method::GET,
])
.into();
route_1::handler(&allowed_methods).await
}
}
}
i => unreachable!("Unknown route id: {}", i),
}
}
pub mod route_0 {
pub async fn handler() -> pavex::response::Response {
let v0 = app::handler();
<http::StatusCode as pavex::response::IntoResponse>::into_response(v0)
}
}
pub mod route_1 {
pub async fn handler(
v0: &pavex::router::AllowedMethods,
) -> pavex::response::Response {
let v1 = pavex::router::default_fallback(v0).await;
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
digraph "GET /home - 0" {
0 [ label = "app::handler() -> http::StatusCode"]
1 [ label = "<http::StatusCode as pavex::response::IntoResponse>::into_response(http::StatusCode) -> pavex::response::Response"]
0 -> 1 [ ]
}

digraph "* /home - 0" {
0 [ label = "pavex::router::default_fallback(&pavex::router::AllowedMethods) -> pavex::response::Response"]
2 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"]
3 [ label = "&pavex::router::AllowedMethods"]
0 -> 2 [ ]
3 -> 0 [ ]
}

digraph app_state {
0 [ label = "crate::ApplicationState() -> crate::ApplicationState"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use pavex::blueprint::{router::GET, Blueprint};
use pavex::f;
use pavex::http::StatusCode;

pub fn handler() -> StatusCode {
todo!()
}

pub fn blueprint() -> Blueprint {
let mut bp = Blueprint::new();
bp.route(GET, "/home", f!(crate::handler));
bp
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
description = """Pavex can handle multiple versions of the same
package in the project dependency tree, as long as they aren't all
**direct** dependencies of the project"""

[expectations]
codegen = "pass"

[dependencies]
# This depends on a different version of `http` than what `pavex` brings in
reqwest = { version = "0.11", features = ["json"] }


24 changes: 20 additions & 4 deletions libs/pavexc/src/compiler/resolvers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,25 @@ pub(crate) fn resolve_type(
generic_bindings: &HashMap<String, ResolvedType>,
) -> Result<ResolvedType, anyhow::Error> {
match type_ {
Type::ResolvedPath(rustdoc_types::Path { id, args, .. }) => {
let (global_type_id, base_type) =
krate_collection.get_canonical_path_by_local_type_id(used_by_package_id, id)?;
Type::ResolvedPath(rustdoc_types::Path { id, args, name }) => {
let re_exporter_crate_name = if id.0.starts_with("0:") {
// 0 is the crate index of local types.
None
} else {
// It is not guaranteed that this type will be from a direct dependency of `used_by_package_id`.
// It might be a re-export from a transitive dependency, done by a direct dependency.
// Unfortunately, `rustdoc` does not provide the package id of the crate where the type
// was re-exported from, creating a "missing link".
// We try to infer it from the `name` property, which is usually the fully qualified
// name of the type, e.g. `std::collections::HashMap`.
name.split("::").next()
};
let (global_type_id, base_type) = krate_collection
.get_canonical_path_by_local_type_id(
used_by_package_id,
id,
re_exporter_crate_name,
)?;
let type_item = krate_collection.get_type_by_global_type_id(&global_type_id);
// We want to remove any indirections (e.g. `type Foo = Bar;`) and get the actual type.
if let ItemEnum::TypeAlias(type_alias) = &type_item.inner {
Expand Down Expand Up @@ -420,7 +436,7 @@ pub(crate) fn resolve_type_path(
let item = &resolved_item.item;
let used_by_package_id = resolved_item.item_id.package_id();
let (global_type_id, base_type) =
krate_collection.get_canonical_path_by_local_type_id(used_by_package_id, &item.id)?;
krate_collection.get_canonical_path_by_local_type_id(used_by_package_id, &item.id, None)?;
let mut generic_arguments = vec![];
let (last_segment, first_segments) = path.segments.split_last().unwrap();
for segment in first_segments {
Expand Down
8 changes: 6 additions & 2 deletions libs/pavexc/src/compiler/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@ pub(crate) fn implements_trait(
};
if let Some(trait_id) = trait_id {
if let Ok((_, trait_path)) = krate_collection
.get_canonical_path_by_local_type_id(&our_path_type.package_id, trait_id)
.get_canonical_path_by_local_type_id(
&our_path_type.package_id,
trait_id,
None,
)
{
if trait_path == expected_trait.base_type
// The "impls" for a rustdoc item include implementations for
Expand Down Expand Up @@ -275,7 +279,7 @@ fn is_equivalent(
};
let rustdoc_type_id = &p.id;
let Ok((rustdoc_global_type_id, _)) = krate_collection
.get_canonical_path_by_local_type_id(used_by_package_id, rustdoc_type_id)
.get_canonical_path_by_local_type_id(used_by_package_id, rustdoc_type_id, None)
else {
tracing::trace!("Failed to look up {:?}", rustdoc_type_id);
return false;
Expand Down
2 changes: 1 addition & 1 deletion libs/pavexc/src/language/resolved_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl ResolvedPathType {
let item = &resolved_item.item;
let used_by_package_id = resolved_item.item_id.package_id();
let (global_type_id, base_type) = krate_collection
.get_canonical_path_by_local_type_id(used_by_package_id, &item.id)?;
.get_canonical_path_by_local_type_id(used_by_package_id, &item.id, None)?;
let mut generic_arguments = vec![];
for segment in &p.path.segments {
for generic_path in &segment.generic_arguments {
Expand Down
Loading

0 comments on commit d14d2f8

Please sign in to comment.