call method

Node call(
  1. {bool inValue = false,
  2. bool getLookup}
)

A Mixin call, with an optional argument list

#mixins > .square(#fff);
#mixins.square(#fff);
.rounded(4px, black);
.button;

We can lookup / return a value using the lookup syntax:

color: #mixin.square(#fff)[@color];

The while loop is there because mixins can be namespaced, but we only support the child and descendant selector for now.

Implementation

Node call({bool inValue = false, bool getLookup}) {
  List<MixinArgs> args;
  List<Element> elements;
  var hasparens = false;
  var important = false;
  List<String> lookups;

  final index = parserInput.i;
  final s = parserInput.currentChar();

  if (s != '.' && s != '#') return null;

  parserInput.save(); // stop us absorbing part of an invalid selector

  elements = this.elements();

  if (elements != null) {
    if (parserInput.$char('(') != null) {
      args = this.args(isCall: true).args;
      parserInput.expectChar(')');
      hasparens = true;
    }

    if (getLookup != false) lookups = ruleLookups();
    if (getLookup == true && lookups == null) {
      parserInput.restore();
      return null;
    }

    if (inValue && lookups == null && !hasparens) {
      // This isn't a valid in-value mixin call
      parserInput.restore();
      return null;
    }

    if (!inValue && parsers.important() != null) important = true;

    if (inValue || parsers.end()) {
      parserInput.forget();
      final mixin = MixinCall(elements, args,
          index: index,
          currentFileInfo: fileInfo,
          important: lookups == null && important);
      return lookups != null ? NamespaceValue(mixin, lookups) : mixin;
    }
  }

  parserInput.restore();
  return null;

// 3.10.3 20190923
//  call: function (inValue, getLookup) {
//      const s = parserInput.currentChar();
//      let important = false;
//      let lookups;
//      const index = parserInput.i;
//      let elements;
//      let args;
//      let hasParens;
//
//      if (s !== '.' && s !== '#') { return; }
//
//      parserInput.save(); // stop us absorbing part of an invalid selector
//
//      elements = this.elements();
//
//      if (elements) {
//          if (parserInput.$char('(')) {
//              args = this.args(true).args;
//              expectChar(')');
//              hasParens = true;
//          }
//
//          if (getLookup !== false) {
//              lookups = this.ruleLookups();
//          }
//          if (getLookup === true && !lookups) {
//              parserInput.restore();
//              return;
//          }
//
//          if (inValue && !lookups && !hasParens) {
//              // This isn't a valid in-value mixin call
//              parserInput.restore();
//              return;
//          }
//
//          if (!inValue && parsers.important()) {
//              important = true;
//          }
//
//          if (inValue || parsers.end()) {
//              parserInput.forget();
//              const mixin = new(tree.mixin.Call)(elements, args, index, fileInfo, !lookups && important);
//              if (lookups) {
//                  return new tree.NamespaceValue(mixin, lookups);
//              }
//              else {
//                  return mixin;
//              }
//          }
//      }
//
//      parserInput.restore();
//  },
}