dtolnay / request-for-implementation

Crates that don't exist, but should

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Library to inline out-of-line mod items and resolve #[path = "..."]

dtolnay opened this issue · comments

In dtolnay/cargo-expand#11 I need to be able to take a source file as a syn::File and transitively expand every mod m; into mod m { ... } with its contents drawn from the right file.

Concretely we'll be replacing the content field of every ItemMod with Some if it is None.

Example input:

src/lib.rs

#[cfg(feature = "m1")]
mod m1;

#[cfg_attr(feature = "m2", path = "m2.rs")]
#[cfg_attr(not(feature = "m2"), path = "empty.rs")]
mod placeholder;

src/m1.rs

struct M1;

src/m2.rs

//! module level doc comment

struct M2;

src/empty.rs

// empty file

The result will look like:

#[cfg(feature = "m1")]
mod m1 {
    struct M1;
}

#[cfg(feature = "m2")]
mod placeholder {
    //! module level doc comment

    struct M2;
}

#[cfg(not(feature = "m2"))]
mod placeholder {
}

Possible API:

pub fn parse_and_inline_modules(root: &std::path::Path) -> syn::File;

I'll take a look at this one.

Should this be done recursively?

How should not-found files be handled? They could be made into empty modules, or the top-line API could be changed to return a Result.

Yes I would like it to be recursive.

For my use case I would want not-found modules to simply stay as mod m; and for the top-level API to be infallible. Performing this transformation 100% correctly requires more parts of a compiler (including name resolution and macro expansion), so since only an approximation is being implemented, there is no meaningful way that a caller could handle failures.

Found a couple bugs; filing them over in the crate repo.

@dpc is https://docs.rs/syn-inline-mod sufficient for your use case or do you need it to be integrated into a cli?

@dtolnay After I'll figure out how to convert it to string, and how to find entry points to a given crate, I'll be all set. :)

@dpc I've been calling into_token_stream().to_string() on the syn::File instance to get the results into a string.

I don't know what is the best way to find out the crate entry point. This may be a Cargo feature request. The following might work for now:

cargo +nightly build -Z unstable-options --build-plan \
    | jq -r '.invocations[-1].args[2]'

Added link in the readme. Nicely done!