definition method

MixinDefinition definition()

A Mixin definition, with a list of parameters

.rounded (@radius: 2px, @color) {
   ...
}

Until we have a finer grained state-machine, we have to do a look-ahead, to make sure we don't have a mixin call. See the rule function for more information.

We start by matching .rounded (, and then proceed on to the argument list, which has optional default values. We store the parameters in params, with a value key, if there is a value, such as in the case of @radius.

Once we've got our params list, and a closing ), we parse the {...} block.

Implementation

MixinDefinition definition() {
  if ((parserInput.currentChar() != '.' &&
          parserInput.currentChar() != '#') ||
      parserInput.peek(_reDefinition)) {
    return null;
  }

  parserInput.save();

  final String name = parserInput.$re(_definitionRegExp);
  if (name != null) {
    Condition cond;
    final argInfo = args(isCall: false);
    final index = parserInput.i; //not in original

    final params = argInfo.args;
    final variadic = argInfo.variadic;

    // .mixincall("@{a}");
    // looks a bit like a mixin definition..
    // also
    // .mixincall(@a: {rule: set;});
    // so we have to be nice and restore
    if (parserInput.$char(')') == null) {
      parserInput.restore("Missing closing ')'");
      return null;
    }

    parserInput.commentStore.length = 0;

    // Guard
    if (parserInput.$str('when') != null) {
      cond = parserInput.expect(parsers.conditions, 'expected condition');
    }

    final ruleset = parsers.block();

    if (ruleset != null) {
      parserInput.forget();
      return MixinDefinition(name, params, ruleset, cond,
          variadic: variadic,
          index: index,
          currentFileInfo: context.currentFileInfo);
    } else {
      parserInput.restore();
    }
  } else {
    parserInput.restore();
  }

  return null;

// 3.10.3 20190825
//  definition: function () {
//      let name;
//      let params = [];
//      let match;
//      let ruleset;
//      let cond;
//      let variadic = false;
//      if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
//          parserInput.peek(/^[^{]*\}/)) {
//          return;
//      }
//
//      parserInput.save();
//
//      match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
//      if (match) {
//          name = match[1];
//
//          const argInfo = this.args(false);
//          params = argInfo.args;
//          variadic = argInfo.variadic;
//
//          // .mixincall("@{a}");
//          // looks a bit like a mixin definition..
//          // also
//          // .mixincall(@a: {rule: set;});
//          // so we have to be nice and restore
//          if (!parserInput.$char(')')) {
//              parserInput.restore('Missing closing \')\'');
//              return;
//          }
//
//          parserInput.commentStore.length = 0;
//
//          if (parserInput.$str('when')) { // Guard
//              cond = expect(parsers.conditions, 'expected condition');
//          }
//
//          ruleset = parsers.block();
//
//          if (ruleset) {
//              parserInput.forget();
//              return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
//          } else {
//              parserInput.restore();
//          }
//      } else {
//          parserInput.restore();
//      }
//  },
}