mirror of
https://github.com/Noratrieb/target-tier-docs-experiment.git
synced 2026-01-14 16:35:09 +01:00
start with tables
This commit is contained in:
parent
f6cef8ab1f
commit
f4493e17b2
3 changed files with 127 additions and 18 deletions
74
src/main.rs
74
src/main.rs
|
|
@ -17,6 +17,15 @@ struct TargetDocs {
|
||||||
maintainers: Vec<String>,
|
maintainers: Vec<String>,
|
||||||
sections: Vec<(String, String)>,
|
sections: Vec<(String, String)>,
|
||||||
tier: String,
|
tier: String,
|
||||||
|
// TODO: Make this mandatory.
|
||||||
|
metadata: Option<TargetMetadata>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Metadata for the table
|
||||||
|
struct TargetMetadata {
|
||||||
|
notes: String,
|
||||||
|
std: String,
|
||||||
|
host: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SECTIONS: &[&str] = &[
|
const SECTIONS: &[&str] = &[
|
||||||
|
|
@ -57,7 +66,14 @@ fn main() -> Result<()> {
|
||||||
let mut info_patterns = parse::load_target_infos(Path::new(input_dir))
|
let mut info_patterns = parse::load_target_infos(Path::new(input_dir))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|info| TargetPatternEntry { info, used: false })
|
.map(|info| {
|
||||||
|
let metadata_used = vec![false; info.metadata.len()];
|
||||||
|
TargetPatternEntry {
|
||||||
|
info,
|
||||||
|
used: false,
|
||||||
|
metadata_used,
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
eprintln!("Collecting rustc information");
|
eprintln!("Collecting rustc information");
|
||||||
|
|
@ -66,16 +82,21 @@ fn main() -> Result<()> {
|
||||||
.map(|target| rustc_target_info(&rustc, target))
|
.map(|target| rustc_target_info(&rustc, target))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let targets = targets
|
||||||
|
.into_iter()
|
||||||
|
.map(|target| target_doc_info(&mut info_patterns, target))
|
||||||
|
.zip(rustc_infos)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
eprintln!("Rendering targets");
|
eprintln!("Rendering targets");
|
||||||
for (target, rustc_info) in std::iter::zip(&targets, rustc_infos) {
|
for (info, rustc_info) in &targets {
|
||||||
let info = target_info(&mut info_patterns, target);
|
let doc = render::render_target_md(info, rustc_info);
|
||||||
let doc = render::render_target_md(&info, &rustc_info);
|
|
||||||
|
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
Path::new(output_src)
|
Path::new(output_src)
|
||||||
.join("platform-support")
|
.join("platform-support")
|
||||||
.join("targets")
|
.join("targets")
|
||||||
.join(format!("{target}.md")),
|
.join(format!("{}.md", info.name)),
|
||||||
doc,
|
doc,
|
||||||
)
|
)
|
||||||
.wrap_err("writing target file")?;
|
.wrap_err("writing target file")?;
|
||||||
|
|
@ -88,9 +109,21 @@ fn main() -> Result<()> {
|
||||||
target_pattern.info.pattern
|
target_pattern.info.pattern
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (used, meta) in
|
||||||
|
std::iter::zip(target_pattern.metadata_used, target_pattern.info.metadata)
|
||||||
|
{
|
||||||
|
if !used {
|
||||||
|
bail!(
|
||||||
|
"in target pattern `{}`, the metadata pattern `{}` was never used",
|
||||||
|
target_pattern.info.pattern,
|
||||||
|
meta.pattern
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render::render_static(&Path::new(output_src).join("platform-support"), &targets)?;
|
render::render_static(Path::new(output_src), &targets)?;
|
||||||
|
|
||||||
eprintln!("Finished generating target docs");
|
eprintln!("Finished generating target docs");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -99,18 +132,20 @@ fn main() -> Result<()> {
|
||||||
struct TargetPatternEntry {
|
struct TargetPatternEntry {
|
||||||
info: ParsedTargetInfoFile,
|
info: ParsedTargetInfoFile,
|
||||||
used: bool,
|
used: bool,
|
||||||
|
metadata_used: Vec<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the target information from `target_info.toml` by applying all patterns that match.
|
fn target_doc_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> TargetDocs {
|
||||||
fn target_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> TargetDocs {
|
|
||||||
let mut tier = None;
|
let mut tier = None;
|
||||||
let mut maintainers = Vec::new();
|
let mut maintainers = Vec::new();
|
||||||
let mut sections = Vec::new();
|
let mut sections = Vec::new();
|
||||||
|
|
||||||
for target_pattern in info_patterns {
|
let mut metadata = None;
|
||||||
if glob_match::glob_match(&target_pattern.info.pattern, target) {
|
|
||||||
target_pattern.used = true;
|
for target_pattern_entry in info_patterns {
|
||||||
let target_pattern = &target_pattern.info;
|
if glob_match::glob_match(&target_pattern_entry.info.pattern, target) {
|
||||||
|
target_pattern_entry.used = true;
|
||||||
|
let target_pattern = &target_pattern_entry.info;
|
||||||
|
|
||||||
maintainers.extend_from_slice(&target_pattern.maintainers);
|
maintainers.extend_from_slice(&target_pattern.maintainers);
|
||||||
|
|
||||||
|
|
@ -127,6 +162,20 @@ fn target_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> Target
|
||||||
}
|
}
|
||||||
sections.push((section_name.clone(), content.clone()));
|
sections.push((section_name.clone(), content.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i, metadata_pattern) in target_pattern.metadata.iter().enumerate() {
|
||||||
|
if glob_match::glob_match(&metadata_pattern.pattern, target) {
|
||||||
|
target_pattern_entry.metadata_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(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +185,7 @@ fn target_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> Target
|
||||||
// tier: tier.expect(&format!("no tier found for target {target}")),
|
// tier: tier.expect(&format!("no tier found for target {target}")),
|
||||||
tier: tier.unwrap_or("UNKNOWN".to_owned()),
|
tier: tier.unwrap_or("UNKNOWN".to_owned()),
|
||||||
sections,
|
sections,
|
||||||
|
metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
src/parse.rs
16
src/parse.rs
|
|
@ -3,19 +3,32 @@
|
||||||
use eyre::{bail, OptionExt, Result, WrapErr};
|
use eyre::{bail, OptionExt, Result, WrapErr};
|
||||||
use std::{fs::DirEntry, path::Path};
|
use std::{fs::DirEntry, path::Path};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug)]
|
||||||
pub struct ParsedTargetInfoFile {
|
pub struct ParsedTargetInfoFile {
|
||||||
pub pattern: String,
|
pub pattern: String,
|
||||||
pub tier: Option<String>,
|
pub tier: Option<String>,
|
||||||
pub maintainers: Vec<String>,
|
pub maintainers: Vec<String>,
|
||||||
pub sections: Vec<(String, String)>,
|
pub sections: Vec<(String, String)>,
|
||||||
|
pub metadata: Vec<ParsedTargetMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
struct Frontmatter {
|
struct Frontmatter {
|
||||||
tier: Option<String>,
|
tier: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
maintainers: Vec<String>,
|
maintainers: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
metadata: Vec<ParsedTargetMetadata>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct ParsedTargetMetadata {
|
||||||
|
pub pattern: String,
|
||||||
|
pub notes: String,
|
||||||
|
pub std: String,
|
||||||
|
pub host: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_target_infos(directory: &Path) -> Result<Vec<ParsedTargetInfoFile>> {
|
pub fn load_target_infos(directory: &Path) -> Result<Vec<ParsedTargetInfoFile>> {
|
||||||
|
|
@ -93,6 +106,7 @@ fn parse_file(name: &str, content: &str) -> Result<ParsedTargetInfoFile> {
|
||||||
maintainers: frontmatter.maintainers,
|
maintainers: frontmatter.maintainers,
|
||||||
tier: frontmatter.tier,
|
tier: frontmatter.tier,
|
||||||
sections,
|
sections,
|
||||||
|
metadata: frontmatter.metadata,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use eyre::{Context, OptionExt, Result};
|
use eyre::{bail, Context, OptionExt, Result};
|
||||||
use std::{fs, path::Path};
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
use crate::{is_in_rust_lang_rust, RustcTargetInfo, TargetDocs};
|
use crate::{is_in_rust_lang_rust, RustcTargetInfo, TargetDocs};
|
||||||
|
|
@ -91,13 +91,13 @@ fn replace_section(prev_content: &str, section_name: &str, replacement: &str) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders the non-target files like `SUMMARY.md` that depend on the target.
|
/// Renders the non-target files like `SUMMARY.md` that depend on the target.
|
||||||
pub fn render_static(platform_support: &Path, targets: &[&str]) -> Result<()> {
|
pub fn render_static(src_output: &Path, targets: &[(TargetDocs, RustcTargetInfo)]) -> Result<()> {
|
||||||
let targets_file = platform_support.join("targets.md");
|
let targets_file = src_output.join("platform-support").join("targets.md");
|
||||||
let old_targets = fs::read_to_string(&targets_file).wrap_err("reading summary file")?;
|
let old_targets = fs::read_to_string(&targets_file).wrap_err("reading summary file")?;
|
||||||
|
|
||||||
let target_list = targets
|
let target_list = targets
|
||||||
.iter()
|
.iter()
|
||||||
.map(|target| format!("- [{0}](targets/{0}.md)", target))
|
.map(|(target, _)| format!("- [{0}](targets/{0}.md)", target.name))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
|
|
@ -127,6 +127,51 @@ pub fn render_static(platform_support: &Path, targets: &[&str]) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Render the nice table showing off all targets and their tier.
|
// TODO: Render the nice table showing off all targets and their tier.
|
||||||
|
let platform_support_main = src_output.join("platform-support.md");
|
||||||
|
let platform_support_main_old =
|
||||||
|
fs::read_to_string(&platform_support_main).wrap_err("reading platform-support.md")?;
|
||||||
|
|
||||||
|
let tier3_table =
|
||||||
|
render_table_with_host(targets.into_iter().filter(|target| target.0.tier == "3"))
|
||||||
|
.wrap_err("rendering tier 3 table")?;
|
||||||
|
|
||||||
|
let platform_support_main_new =
|
||||||
|
replace_section(&platform_support_main_old, "TIER3", &tier3_table)
|
||||||
|
.wrap_err("replacing platform support.md")?;
|
||||||
|
|
||||||
|
fs::write(platform_support_main, platform_support_main_new)
|
||||||
|
.wrap_err("writing platform-support.md")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_table_with_host<'a>(
|
||||||
|
targets: impl IntoIterator<Item = &'a (TargetDocs, RustcTargetInfo)>,
|
||||||
|
) -> Result<String> {
|
||||||
|
let mut rows = Vec::new();
|
||||||
|
|
||||||
|
for (target, _) in targets {
|
||||||
|
let meta = target.metadata.as_ref();
|
||||||
|
let std = match meta.map(|meta| meta.std.as_str()) {
|
||||||
|
Some("true") => "✓",
|
||||||
|
Some("unknown") => "?",
|
||||||
|
Some("false") => " ",
|
||||||
|
None => "?",
|
||||||
|
_ => bail!("invalid value for std todo parse early"),
|
||||||
|
};
|
||||||
|
let host = match meta.map(|meta| meta.host.as_str()) {
|
||||||
|
Some("true") => "✓",
|
||||||
|
Some("unknown") => "?",
|
||||||
|
Some("false") => " ",
|
||||||
|
None => "?",
|
||||||
|
_ => bail!("invalid value for host todo parse early"),
|
||||||
|
};
|
||||||
|
let notes = meta.map(|meta| meta.notes.as_str()).unwrap_or("unknown");
|
||||||
|
rows.push(format!(
|
||||||
|
"[`{0}`](platform-support/targets/{0}.md) | {std} | {host} | {notes}",
|
||||||
|
target.name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(rows.join("\n"))
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue