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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use crate::error::SassResult;

use super::Extension;

/// An `Extension` created by merging two `Extension`s with the same extender
/// and target.
///
/// This is used when multiple mandatory extensions exist to ensure that both of
/// them are marked as resolved.
pub(super) struct MergedExtension;

impl MergedExtension {
    /// Returns an extension that combines `left` and `right`.
    ///
    /// Returns an `Err` if `left` and `right` have incompatible media
    /// contexts.
    ///
    /// Returns an `Err` if `left` and `right` don't have the same
    /// extender and target.
    pub fn merge(left: Extension, right: Extension) -> SassResult<Extension> {
        if left.extender != right.extender || left.target != right.target {
            todo!("we need a span to throw a proper error")
            //     return Err((format!("{} and {} aren't the same extension.", left, right), ))
        }

        if left.media_context.is_some()
            && right.media_context.is_some()
            && left.media_context != right.media_context
        {
            todo!()
            // throw SassException(
            //     "From ${left.span.message('')}\n"
            //     "You may not @extend the same selector from within different media "
            //     "queries.",
            //     right.span);
        }

        if right.is_optional && right.media_context.is_none() {
            return Ok(left);
        }

        if left.is_optional && left.media_context.is_none() {
            return Ok(right);
        }

        Ok(MergedExtension::into_extension(left, right))
    }

    fn into_extension(left: Extension, right: Extension) -> Extension {
        Extension {
            extender: left.extender,
            target: left.target,
            span: left.span,
            media_context: match left.media_context {
                Some(v) => Some(v),
                None => right.media_context,
            },
            specificity: left.specificity,
            is_optional: true,
            is_original: false,
            left: None,
            right: None,
        }
        // : super(left.extender, left.target, left.extenderSpan, left.span,
        //     left.mediaContext ?? right.mediaContext,
        //     specificity: left.specificity, optional: true);
    }

    /// Returns all leaf-node `Extension`s in the tree or `MergedExtension`s.
    #[allow(dead_code, unused_mut, clippy::unused_self)]
    pub fn unmerge(mut self) -> Vec<Extension> {
        todo!()
        /*  Iterable<Extension> unmerge() sync* {
            if (left is MergedExtension) {
              yield* (left as MergedExtension).unmerge();
            } else {
              yield left;
            }

            if (right is MergedExtension) {
              yield* (right as MergedExtension).unmerge();
            } else {
              yield right;
            }
          }
        */
    }
}
/*
class MergedExtension extends Extension {
  /// One of the merged extensions.
  final Extension left;

  /// The other merged extension.
  final Extension right;

  MergedExtension._(this.left, this.right)
      : super(left.extender, left.target, left.extenderSpan, left.span,
            left.mediaContext ?? right.mediaContext,
            specificity: left.specificity, optional: true);


}
*/