|
| 1 | +use rustc_hash::{FxHashMap, FxHashSet}; |
| 2 | +use rustpython_ast::{Expr, ExprKind, Keyword}; |
| 3 | +use rustpython_parser::ast::Constant; |
| 4 | + |
| 5 | +use crate::ast::helpers::{collect_call_paths, dealias_call_path, match_call_path, SimpleCallArgs}; |
| 6 | +use crate::ast::types::Range; |
| 7 | +use crate::registry::Diagnostic; |
| 8 | +use crate::violations; |
| 9 | + |
| 10 | +/// S701 |
| 11 | +pub fn jinja2_autoescape_false( |
| 12 | + func: &Expr, |
| 13 | + args: &[Expr], |
| 14 | + keywords: &[Keyword], |
| 15 | + from_imports: &FxHashMap<&str, FxHashSet<&str>>, |
| 16 | + import_aliases: &FxHashMap<&str, &str>, |
| 17 | +) -> Option<Diagnostic> { |
| 18 | + if match_call_path( |
| 19 | + &dealias_call_path(collect_call_paths(func), import_aliases), |
| 20 | + "jinja2", |
| 21 | + "Environment", |
| 22 | + from_imports, |
| 23 | + ) { |
| 24 | + let call_args = SimpleCallArgs::new(args, keywords); |
| 25 | + |
| 26 | + if let Some(autoescape_arg) = call_args.get_argument("autoescape", None) { |
| 27 | + match &autoescape_arg.node { |
| 28 | + ExprKind::Constant { |
| 29 | + value: Constant::Bool(true), |
| 30 | + .. |
| 31 | + } => (), |
| 32 | + ExprKind::Call { func, .. } => { |
| 33 | + if let ExprKind::Name { id, .. } = &func.node { |
| 34 | + if id.as_str() != "select_autoescape" { |
| 35 | + return Some(Diagnostic::new( |
| 36 | + violations::Jinja2AutoescapeFalse(true), |
| 37 | + Range::from_located(autoescape_arg), |
| 38 | + )); |
| 39 | + } |
| 40 | + } |
| 41 | + } |
| 42 | + _ => { |
| 43 | + return Some(Diagnostic::new( |
| 44 | + violations::Jinja2AutoescapeFalse(true), |
| 45 | + Range::from_located(autoescape_arg), |
| 46 | + )) |
| 47 | + } |
| 48 | + } |
| 49 | + } else { |
| 50 | + return Some(Diagnostic::new( |
| 51 | + violations::Jinja2AutoescapeFalse(false), |
| 52 | + Range::from_located(func), |
| 53 | + )); |
| 54 | + } |
| 55 | + } |
| 56 | + None |
| 57 | +} |
0 commit comments