MixinDefinition? processMixin()

in lib/parser.dart [751:845]


  MixinDefinition? processMixin() {
    _next();

    var name = identifier();

    var params = <TreeNode>[];
    // Any parameters?
    if (_maybeEat(TokenKind.LPAREN)) {
      var mustHaveParam = false;
      var keepGoing = true;
      while (keepGoing) {
        var varDef = processVariableOrDirective(mixinParameter: true);
        if (varDef is VarDefinitionDirective || varDef is VarDefinition) {
          params.add(varDef as TreeNode);
        } else if (mustHaveParam) {
          _warning('Expecting parameter', _makeSpan(_peekToken.span));
          keepGoing = false;
        }
        if (_maybeEat(TokenKind.COMMA)) {
          mustHaveParam = true;
          continue;
        }
        keepGoing = !_maybeEat(TokenKind.RPAREN);
      }
    }

    _eat(TokenKind.LBRACE);

    var productions = <TreeNode>[];
    MixinDefinition? mixinDirective;

    var start = _peekToken.span;
    while (!_maybeEat(TokenKind.END_OF_FILE)) {
      var directive = processDirective();
      if (directive != null) {
        productions.add(directive);
        continue;
      }

      var declGroup = processDeclarations(checkBrace: false);
      if (declGroup.declarations.any((decl) {
        return decl is Declaration && decl is! IncludeMixinAtDeclaration;
      })) {
        var newDecls = <Declaration>[];
        productions.forEach((include) {
          // If declGroup has items that are declarations then we assume
          // this mixin is a declaration mixin not a top-level mixin.
          if (include is IncludeDirective) {
            newDecls.add(IncludeMixinAtDeclaration(include, include.span));
          } else {
            _warning('Error mixing of top-level vs declarations mixins',
                _makeSpan(include.span as FileSpan));
          }
        });
        declGroup.declarations.insertAll(0, newDecls);
        productions = [];
      } else {
        // Declarations are just @includes make it a list of productions
        // not a declaration group (anything else is a ruleset).  Make it a
        // list of productions, not a declaration group.
        for (var decl in declGroup.declarations) {
          productions
              .add(decl is IncludeMixinAtDeclaration ? decl.include : decl);
        }
        ;
        declGroup.declarations.clear();
      }

      if (declGroup.declarations.isNotEmpty) {
        if (productions.isEmpty) {
          mixinDirective = MixinDeclarationDirective(
              name.name, params, false, declGroup, _makeSpan(start));
          break;
        } else {
          for (var decl in declGroup.declarations) {
            productions
                .add(decl is IncludeMixinAtDeclaration ? decl.include : decl);
          }
        }
      } else {
        mixinDirective = MixinRulesetDirective(
            name.name, params, false, productions, _makeSpan(start));
        break;
      }
    }

    if (productions.isNotEmpty) {
      mixinDirective = MixinRulesetDirective(
          name.name, params, false, productions, _makeSpan(start));
    }

    _eat(TokenKind.RBRACE);

    return mixinDirective;
  }