1use anyhow::Result;
4use async_trait::async_trait;
5use libabbs::apml::value::union::Union;
6use libpfu::{
7 Linter, Session, declare_lint, declare_linter,
8 message::{LintMessage, Snippet},
9 walk_apml,
10};
11use log::debug;
12
13declare_linter! {
14 pub CHKUPDATE_LINTER,
15 ChkUpdateLinter,
16 [
17 "unknown-findupdate-tag",
18 "prefer-anitya",
19 ]
20}
21
22declare_lint! {
23 pub UNKNOWN_FINDUPDATE_TAG_LINT,
24 "unknown-findupdate-tag",
25 Error,
26 "unknown handler found in CHKUPDATE"
27}
28
29declare_lint! {
30 pub PREFER_ANITYA_LINT,
31 "prefer-anitya",
32 Warning,
33 "prefer to use Anitya for version checking"
34}
35
36#[async_trait]
37impl Linter for ChkUpdateLinter {
38 async fn apply(&self, sess: &Session) -> Result<()> {
39 for mut apml in walk_apml(sess) {
40 debug!("Checking CHKUPDATE in {apml:?}");
41 let (chkupdate, chkupdate_idx) = apml.with_upgraded(|apml| {
42 (
43 apml.ctx().map(|ctx| ctx.read("CHKUPDATE").into_string()),
44 apml.read_with_editor(|editor| {
45 editor
46 .find_var("CHKUPDATE")
47 .unzip()
48 .0
49 .unwrap_or_default()
50 }),
51 )
52 });
53 let chkupdate = chkupdate?;
54 let chkupdate = chkupdate.trim();
55 if chkupdate.is_empty() {
56 debug!("CHKUPDATE is not defined");
57 return Ok(());
58 }
59
60 let un = Union::try_from(chkupdate)?;
61 match un.tag.to_ascii_lowercase().as_str() {
62 "anitya" => {}
63 "github" | "gitweb" | "git" | "html" | "gitlab" => {
64 LintMessage::new(PREFER_ANITYA_LINT)
65 .note(format!(
66 "CHKUPDATE with tag {} should be converted into anitya",
67 un.tag
68 ))
69 .snippet(Snippet::new_index(sess, &apml, chkupdate_idx))
70 .emit(sess);
71 }
72 _ => {
73 LintMessage::new(UNKNOWN_FINDUPDATE_TAG_LINT)
74 .note(format!(
75 "CHKUPDATE with tag {} is unsupported",
76 un.tag
77 ))
78 .snippet(Snippet::new_index(sess, &apml, chkupdate_idx))
79 .emit(sess);
80 }
81 }
82 }
83 Ok(())
84 }
85}