mirror of
https://github.com/Noratrieb/target-tier-docs-experiment.git
synced 2026-01-14 16:35:09 +01:00
stuff
This commit is contained in:
parent
720b23bd8e
commit
a00ca6ae97
3 changed files with 87 additions and 92 deletions
82
src/main.rs
82
src/main.rs
|
|
@ -2,12 +2,13 @@ mod parse;
|
|||
mod render;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use eyre::{bail, Context, OptionExt, Result};
|
||||
use parse::{Footnote, ParsedTargetInfoFile, Tier, TriStateBool};
|
||||
use parse::ParsedTargetInfoFile;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Information about a target obtained from the target_info markdown file.
|
||||
|
|
@ -52,14 +53,24 @@ fn main() -> Result<()> {
|
|||
.wrap_err("failed loading target_info")?
|
||||
.into_iter()
|
||||
.map(|info| {
|
||||
let metadata_used = vec![false; info.metadata.len()];
|
||||
TargetPatternEntry { info, used: false, footnotes_used: metadata_used }
|
||||
let footnotes_used = info
|
||||
.footnotes
|
||||
.iter()
|
||||
.map(|(target, _)| (target.clone(), false))
|
||||
.collect();
|
||||
TargetPatternEntry {
|
||||
info,
|
||||
used: false,
|
||||
footnotes_used,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
eprintln!("Collecting rustc information");
|
||||
let rustc_infos =
|
||||
targets.iter().map(|target| rustc_target_info(&rustc, target)).collect::<Vec<_>>();
|
||||
let rustc_infos = targets
|
||||
.iter()
|
||||
.map(|target| rustc_target_info(&rustc, target))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let targets = targets
|
||||
.into_iter()
|
||||
|
|
@ -68,7 +79,9 @@ fn main() -> Result<()> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
eprintln!("Rendering targets check_only={check_only}");
|
||||
let targets_dir = Path::new(output_src).join("platform-support").join("targets");
|
||||
let targets_dir = Path::new(output_src)
|
||||
.join("platform-support")
|
||||
.join("targets");
|
||||
if !check_only {
|
||||
std::fs::create_dir_all(&targets_dir).wrap_err("creating platform-support/targets dir")?;
|
||||
}
|
||||
|
|
@ -83,17 +96,19 @@ fn main() -> Result<()> {
|
|||
|
||||
for target_pattern in info_patterns {
|
||||
if !target_pattern.used {
|
||||
bail!("target pattern `{}` was never used", target_pattern.info.pattern);
|
||||
bail!(
|
||||
"target pattern `{}` was never used",
|
||||
target_pattern.info.pattern
|
||||
);
|
||||
}
|
||||
|
||||
for (used, meta) in
|
||||
std::iter::zip(target_pattern.footnotes_used, target_pattern.info.metadata)
|
||||
{
|
||||
for footnote_target in target_pattern.info.footnotes.keys() {
|
||||
let used = target_pattern.footnotes_used[footnote_target];
|
||||
if !used {
|
||||
bail!(
|
||||
"in target pattern `{}`, the footnotes for target `{}` were never used",
|
||||
target_pattern.info.pattern,
|
||||
meta.target
|
||||
footnote_target,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +123,7 @@ fn main() -> Result<()> {
|
|||
struct TargetPatternEntry {
|
||||
info: ParsedTargetInfoFile,
|
||||
used: bool,
|
||||
footnotes_used: Vec<bool>,
|
||||
footnotes_used: HashMap<String, bool>,
|
||||
}
|
||||
|
||||
fn target_doc_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> TargetDocs {
|
||||
|
|
@ -116,7 +131,6 @@ fn target_doc_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> Ta
|
|||
let mut maintainers = Vec::new();
|
||||
let mut sections = Vec::new();
|
||||
|
||||
let mut metadata = None;
|
||||
let mut footnotes = Vec::new();
|
||||
|
||||
for target_pattern_entry in info_patterns {
|
||||
|
|
@ -145,32 +159,24 @@ fn target_doc_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> Ta
|
|||
}
|
||||
|
||||
if let Some(target_footnotes) = target_pattern.footnotes.get(target) {
|
||||
target_pattern_entry.footnotes_used[i] = true;
|
||||
target_pattern_entry
|
||||
.footnotes_used
|
||||
.insert(target.to_owned(), true);
|
||||
|
||||
if !footnotes.is_empty() {
|
||||
panic!("target {target} is assigned metadata from more than one pattern");
|
||||
}
|
||||
footnotes = target_footnotes.clone();
|
||||
}
|
||||
|
||||
for (i, metadata_pattern) in target_pattern.metadata.iter().enumerate() {
|
||||
if metadata_pattern.target == target {
|
||||
target_pattern_entry.footnotes_used[i] = true;
|
||||
if metadata.is_some() {
|
||||
panic!("target {target} is assigned metadata from more than one pattern");
|
||||
}
|
||||
metadata = Some(TargetMetadata {
|
||||
notes: metadata_pattern.notes.clone(),
|
||||
host: metadata_pattern.host.clone(),
|
||||
std: metadata_pattern.std.clone(),
|
||||
footnotes: metadata_pattern.footnotes.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TargetDocs { name: target.to_owned(), maintainers, sections, footnotes }
|
||||
TargetDocs {
|
||||
name: target.to_owned(),
|
||||
maintainers,
|
||||
sections,
|
||||
footnotes,
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a target obtained from rustc.
|
||||
|
|
@ -212,11 +218,21 @@ fn rustc_target_info(rustc: &Path, target: &str) -> RustcTargetInfo {
|
|||
|
||||
let json_spec = rustc_stdout(
|
||||
rustc,
|
||||
&["-Zunstable-options", "--print", "target-spec-json", "--target", target],
|
||||
&[
|
||||
"-Zunstable-options",
|
||||
"--print",
|
||||
"target-spec-json",
|
||||
"--target",
|
||||
target,
|
||||
],
|
||||
);
|
||||
let spec = serde_json::from_str::<TargetJson>(&json_spec);
|
||||
let spec = serde_json::from_str::<TargetJson>(&json_spec)
|
||||
.expect("parsing --print target-spec-json for metadata");
|
||||
|
||||
RustcTargetInfo { target_cfgs, metadata: spec.metadata }
|
||||
RustcTargetInfo {
|
||||
target_cfgs,
|
||||
metadata: spec.metadata,
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_stdout(rustc: &Path, args: &[&str]) -> String {
|
||||
|
|
|
|||
|
|
@ -86,16 +86,9 @@ fn parse_file(name: &str, content: &str) -> Result<ParsedTargetInfoFile> {
|
|||
|
||||
let frontmatter_line_count = frontmatter.lines().count() + 2; // 2 from ---
|
||||
|
||||
let mut frontmatter =
|
||||
let frontmatter =
|
||||
serde_yaml::from_str::<Frontmatter>(frontmatter).wrap_err("invalid frontmatter")?;
|
||||
|
||||
frontmatter.metadata.iter_mut().for_each(|meta| {
|
||||
meta.footnotes.iter_mut().for_each(|footnote| {
|
||||
footnote.content = footnote.content.replace("\r\n", " ").replace("\n", " ")
|
||||
})
|
||||
});
|
||||
let frontmatter = frontmatter;
|
||||
|
||||
let body = frontmatter_splitter.next().ok_or_eyre("no body")?;
|
||||
|
||||
let mut sections = Vec::<(String, String)>::new();
|
||||
|
|
|
|||
|
|
@ -1,27 +1,18 @@
|
|||
use eyre::{Context, OptionExt, Result};
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use crate::{
|
||||
parse::{Footnote, Tier, TriStateBool},
|
||||
RustcTargetInfo, TargetDocs,
|
||||
};
|
||||
|
||||
impl TargetDocs {
|
||||
fn has_host_tools(&self) -> bool {
|
||||
self.metadata.as_ref().map_or(false, |meta| meta.host == TriStateBool::True)
|
||||
}
|
||||
}
|
||||
use crate::{RustcTargetInfo, TargetDocs};
|
||||
|
||||
/// Renders a single target markdown file from the information obtained.
|
||||
pub fn render_target_md(target: &TargetDocs, rustc_info: &RustcTargetInfo) -> String {
|
||||
let mut doc = format!(
|
||||
"# {}\n\n**Tier: {}**\n\n",
|
||||
target.name,
|
||||
match target.tier {
|
||||
Some(Tier::One) => "1",
|
||||
Some(Tier::Two) => "2",
|
||||
Some(Tier::Three) => "3",
|
||||
None => "UNKNOWN",
|
||||
match rustc_info.metadata.tier {
|
||||
Some(1) => "1",
|
||||
Some(2) => "2",
|
||||
Some(3) => "3",
|
||||
_ => "UNKNOWN",
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -61,7 +52,10 @@ pub fn render_target_md(target: &TargetDocs, rustc_info: &RustcTargetInfo) -> St
|
|||
section("Maintainers", &maintainers_content);
|
||||
|
||||
for section_name in crate::SECTIONS {
|
||||
let value = target.sections.iter().find(|(name, _)| name == section_name);
|
||||
let value = target
|
||||
.sections
|
||||
.iter()
|
||||
.find(|(name, _)| name == section_name);
|
||||
|
||||
let section_content = match value {
|
||||
Some((_, value)) => value.clone(),
|
||||
|
|
@ -141,12 +135,6 @@ pub fn render_static(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
impl Footnote {
|
||||
fn reference(&self) -> String {
|
||||
format!("[^{}]", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
fn render_platform_support_tables(
|
||||
content: &str,
|
||||
targets: &[(TargetDocs, RustcTargetInfo)],
|
||||
|
|
@ -160,7 +148,7 @@ fn render_platform_support_tables(
|
|||
content,
|
||||
"TIER1HOST",
|
||||
TierTable {
|
||||
filter: |target| target.tier == Some(Tier::One),
|
||||
filter: |target| target.1.metadata.tier == Some(1),
|
||||
include_host: false,
|
||||
include_std: false,
|
||||
},
|
||||
|
|
@ -169,7 +157,9 @@ fn render_platform_support_tables(
|
|||
&content,
|
||||
"TIER2HOST",
|
||||
TierTable {
|
||||
filter: |target| target.tier == Some(Tier::Two) && target.has_host_tools(),
|
||||
filter: |target| {
|
||||
target.1.metadata.tier == Some(2) && target.1.metadata.host_tools.unwrap_or(false)
|
||||
},
|
||||
include_host: false,
|
||||
include_std: false,
|
||||
},
|
||||
|
|
@ -178,7 +168,9 @@ fn render_platform_support_tables(
|
|||
&content,
|
||||
"TIER2",
|
||||
TierTable {
|
||||
filter: |target| target.tier == Some(Tier::Two) && !target.has_host_tools(),
|
||||
filter: |target| {
|
||||
target.1.metadata.tier == Some(2) && !target.1.metadata.host_tools.unwrap_or(false)
|
||||
},
|
||||
include_host: false,
|
||||
include_std: true,
|
||||
},
|
||||
|
|
@ -187,7 +179,7 @@ fn render_platform_support_tables(
|
|||
&content,
|
||||
"TIER3",
|
||||
TierTable {
|
||||
filter: |target| target.tier == Some(Tier::Three),
|
||||
filter: |target| target.1.metadata.tier == Some(3),
|
||||
include_host: true,
|
||||
include_std: true,
|
||||
},
|
||||
|
|
@ -196,49 +188,50 @@ fn render_platform_support_tables(
|
|||
Ok(content)
|
||||
}
|
||||
|
||||
fn render_table_tri_state_bool(bool: TriStateBool) -> &'static str {
|
||||
fn render_table_option_bool(bool: Option<bool>) -> &'static str {
|
||||
match bool {
|
||||
TriStateBool::True => "✓",
|
||||
TriStateBool::False => " ",
|
||||
TriStateBool::Unknown => "?",
|
||||
Some(true) => "✓",
|
||||
Some(false) => " ",
|
||||
None => "?",
|
||||
}
|
||||
}
|
||||
|
||||
struct TierTable {
|
||||
filter: fn(&TargetDocs) -> bool,
|
||||
filter: fn(&(TargetDocs, RustcTargetInfo)) -> bool,
|
||||
include_std: bool,
|
||||
include_host: bool,
|
||||
}
|
||||
|
||||
fn render_table(targets: &[(TargetDocs, RustcTargetInfo)], table: TierTable) -> Result<String> {
|
||||
let mut rows = Vec::new();
|
||||
let mut all_footnotes = Vec::new();
|
||||
|
||||
let targets = targets.into_iter().filter(|target| (table.filter)(&target.0));
|
||||
let targets = targets.into_iter().filter(|target| (table.filter)(&target));
|
||||
|
||||
for (target, _) in targets {
|
||||
let meta = target.metadata.as_ref();
|
||||
for (target, rustc_info) in targets {
|
||||
let meta = &rustc_info.metadata;
|
||||
|
||||
let mut notes = meta.map(|meta| meta.notes.as_str()).unwrap_or("unknown").to_owned();
|
||||
let mut notes = meta.description.as_deref().unwrap_or("unknown").to_owned();
|
||||
|
||||
if meta.map_or(false, |meta| !meta.footnotes.is_empty()) {
|
||||
let footnotes = &meta.unwrap().footnotes;
|
||||
all_footnotes.extend(footnotes);
|
||||
let footnotes_str =
|
||||
footnotes.iter().map(|footnote| footnote.reference()).collect::<Vec<_>>().join(" ");
|
||||
if !target.footnotes.is_empty() {
|
||||
let footnotes_str = target
|
||||
.footnotes
|
||||
.iter()
|
||||
.map(|footnote| format!("[^{}]", footnote))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
notes = format!("{notes} {footnotes_str}");
|
||||
}
|
||||
|
||||
let std = if table.include_std {
|
||||
let std = meta.map(|meta| render_table_tri_state_bool(meta.std)).unwrap_or("?");
|
||||
let std = render_table_option_bool(meta.std);
|
||||
format!(" | {std}")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let host = if table.include_host {
|
||||
let host = meta.map(|meta| render_table_tri_state_bool(meta.host)).unwrap_or("?");
|
||||
let host = render_table_option_bool(meta.host_tools);
|
||||
format!(" | {host}")
|
||||
} else {
|
||||
String::new()
|
||||
|
|
@ -250,14 +243,7 @@ fn render_table(targets: &[(TargetDocs, RustcTargetInfo)], table: TierTable) ->
|
|||
));
|
||||
}
|
||||
|
||||
let mut result = rows.join("\n");
|
||||
|
||||
for footnote in all_footnotes {
|
||||
result.push_str("\n\n");
|
||||
result.push_str(&footnote.reference());
|
||||
result.push_str(": ");
|
||||
result.push_str(&footnote.content);
|
||||
}
|
||||
let result = rows.join("\n");
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue