Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support proc-macro lib type #466

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use log::{debug, info};
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::ToTokens as _;
use semver::{Comparator, Op, Version, VersionReq};
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet, VecDeque},
default::Default,
fmt::{self, Debug, Formatter},
fs::File,
io::{self, BufReader, Cursor, Read, Write},
Expand Down Expand Up @@ -86,7 +87,7 @@ impl Scope {
{
self.scope
.entry(key.into())
.or_insert_with(VecDeque::new)
.or_default()
.push_front((ty, value.into()));
}

Expand Down Expand Up @@ -292,21 +293,36 @@ impl CrateCode {
}
}

#[derive(Clone, Copy, Debug, Serialize)]
#[derive(Default, Clone, Copy, Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TargetType {
Bin,
#[default]
Lib
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[serde(untagged)]
pub enum TargetFilter {
Name(String),
Type(TargetType)
}

impl Default for TargetFilter {
fn default() -> Self {
Self::Type(TargetType::default())
}
}

#[derive(Debug)]
pub struct InputFile {
/// The name of the crate.
pub crate_name: String,
/// The version of the crate
pub crate_version: Version,
/// The target type.
pub target_type: TargetType,
pub target_type: String,
/// The repository url (if specified).
pub repository: Option<String>,
/// The license field (if specified).
Expand Down Expand Up @@ -361,7 +377,7 @@ pub fn read_code(
metadata: &Metadata,
pkg: &Package,
code: CrateCode,
target_type: TargetType,
target_type: String,
diagnostics: &mut Diagnostic
) -> InputFile {
let crate_name = pkg.name.clone();
Expand Down Expand Up @@ -429,6 +445,7 @@ fn parse_doc_attr(
expr: &Expr,
diagnostics: &mut Diagnostic
) -> syn::Result<Option<LitStr>> {
#[allow(dead_code)]
enum LitOrMacro {
Lit(LitStr),
Macro(Macro)
Expand Down
69 changes: 31 additions & 38 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub mod preproc;
#[doc(hidden)]
pub mod verify;

use crate::input::Scope;
use crate::input::{Scope, TargetFilter};
use diagnostic::Diagnostic;
use input::{CrateCode, InputFile, TargetType};

Expand All @@ -35,7 +35,7 @@ use input::{CrateCode, InputFile, TargetType};
pub fn read_input(
manifest_path: Option<PathBuf>,
package: Option<String>,
prefer_bin: bool,
target_filter: Option<TargetFilter>,
expand_macros: bool,
template: PathBuf,
features: Option<String>,
Expand All @@ -47,7 +47,7 @@ pub fn read_input(
let input = InputFile {
crate_name: "N/A".into(),
crate_version: Version::new(0, 0, 0),
target_type: TargetType::Lib,
target_type: "lib".into(),
repository: None,
license: None,
rust_version: None,
Expand Down Expand Up @@ -127,43 +127,36 @@ Help: You can use --manifest-path and/or -p to specify the package to use."#
)
};

// find the target whose rustdoc comment we'll use.
// this uses a library target if exists, otherwise a binary target with the same name as the
// package, or otherwise the first binary target
let is_lib = |target: &&Target| target.is_lib();
let is_default_bin =
|target: &&Target| target.is_bin() && target.name == pkg.name.as_str();
let target_and_type = if prefer_bin {
pkg.targets
.iter()
.find(is_default_bin)
.map(|target| (target, TargetType::Bin))
.or_else(|| {
pkg.targets
.iter()
.find(is_lib)
.map(|target| (target, TargetType::Lib))
})
} else {
pkg.targets
.iter()
.find(is_lib)
.map(|target| (target, TargetType::Lib))
.or_else(|| {
pkg.targets
let target_opt = match target_filter {
None => pkg.targets.first(),
Some(TargetFilter::Name(name)) => {
pkg.targets.iter().find(|target| target.name == name)
},
Some(TargetFilter::Type(ty)) => {
let is_lib = |target: &&Target| target.is_lib();
let is_default_bin =
|target: &&Target| target.is_bin() && target.name == pkg.name.as_str();
match ty {
TargetType::Bin => pkg
.targets
.iter()
.find(is_default_bin)
.map(|target| (target, TargetType::Bin))
})
.or_else(|| pkg.targets.iter().find(is_lib)),
TargetType::Lib => pkg
.targets
.iter()
.find(is_lib)
.or_else(|| pkg.targets.iter().find(is_default_bin))
}
}
};
let (target, target_type) = unwrap!(
target_and_type.or_else(|| {
pkg.targets
.iter()
.find(|target| target.is_bin())
.map(|target| (target, TargetType::Bin))
}),
"Failed to find a library or binary target"
// default to the first bin if the user-requested target is not found
let target_opt =
target_opt.or_else(|| pkg.targets.iter().find(|target| target.is_bin()));
let target = unwrap!(target_opt, "Failed to find a library or binary target");
let target_kind = unwrap!(
target.kind.first(),
"Failed to determine the kind of the target"
);

// resolve the template
Expand Down Expand Up @@ -200,7 +193,7 @@ Help: You can use --manifest-path and/or -p to specify the package to use."#
// process the target
info!("Reading {}", file.display());
let input_file =
input::read_code(&metadata, pkg, code, target_type, &mut diagnostics);
input::read_code(&metadata, pkg, code, target_kind.clone(), &mut diagnostics);
debug!("Processing {input_file:#?}");

(input_file, template, diagnostics)
Expand Down
2 changes: 1 addition & 1 deletion src/links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ mod tests {
let mut input = crate::input::InputFile {
crate_name: "my-crate".into(),
crate_version: semver::Version::new(0, 0, 0),
target_type: crate::input::TargetType::Lib,
target_type: "lib".into(),
repository: None,
license: None,
rust_version: None,
Expand Down
24 changes: 20 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@
//! [cargo-readme]: https://github.com/livioribeiro/cargo-readme
//! [docs.rs]: https://docs.rs

use cargo_doc2readme::{diagnostic::Diagnostic, output, read_input, verify};
use cargo_doc2readme::{
diagnostic::Diagnostic,
input::{TargetFilter, TargetType},
output, read_input, verify
};
use clap::Parser;
use log::{error, info, warn, Level};
use std::{env, fs::File, io, path::PathBuf, process::ExitCode};
Expand Down Expand Up @@ -136,13 +140,17 @@ struct Args {
no_default_features: bool,

/// Prefer binary targets over library targets for rustdoc source.
#[arg(long, conflicts_with = "lib")]
#[arg(long, conflicts_with_all = ["target_name", "lib"])]
bin: bool,

/// Prefer library targets over binary targets for rustdoc source. This is the default.
#[arg(long, conflicts_with = "bin")]
#[arg(long, conflicts_with_all = ["target_name", "bin"])]
lib: bool,

/// Explicitly specify the target name
#[arg(long, conflicts_with_all = ["lib", "bin"])]
target_name: Option<String>,

/// Verify that the output file is (reasonably) up to date, and fail
/// if it needs updating. The output file will not be changed.
#[arg(long)]
Expand Down Expand Up @@ -197,10 +205,18 @@ fn main() -> ExitCode {
)
.expect("Failed to initialize logger");

let target_filter = args.target_name.map(TargetFilter::Name).or({
if args.bin {
Some(TargetFilter::Type(TargetType::Bin))
} else {
Some(TargetFilter::Type(TargetType::Lib))
}
});

let (input_file, template, diagnostics) = read_input(
args.manifest_path,
args.package,
args.bin,
target_filter,
args.expand_macros,
args.template,
args.features,
Expand Down
6 changes: 3 additions & 3 deletions src/output.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
input::{InputFile, Scope, TargetType},
input::{InputFile, Scope},
links::Links
};
use itertools::Itertools as _;
Expand Down Expand Up @@ -434,7 +434,7 @@ struct TemplateContext<'a> {
krate: &'a str,
#[serde(rename = "crate_version")]
krate_version: &'a str,
target: TargetType,
target: &'a str,

repository: Option<&'a str>,
repository_host: Option<String>,
Expand Down Expand Up @@ -463,7 +463,7 @@ pub fn emit(
let ctx = TemplateContext {
krate: &input.crate_name,
krate_version: &format!("{}", input.crate_version),
target: input.target_type,
target: &input.target_type,
repository,
repository_host: repository.and_then(|repo| {
let url = Url::parse(repo).ok();
Expand Down
7 changes: 7 additions & 0 deletions tests/pass/proc-macro/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions tests/pass/proc-macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "proc-macro"
version = "0.0.0"
publish = false
edition = "2021"

[lib]
proc-macro = true
path = "lib.rs"
2 changes: 2 additions & 0 deletions tests/pass/proc-macro/README.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{readme}}
{{links}}
5 changes: 5 additions & 0 deletions tests/pass/proc-macro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blah blah
[`test_macro!`][__link0]
blah blah

[__link0]: `test_macro!`
10 changes: 10 additions & 0 deletions tests/pass/proc-macro/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! blah blah
//! [`test_macro!`]
//! blah blah

use proc_macro::TokenStream;

#[proc_macro]
pub fn test_macro(input: TokenStream) -> TokenStream {
input
}
3 changes: 3 additions & 0 deletions tests/pass/proc-macro/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nightly = true
expand_macros = true
target_filter = "proc_macro"
9 changes: 7 additions & 2 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
#![forbid(unsafe_code)]

use cargo_doc2readme::{
diagnostic::Diagnostic, input::InputFile, output, read_input, verify
diagnostic::Diagnostic,
input::{InputFile, TargetFilter},
output, read_input, verify
};
use lazy_regex::regex_replace_all;
use libtest::{Arguments, Failed, Trial};
Expand Down Expand Up @@ -55,6 +57,9 @@ struct TestConfig {
/// Test with these features enabled. Ignored unless combined with `--expand-macros`.
features: Option<String>,

#[serde(default)]
target_filter: Option<TargetFilter>,

/// Test with all features enabled. Ignored unless combined with `--expand-macros`.
#[serde(default)]
all_features: bool,
Expand Down Expand Up @@ -116,7 +121,7 @@ impl<'a> TestRun<'a> {
let (input_file, template, diagnostic) = read_input(
Some(manifest_path),
None,
false,
data.config.target_filter.clone(),
data.config.expand_macros,
template_path,
data.config.features.clone(),
Expand Down