Compare commits
2 commits
21ff321402
...
3bdb914052
Author | SHA1 | Date | |
---|---|---|---|
3bdb914052 | |||
1e2a6e1804 |
12 changed files with 179 additions and 83 deletions
1
.ignore
Normal file
1
.ignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
**/tests
|
53
src/main.rs
53
src/main.rs
|
@ -2,9 +2,11 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use model::{Config, FoundMarkers, Line, Marker, MarkerKind};
|
use model::{Config, FoundMarkers, Line, Marker};
|
||||||
|
use patterns::{issue_pattern, marker_pattern};
|
||||||
|
|
||||||
mod model;
|
mod model;
|
||||||
|
mod patterns;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
println!("Forgejo TODO Checker!");
|
println!("Forgejo TODO Checker!");
|
||||||
|
@ -17,10 +19,8 @@ fn main() -> Result<()> {
|
||||||
))
|
))
|
||||||
.repo(std::env::var("GITHUB_REPOSITORY").context("GITHUB_REPOSITORY")?)
|
.repo(std::env::var("GITHUB_REPOSITORY").context("GITHUB_REPOSITORY")?)
|
||||||
.server(std::env::var("GITHUB_SERVER_URL").context("GITHUB_SERVER_URL")?)
|
.server(std::env::var("GITHUB_SERVER_URL").context("GITHUB_SERVER_URL")?)
|
||||||
.prefix_pattern(regex::Regex::new(r"(#|//)\s*(TODO|FIXME)").context("prefix regex")?)
|
.prefix_pattern(marker_pattern()?)
|
||||||
.issue_pattern(
|
.issue_pattern(issue_pattern()?)
|
||||||
regex::Regex::new(r"( |)(\(|\(#)(?P<ISSUE_NUMBER>\d+)(\))").context("issue regex")?,
|
|
||||||
)
|
|
||||||
.maybe_auth_token(std::env::var("REPO_TOKEN").ok())
|
.maybe_auth_token(std::env::var("REPO_TOKEN").ok())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{found_markers:?}");
|
println!("{found_markers:#?}");
|
||||||
|
|
||||||
// TODO: add authentication when provided
|
// TODO: add authentication when provided
|
||||||
// let issues = ureq::get(&api).call()?.into_string()?;
|
// let issues = ureq::get(&api).call()?.into_string()?;
|
||||||
|
@ -59,35 +59,16 @@ fn scan_file(file: &Path, config: &Config, found_markers: &mut FoundMarkers) ->
|
||||||
.file_read_to_string(file)?
|
.file_read_to_string(file)?
|
||||||
.lines()
|
.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(n, line)| prefix_match(n, line, file, config))
|
.map(|(n, line)| {
|
||||||
.for_each(|marker| {
|
Line::builder()
|
||||||
println!("- {}", marker.line().value());
|
.file(file.to_path_buf())
|
||||||
if let Some(issue) = config
|
.num(n)
|
||||||
.issue_pattern()
|
.value(line.to_owned())
|
||||||
.find(marker.line().value())
|
.build()
|
||||||
.map(|issue| issue.as_str())
|
})
|
||||||
.and_then(|issue| issue.parse::<usize>().ok())
|
.filter_map(|line| line.into_marker().ok())
|
||||||
{
|
.filter(|marker| !matches!(marker, Marker::Unmarked))
|
||||||
found_markers.add_issue_marker(marker.into_issue_marker(issue));
|
.for_each(|marker| found_markers.add_marker(marker));
|
||||||
} else {
|
|
||||||
found_markers.add_marker(marker);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix_match(num: usize, line: &str, path: &Path, config: &Config) -> Option<Marker> {
|
|
||||||
let find = config.prefix_pattern().find(line)?;
|
|
||||||
let kind = match find.as_str() {
|
|
||||||
"TODO" => Some(MarkerKind::Todo),
|
|
||||||
"FIXME" => Some(MarkerKind::Fixme),
|
|
||||||
_ => None,
|
|
||||||
}?;
|
|
||||||
Some(
|
|
||||||
Marker::builder()
|
|
||||||
.kind(kind)
|
|
||||||
.file(path.to_path_buf())
|
|
||||||
.line(Line::builder().num(num).value(line.to_owned()).build())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +1,47 @@
|
||||||
//
|
//
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use bon::Builder;
|
use bon::Builder;
|
||||||
|
|
||||||
|
use crate::patterns::{issue_pattern, marker_pattern};
|
||||||
|
|
||||||
|
use super::Marker;
|
||||||
|
|
||||||
#[derive(Debug, Builder)]
|
#[derive(Debug, Builder)]
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
|
file: PathBuf,
|
||||||
num: usize,
|
num: usize,
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
impl Line {
|
impl Line {
|
||||||
|
pub fn file(&self) -> &Path {
|
||||||
|
&self.file
|
||||||
|
}
|
||||||
pub fn num(&self) -> usize {
|
pub fn num(&self) -> usize {
|
||||||
self.num
|
self.num
|
||||||
}
|
}
|
||||||
pub fn value(&self) -> &str {
|
pub fn value(&self) -> &str {
|
||||||
&self.value
|
&self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_marker(self) -> Result<Marker> {
|
||||||
|
if marker_pattern()?.find(&self.value).is_some() {
|
||||||
|
match issue_pattern()?.captures(&self.value) {
|
||||||
|
Some(capture) => {
|
||||||
|
let issue = capture
|
||||||
|
.name("ISSUE_NUMBER")
|
||||||
|
.context("ISSUE_NUMBER")?
|
||||||
|
.as_str()
|
||||||
|
.to_owned();
|
||||||
|
Ok(Marker::Valid(self, issue))
|
||||||
|
}
|
||||||
|
None => Ok(Marker::Invalid(self)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Marker::Unmarked)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
use super::{IssueMarker, Marker};
|
use super::Marker;
|
||||||
|
|
||||||
//
|
//
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct FoundMarkers {
|
pub struct FoundMarkers {
|
||||||
markers: Vec<Marker>,
|
markers: Vec<Marker>,
|
||||||
issue_markers: Vec<IssueMarker>,
|
|
||||||
}
|
}
|
||||||
impl FoundMarkers {
|
impl FoundMarkers {
|
||||||
pub fn add_marker(&mut self, marker: Marker) {
|
pub fn add_marker(&mut self, marker: Marker) {
|
||||||
self.markers.push(marker);
|
self.markers.push(marker);
|
||||||
}
|
}
|
||||||
pub fn add_issue_marker(&mut self, issue_marker: IssueMarker) {
|
|
||||||
self.issue_markers.push(issue_marker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
//
|
|
||||||
/// What type of comment #[derive(Debug)]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum MarkerKind {
|
|
||||||
Todo,
|
|
||||||
Fixme,
|
|
||||||
}
|
|
|
@ -1,37 +1,11 @@
|
||||||
//
|
//
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use bon::Builder;
|
|
||||||
|
|
||||||
use crate::model::Line;
|
use crate::model::Line;
|
||||||
|
|
||||||
use super::{IssueMarker, MarkerKind};
|
#[derive(Debug)]
|
||||||
|
pub enum Marker {
|
||||||
/// Represents a TODO or FIXME comment that doesn't have any issue number
|
Unmarked,
|
||||||
#[derive(Debug, Builder)]
|
Invalid(Line),
|
||||||
pub struct Marker {
|
Valid(Line, String),
|
||||||
/// What type of marker
|
|
||||||
kind: MarkerKind,
|
|
||||||
|
|
||||||
/// Path of the file
|
|
||||||
file: PathBuf,
|
|
||||||
|
|
||||||
/// The line from the file
|
|
||||||
line: Line,
|
|
||||||
}
|
|
||||||
impl Marker {
|
|
||||||
pub fn kind(&self) -> &MarkerKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
pub fn file(&self) -> &Path {
|
|
||||||
&self.file
|
|
||||||
}
|
|
||||||
pub fn line(&self) -> &Line {
|
|
||||||
&self.line
|
|
||||||
}
|
|
||||||
pub fn into_issue_marker(self, issue: usize) -> IssueMarker {
|
|
||||||
IssueMarker::builder().marker(self).issue(issue).build()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
//
|
//
|
||||||
mod found;
|
mod found;
|
||||||
mod issue;
|
mod issue;
|
||||||
mod kind;
|
|
||||||
mod marker;
|
mod marker;
|
||||||
|
|
||||||
pub use found::FoundMarkers;
|
pub use found::FoundMarkers;
|
||||||
pub use issue::IssueMarker;
|
|
||||||
pub use kind::MarkerKind;
|
|
||||||
pub use marker::Marker;
|
pub use marker::Marker;
|
||||||
|
|
|
@ -5,4 +5,5 @@ mod markers;
|
||||||
|
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub use line::Line;
|
pub use line::Line;
|
||||||
pub use markers::*;
|
pub use markers::FoundMarkers;
|
||||||
|
pub use markers::Marker;
|
||||||
|
|
16
src/patterns/mod.rs
Normal file
16
src/patterns/mod.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
use anyhow::{Context as _, Result};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
/// The pattern to find a TODO or FIXME comment
|
||||||
|
pub fn marker_pattern() -> Result<Regex> {
|
||||||
|
regex::Regex::new(r"(#|//)\s*(TODO|FIXME)").context("prefix regex")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The pattern to find an issue number on an already found TODO or FIXME comment
|
||||||
|
pub fn issue_pattern() -> Result<Regex> {
|
||||||
|
regex::Regex::new(r"( |)(\(|\(#)(?P<ISSUE_NUMBER>\d+)(\))").context("issue regex")
|
||||||
|
}
|
33
src/patterns/tests/issue.rs
Normal file
33
src/patterns/tests/issue.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_issue_should_find_number() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line with a // TODO: (#13) issue number";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = issue_pattern()?.captures(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_some());
|
||||||
|
let captures = result.unwrap();
|
||||||
|
let issue_number = captures.name("ISSUE_NUMBER").unwrap().as_str();
|
||||||
|
assert_eq!(issue_number, "13");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_no_issue_should_find_nothing() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line with a // TODO: and no issue number";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = issue_pattern()?.captures(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_none());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
70
src/patterns/tests/marker.rs
Normal file
70
src/patterns/tests/marker.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_todo_find_marker() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line // TODO: with a marker";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = marker_pattern()?.find(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_some());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_fixme_find_marker() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line // FIXME: with a marker";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = marker_pattern()?.find(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_some());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_no_marker_find_nothing() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line with no marker";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = marker_pattern()?.find(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_none());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_invalid_todo_find_nothing() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line TODO: with no real marker";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = marker_pattern()?.find(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_none());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn when_invalid_fixme_find_nothing() -> anyhow::Result<()> {
|
||||||
|
//given
|
||||||
|
let line = " a line FIXME: with no real marker";
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = marker_pattern()?.find(line);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert!(result.is_none());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
5
src/patterns/tests/mod.rs
Normal file
5
src/patterns/tests/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
//
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
mod issue;
|
||||||
|
mod marker;
|
Loading…
Reference in a new issue