1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::fmt;

use crate::{
    args::{CallArgs, FuncArgs},
    error::SassResult,
    parse::{Parser, Stmt},
    Token,
};

pub(crate) type BuiltinMixin = fn(CallArgs, &mut Parser) -> SassResult<Vec<Stmt>>;

#[derive(Clone)]
pub(crate) enum Mixin {
    UserDefined(UserDefinedMixin),
    Builtin(BuiltinMixin),
}

impl fmt::Debug for Mixin {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::UserDefined(u) => f
                .debug_struct("UserDefinedMixin")
                .field("args", &u.args)
                .field("body", &u.body)
                .field("accepts_content_block", &u.accepts_content_block)
                .field("declared_at_root", &u.declared_at_root)
                .finish(),
            Self::Builtin(..) => f.debug_struct("BuiltinMixin").finish(),
        }
    }
}

impl Mixin {
    pub fn new_user_defined(
        args: FuncArgs,
        body: Vec<Token>,
        accepts_content_block: bool,
        declared_at_root: bool,
    ) -> Self {
        Mixin::UserDefined(UserDefinedMixin::new(
            args,
            body,
            accepts_content_block,
            declared_at_root,
        ))
    }
}

#[derive(Debug, Clone)]
pub(crate) struct UserDefinedMixin {
    pub args: FuncArgs,
    pub body: Vec<Token>,
    pub accepts_content_block: bool,
    pub declared_at_root: bool,
}

impl UserDefinedMixin {
    pub fn new(
        args: FuncArgs,
        body: Vec<Token>,
        accepts_content_block: bool,
        declared_at_root: bool,
    ) -> Self {
        Self {
            args,
            body,
            accepts_content_block,
            declared_at_root,
        }
    }
}

#[derive(Debug, Clone)]
pub(crate) struct Content {
    /// The literal block, serialized as a list of tokens
    pub content: Option<Vec<Token>>,

    /// Optional args, e.g. `@content(a, b, c);`
    pub content_args: Option<FuncArgs>,

    /// The number of scopes at the use of `@include`
    ///
    /// This is used to "reset" back to the state of the `@include`
    /// without actually cloning the scope or putting it in an `Rc`
    pub scope_len: usize,

    /// Whether or not the mixin this `@content` block is inside of was
    /// declared in the global scope
    pub declared_at_root: bool,
}