Skip to content

Commit

Permalink
Replace prefix/suffix with formatx
Browse files Browse the repository at this point in the history
  • Loading branch information
SamWilsn committed Oct 18, 2024
1 parent 2fbefe1 commit d7dc36b
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 162 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions eipw-lint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ educe = { version = "0.6.0", default-features = false, features = [ "Debug" ] }
tokio = { optional = true, version = "1.40.0", features = [ "macros" ] }
scraper = { version = "0.20.0", default-features = false }
jsonschema = { version = "0.21.0", default-features = false }
formatx = "0.2.2"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.40.0", features = [ "fs", "macros" ] }
Expand Down
104 changes: 74 additions & 30 deletions eipw-lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use eipw_snippets::{Annotation, Level, Snippet};
use comrak::arena_tree::Node;
use comrak::nodes::Ast;
use comrak::Arena;
use formatx::formatx;

use crate::lints::{Context, DefaultLint, Error as LintError, FetchContext, InnerContext, Lint};
use crate::modifiers::{DefaultModifier, Modifier};
Expand Down Expand Up @@ -113,16 +114,12 @@ pub fn default_lints_enum() -> impl Iterator<Item = (&'static str, DefaultLint<&
"preamble-refs-title",
PreambleProposalRef(preamble::ProposalRef {
name: "title",
prefix: "eip-",
suffix: ".md",
}),
),
(
"preamble-refs-description",
PreambleProposalRef(preamble::ProposalRef {
name: "description",
prefix: "eip-",
suffix: ".md",
}),
),
(
Expand Down Expand Up @@ -323,8 +320,6 @@ pub fn default_lints_enum() -> impl Iterator<Item = (&'static str, DefaultLint<&
PreambleRequiresStatus(preamble::RequiresStatus {
requires: "requires",
status: "status",
prefix: "eip-",
suffix: ".md",
flow: vec![
vec!["Draft", "Stagnant"],
vec!["Review"],
Expand All @@ -351,19 +346,15 @@ pub fn default_lints_enum() -> impl Iterator<Item = (&'static str, DefaultLint<&
"preamble-file-name",
PreambleFileName(preamble::FileName {
name: "eip",
prefix: "eip-",
suffix: ".md",
format: "eip-{}",
}),
),
//
// Markdown
//
(
"markdown-refs",
MarkdownProposalRef(markdown::ProposalRef {
prefix: "eip-",
suffix: ".md",
}),
MarkdownProposalRef(markdown::ProposalRef),
),
(
"markdown-html-comments",
Expand Down Expand Up @@ -449,8 +440,7 @@ pub fn default_lints_enum() -> impl Iterator<Item = (&'static str, DefaultLint<&
(
"markdown-link-status",
MarkdownLinkStatus(markdown::LinkStatus {
prefix: "eip-",
suffix: ".md",
pattern: r"(?i)(?:eip|erc)-([0-9]+).md$",
status: "status",
flow: vec![
vec!["Draft", "Stagnant"],
Expand Down Expand Up @@ -542,21 +532,31 @@ impl<T> Iterator for NeverIter<T> {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[non_exhaustive]
pub struct FetchOptions {
pub proposal_format: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[non_exhaustive]
pub struct Options<M, L> {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub modifiers: Option<M>,

#[serde(default, skip_serializing_if = "Option::is_none")]
pub lints: Option<L>,

#[serde(default, skip_serializing_if = "Option::is_none")]
pub fetch: Option<FetchOptions>,
}

impl<M, L> Default for Options<M, L> {
fn default() -> Self {
Self {
modifiers: None,
lints: None,
fetch: None,
}
}
}
Expand All @@ -583,7 +583,11 @@ where
.map(|(k, v)| (k.as_ref(), Box::new(v.clone()) as Box<dyn Lint>))
});

Options { modifiers, lints }
Options {
modifiers,
lints,
fetch: self.fetch.clone(),
}
}
}

Expand All @@ -595,6 +599,8 @@ pub struct Linter<'a, R> {
modifiers: Vec<Box<dyn Modifier>>,
sources: Vec<Source<'a>>,

proposal_format: String,

#[educe(Debug(ignore))]
reporter: R,

Expand Down Expand Up @@ -630,12 +636,18 @@ impl<'a, R> Linter<'a, R> {
.collect(),
};

let proposal_format = options
.fetch
.map(|o| o.proposal_format)
.unwrap_or_else(|| "eip-{}".into());

Self {
reporter,
sources: Default::default(),
fetch: Box::<fetch::DefaultFetch>::default(),
modifiers,
lints,
proposal_format,
}
}

Expand All @@ -645,6 +657,7 @@ impl<'a, R> Linter<'a, R> {
Options {
lints: Option::<NeverIter<_>>::None,
modifiers: Some(modifiers),
fetch: Default::default(),
},
)
}
Expand All @@ -658,6 +671,7 @@ impl<'a, R> Linter<'a, R> {
Options {
modifiers: Option::<NeverIter<_>>::None,
lints: Some(lints),
fetch: Default::default(),
},
)
}
Expand Down Expand Up @@ -764,7 +778,7 @@ where
let context = FetchContext {
body: inner.body,
preamble: &inner.preamble,
eips: Default::default(),
fetch_proposals: Default::default(),
};

lint.1
Expand All @@ -773,34 +787,61 @@ where
origin: source_origin.clone(),
})?;

let eips = context.eips.into_inner();
let fetch_proposals = context.fetch_proposals.into_inner();

// For now, string sources shouldn't be allowed to fetch external
// resources. The origin field isn't guaranteed to be a file/URL,
// and even if it was, we wouldn't know which of those to interpret
// it as.
ensure!(
eips.is_empty() || !source.is_string(),
fetch_proposals.is_empty() || !source.is_string(),
SliceFetchedSnafu {
lint: *slug,
origin: source_origin.clone(),
}
);

for eip in eips.into_iter() {
let root = match source {
Source::File(p) => p.parent().unwrap_or_else(|| Path::new(".")),
_ => unreachable!(),
};
if fetch_proposals.is_empty() {
continue;
}

let path = root.join(eip);
let source_path = match source {
Source::File(p) => p,
_ => unreachable!(),
};
let source_dir = source_path.parent().unwrap_or_else(|| Path::new("."));
let root = match source_path.file_name() {
Some(f) if f == "index.md" => source_dir.join(".."),
Some(_) | None => source_dir.to_path_buf(),
};

let entry = match fetched_eips.entry(path) {
for proposal in fetch_proposals.into_iter() {
let entry = match fetched_eips.entry(proposal) {
hash_map::Entry::Occupied(_) => continue,
hash_map::Entry::Vacant(v) => v,
};
let basename =
formatx!(&self.proposal_format, proposal).expect("bad proposal format");

let mut plain_path = root.join(&basename);
plain_path.set_extension("md");
let plain = Source::File(&plain_path).fetch(&*self.fetch).await;

let mut index_path = root.join(&basename);
index_path.push("index.md");
let index = Source::File(&index_path).fetch(&*self.fetch).await;

let content = match (plain, index) {
(Ok(_), Ok(_)) => panic!(
"ambiguous proposal between `{}` and `{}`",
plain_path.to_string_lossy(),
index_path.to_string_lossy()
),
(Ok(c), Err(_)) => Ok(c),
(Err(_), Ok(c)) => Ok(c),
(Err(e), Err(_)) => Err(e),
};

let content = Source::File(entry.key()).fetch(&*self.fetch).await;
entry.insert(content);
}
}
Expand All @@ -809,11 +850,11 @@ where
let resources_arena = Arena::new();
let mut parsed_eips = HashMap::new();

for (origin, result) in &fetched_eips {
for (number, result) in &fetched_eips {
let source = match result {
Ok(o) => o,
Err(e) => {
parsed_eips.insert(origin.as_path(), Err(e));
parsed_eips.insert(*number, Err(e));
continue;
}
};
Expand All @@ -822,7 +863,7 @@ where
Some(s) => s,
None => return Ok(self.reporter),
};
parsed_eips.insert(origin.as_path(), Ok(inner));
parsed_eips.insert(*number, Ok(inner));
}

let mut lints: Vec<_> = self.lints.iter().collect();
Expand Down Expand Up @@ -1044,6 +1085,9 @@ mod tests {
let options = Options {
lints: Some(default_lints_enum().collect::<HashMap<_, _>>()),
modifiers: Some(default_modifiers_enum()),
fetch: Some(FetchOptions {
proposal_format: "floop".into(),
}),
};

type StringOptions =
Expand Down
24 changes: 7 additions & 17 deletions eipw-lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use std::cmp::max;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::string::FromUtf8Error;

#[derive(Debug, Snafu)]
Expand Down Expand Up @@ -77,7 +76,7 @@ where
'b: 'a,
{
pub(crate) inner: InnerContext<'a>,
pub(crate) eips: &'b HashMap<&'b Path, Result<InnerContext<'b>, &'b crate::Error>>,
pub(crate) eips: &'b HashMap<u32, Result<InnerContext<'b>, &'b crate::Error>>,
#[educe(Debug(ignore))]
pub(crate) reporter: &'b dyn Reporter,
pub(crate) annotation_level: Level,
Expand Down Expand Up @@ -137,20 +136,11 @@ where
Ok(())
}

pub fn eip(&self, path: &Path) -> Result<Context<'b, 'b>, &crate::Error> {
let origin = self
.origin()
.expect("lint attempted to access an external resource without having an origin");

let origin_path = PathBuf::from(origin);
let root = origin_path.parent().unwrap_or_else(|| Path::new("."));

let key = root.join(path);

let inner = match self.eips.get(key.as_path()) {
pub fn proposal(&self, proposal: u32) -> Result<Context<'b, 'b>, &crate::Error> {
let inner = match self.eips.get(&proposal) {
Some(Ok(i)) => i,
Some(Err(e)) => return Err(e),
None => panic!("no eip found for key `{}`", key.display()),
None => panic!("no eip found for key `{}`", proposal),
};

Ok(Context {
Expand All @@ -166,7 +156,7 @@ where
pub struct FetchContext<'a> {
pub(crate) preamble: &'a Preamble<'a>,
pub(crate) body: &'a AstNode<'a>,
pub(crate) eips: RefCell<HashSet<PathBuf>>,
pub(crate) fetch_proposals: RefCell<HashSet<u32>>,
}

impl<'a> FetchContext<'a> {
Expand All @@ -178,8 +168,8 @@ impl<'a> FetchContext<'a> {
self.body
}

pub fn fetch(&self, path: PathBuf) {
self.eips.borrow_mut().insert(path);
pub fn fetch_proposal(&self, proposal: u32) {
self.fetch_proposals.borrow_mut().insert(proposal);
}
}

Expand Down
Loading

0 comments on commit d7dc36b

Please sign in to comment.