ast_grep_config/
rewriter.rs1use ast_grep_core::language::Language;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::HashSet;
5use thiserror::Error;
6
7use crate::check_var::check_rewriter_fix;
8use crate::fixer::{Fixer, FixerError, SerializableFixer};
9use crate::rule::DeserializeEnv;
10use crate::{RuleCore, RuleCoreError, SerializableRuleCore};
11
12pub struct Rewriter {
13 pub matcher: RuleCore,
14 pub fixer: Vec<Fixer>,
15}
16#[derive(Debug, Error)]
17#[error("Rewriter `{id}` has invalid configuration.")]
18pub struct RewriterError {
19 pub id: String,
20 #[source]
21 pub reason: RewriterErrorReason,
22}
23
24#[derive(Debug, Error)]
25pub enum RewriterErrorReason {
26 #[error(transparent)]
27 Core(#[from] RuleCoreError),
28 #[error("Rewriter rule must have `fix`.")]
29 NoFixInRewriter,
30 #[error("`fix` pattern is invalid.")]
31 Fixer(#[from] FixerError),
32}
33
34#[derive(Serialize, Deserialize, Clone, JsonSchema)]
35pub struct SerializableRewriter {
36 pub id: String,
38 pub fix: SerializableFixer,
42 #[serde(flatten)]
43 pub core: SerializableRuleCore,
44}
45
46impl SerializableRewriter {
47 pub fn try_parse_rewriter<L: Language>(
48 &self,
49 upper_vars: &HashSet<&str>,
50 env: &DeserializeEnv<L>,
51 ) -> Result<Rewriter, RewriterError> {
52 let attach_id = |e| RewriterError {
53 id: self.id.clone(),
54 reason: e,
55 };
56 let rewriter = self
57 .core
58 .get_matcher(env.clone())
59 .map_err(|e| attach_id(e.into()))?;
60 let fixer =
61 Fixer::parse(&self.fix, env, &self.core.transform).map_err(|e| attach_id(e.into()))?;
62 if fixer.is_empty() {
63 return Err(attach_id(RewriterErrorReason::NoFixInRewriter));
64 }
65 check_rewriter_fix(&rewriter, &fixer, upper_vars).map_err(|e| attach_id(e.into()))?;
66 Ok(Rewriter {
67 matcher: rewriter,
68 fixer,
69 })
70 }
71}