processPseudoSelector method

SimpleSelector? processPseudoSelector(
  1. FileSpan start
)

Implementation

SimpleSelector? processPseudoSelector(FileSpan start) {
  // :pseudo-class ::pseudo-element
  // TODO(terry): '::' should be token.
  _eat(TokenKind.COLON);
  var pseudoElement = _maybeEat(TokenKind.COLON);

  // TODO(terry): If no identifier specified consider optimizing out the
  //              : or :: and making this a normal selector.  For now,
  //              create an empty pseudoName.
  // TODO(jiangzhou): Forced to evade
  Identifier pseudoName;
  if (_peekIdentifier()) {
    pseudoName = identifier();
    if (pseudoName.isFunction()) {
      return null;
    }
  } else {
    return null;
  }
  var name = pseudoName.name.toLowerCase();

  // Functional pseudo?
  if (_peekToken.kind == TokenKind.LPAREN) {
    if (!pseudoElement && name == 'not') {
      _eat(TokenKind.LPAREN);

      // Negation :   ':NOT(' S* negation_arg S* ')'
      var negArg = simpleSelector();

      _eat(TokenKind.RPAREN);
      return NegationSelector(negArg);
    } else if (!pseudoElement &&
        (name == 'host' || name == 'host-context' || name == 'global-context' || name == '-acx-global-context')) {
      _eat(TokenKind.LPAREN);
      var selector = processCompoundSelector();
      if (selector == null) {
        _errorExpected('a selector argument');
        return null;
      }
      _eat(TokenKind.RPAREN);
      return PseudoClassFunctionSelector(pseudoName, selector);
    } else {
      // Special parsing for expressions in pseudo functions.  Minus is used
      // as operator not identifier.
      // TODO(jmesserly): we need to flip this before we eat the "(" as the
      // next token will be fetched when we do that. I think we should try to
      // refactor so we don't need this boolean; it seems fragile.
      tokenizer.inSelectorExpression = true;
      _eat(TokenKind.LPAREN);

      // Handle function expression.
      var expr = processSelectorExpression();

      tokenizer.inSelectorExpression = false;

      // Used during selector look-a-head if not a SelectorExpression is
      // bad.
      _eat(TokenKind.RPAREN);
      return (pseudoElement)
          ? PseudoElementFunctionSelector(pseudoName, expr)
          : PseudoClassFunctionSelector(pseudoName, expr);
    }
  }

  // Treat CSS2.1 pseudo-elements defined with pseudo class syntax as pseudo-
  // elements for backwards compatibility.
  return pseudoElement || _legacyPseudoElements.contains(name)
      ? PseudoElementSelector(pseudoName, isLegacy: !pseudoElement)
      : PseudoClassSelector(pseudoName);
}