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

Replace prefix/suffix with formatx #112

Merged
merged 1 commit into from
Oct 18, 2024
Merged
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
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
Loading