call method

Node call ({bool inValue: false, 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;
  bool hasparens = false;
  bool important = false;
  List<String> lookups;

  final int index = parserInput.i;
  final String 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 MixinCall mixin = MixinCall(elements, args,
          index: index,
          currentFileInfo: fileInfo,
          important: lookups == null && important);
      return lookups != null
          ? NamespaceValue(mixin, lookups, important: important)
          : mixin;
    }
  }

  parserInput.restore();
  return null;

// 3.5.0.beta.5 20180702
//  call: function (inValue, getLookup) {
//      var s = parserInput.currentChar(), important = false, lookups,
//          index = parserInput.i, elements, args, 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();
//              var mixin = new(tree.mixin.Call)(elements, args, index, fileInfo, !lookups && important);
//              if (lookups) {
//                  return new tree.NamespaceValue(mixin, lookups, important);
//              }
//              else {
//                  return mixin;
//              }
//          }
//      }
//
//      parserInput.restore();
//  },
}