rested 0.9.2

Language/Interpreter for easily defining and running requests to an http server.
Documentation
use crate::{
    interpreter,
    lexer::Token,
    parser::{
        ast::{self, result::ParsedNode, Expression},
        ast_visit::{self, VisitWith},
    },
};
use tower_lsp::lsp_types::*;

use super::IntoPosition;

pub struct EnvVarsNotInAllNamespaces<'env> {
    pub env: &'env interpreter::environment::Environment,
    pub warnings: Vec<tower_lsp::lsp_types::Diagnostic>,
}

impl<'env> EnvVarsNotInAllNamespaces<'env> {
    pub fn new(env: &'env interpreter::environment::Environment) -> Self {
        Self {
            env,
            warnings: vec![],
        }
    }
}

impl<'env, 'source> ast_visit::Visitor<'source> for EnvVarsNotInAllNamespaces<'env> {
    fn visit_call_expr(&mut self, expr: &ast::CallExpr<'source>) {
        expr.visit_children_with(self);
        if let ast::CallExpr {
            arguments,
            identifier: ParsedNode::Ok(Token { text: "env", .. }),
        } = expr
        {
            if let Some(Expression::String(value)) = &arguments.exprs.first() {
                let namespaces_from_which_var_is_missing = self
                    .env
                    .namespaced_variables
                    .iter()
                    .filter(|(_, vars)| !vars.contains_key(&value.value.to_string()))
                    .map(|(namespace, _)| namespace)
                    .cloned()
                    .collect::<Vec<_>>();

                if !namespaces_from_which_var_is_missing.is_empty() {
                    self.warnings.push(Diagnostic {
                        range: Range {
                            start: value.span.start.into_position(),
                            end: value.span.end.into_position(),
                        },
                        message: format!(
                            "variable '{}' missing from some namespaces: {}",
                            value.value,
                            namespaces_from_which_var_is_missing.join(", ")
                        ),
                        severity: Some(DiagnosticSeverity::WARNING),
                        ..Default::default()
                    })
                }
            }
        };
    }
}