// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// ignore_for_file: prefer_asserts_in_initializer_lists

part of '../visitor.dart';

/////////////////////////////////////////////////////////////////////////
// CSS specific types:
/////////////////////////////////////////////////////////////////////////

class Identifier extends TreeNode {
  String name;

  Identifier(this.name, SourceSpan? span) : super(span);

  @override
  Identifier clone() => Identifier(name, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIdentifier(this);

  @override
  String toString() =>
      // Try to use the identifier's original lexeme to preserve any escape
      // codes as authored. The name, which may include escaped values, may no
      // longer be a valid identifier.
      span?.text ?? name;
}

class Wildcard extends TreeNode {
  Wildcard(super.span);
  @override
  Wildcard clone() => Wildcard(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitWildcard(this);

  String get name => '*';
}

class ThisOperator extends TreeNode {
  ThisOperator(super.span);
  @override
  ThisOperator clone() => ThisOperator(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitThisOperator(this);

  String get name => '&';
}

class Negation extends TreeNode {
  Negation(super.span);
  @override
  Negation clone() => Negation(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNegation(this);

  String get name => 'not';
}

// calc(...)
// TODO(terry): Hack to handle calc however the expressions should be fully
//              parsed and in the AST.
class CalcTerm extends LiteralTerm {
  final LiteralTerm expr;

  CalcTerm(Object value, String text, this.expr, SourceSpan? span)
      : super(value, text, span);

  @override
  CalcTerm clone() => CalcTerm(value, text, expr.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCalcTerm(this);

  @override
  String toString() => '$text($expr)';
}

// /*  ....   */
class CssComment extends TreeNode {
  final String comment;

  CssComment(this.comment, SourceSpan? span) : super(span);
  @override
  CssComment clone() => CssComment(comment, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCssComment(this);
}

// CDO/CDC (Comment Definition Open <!-- and Comment Definition Close -->).
class CommentDefinition extends CssComment {
  CommentDefinition(super.comment, super.span);
  @override
  CommentDefinition clone() => CommentDefinition(comment, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCommentDefinition(this);
}

class SelectorGroup extends TreeNode {
  final List<Selector> selectors;

  SelectorGroup(this.selectors, SourceSpan? span) : super(span);

  @override
  SelectorGroup clone() => SelectorGroup(selectors, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelectorGroup(this);
}

class Selector extends TreeNode {
  final List<SimpleSelectorSequence> simpleSelectorSequences;

  Selector(this.simpleSelectorSequences, SourceSpan? span) : super(span);

  void add(SimpleSelectorSequence seq) => simpleSelectorSequences.add(seq);

  int get length => simpleSelectorSequences.length;

  @override
  Selector clone() {
    var simpleSequences =
        simpleSelectorSequences.map((ss) => ss.clone()).toList();

    return Selector(simpleSequences, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelector(this);
}

class SimpleSelectorSequence extends TreeNode {
  /// +, >, ~, NONE
  int combinator;
  final SimpleSelector simpleSelector;

  SimpleSelectorSequence(this.simpleSelector, SourceSpan? span,
      [this.combinator = TokenKind.COMBINATOR_NONE])
      : super(span);

  bool get isCombinatorNone => combinator == TokenKind.COMBINATOR_NONE;
  bool get isCombinatorPlus => combinator == TokenKind.COMBINATOR_PLUS;
  bool get isCombinatorGreater => combinator == TokenKind.COMBINATOR_GREATER;
  bool get isCombinatorTilde => combinator == TokenKind.COMBINATOR_TILDE;
  bool get isCombinatorDescendant =>
      combinator == TokenKind.COMBINATOR_DESCENDANT;

  String get _combinatorToString => switch (combinator) {
        TokenKind.COMBINATOR_DESCENDANT => ' ',
        TokenKind.COMBINATOR_GREATER => ' > ',
        TokenKind.COMBINATOR_PLUS => ' + ',
        TokenKind.COMBINATOR_TILDE => ' ~ ',
        _ => ''
      };

  @override
  SimpleSelectorSequence clone() =>
      SimpleSelectorSequence(simpleSelector, span, combinator);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitSimpleSelectorSequence(this);

  @override
  String toString() => simpleSelector.name;
}

// All other selectors (element, #id, .class, attribute, pseudo, negation,
// namespace, *) are derived from this selector.
abstract class SimpleSelector extends TreeNode {
  final dynamic _name; // Wildcard, ThisOperator, Identifier, Negation, others?

  SimpleSelector(this._name, SourceSpan? span) : super(span);

  // TOOD(srawlins): Figure this one out.
  // ignore: avoid_dynamic_calls
  String get name => _name.name as String;

  bool get isWildcard => _name is Wildcard;

  bool get isThis => _name is ThisOperator;

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSimpleSelector(this);
}

// element name
class ElementSelector extends SimpleSelector {
  ElementSelector(super.name, super.span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitElementSelector(this);

  @override
  ElementSelector clone() => ElementSelector(_name, span);

  @override
  String toString() => name;
}

// namespace|element
class NamespaceSelector extends SimpleSelector {
  final dynamic _namespace; // null, Wildcard or Identifier

  NamespaceSelector(this._namespace, Object name, SourceSpan? span)
      : super(name, span);

  String get namespace => _namespace is Wildcard
      ? '*'
      : _namespace == null
          ? ''
          : (_namespace as Identifier).name;

  bool get isNamespaceWildcard => _namespace is Wildcard;

  SimpleSelector? get nameAsSimpleSelector => _name as SimpleSelector?;

  @override
  NamespaceSelector clone() => NamespaceSelector(_namespace, '', span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNamespaceSelector(this);

  @override
  String toString() => '$namespace|${nameAsSimpleSelector!.name}';
}

// [attr op value]
class AttributeSelector extends SimpleSelector {
  final int _op;
  final dynamic value;

  AttributeSelector(Identifier name, this._op, this.value, SourceSpan? span)
      : super(name, span);

  int get operatorKind => _op;

  String? matchOperator() => switch (_op) {
        TokenKind.EQUALS => '=',
        TokenKind.INCLUDES => '~=',
        TokenKind.DASH_MATCH => '|=',
        TokenKind.PREFIX_MATCH => '^=',
        TokenKind.SUFFIX_MATCH => '\$=',
        TokenKind.SUBSTRING_MATCH => '*=',
        TokenKind.NO_MATCH => '',
        _ => null
      };

  // Return the TokenKind for operator used by visitAttributeSelector.
  String? matchOperatorAsTokenString() => switch (_op) {
        TokenKind.EQUALS => 'EQUALS',
        TokenKind.INCLUDES => 'INCLUDES',
        TokenKind.DASH_MATCH => 'DASH_MATCH',
        TokenKind.PREFIX_MATCH => 'PREFIX_MATCH',
        TokenKind.SUFFIX_MATCH => 'SUFFIX_MATCH',
        TokenKind.SUBSTRING_MATCH => 'SUBSTRING_MATCH',
        _ => null
      };

  String valueToString() {
    if (value != null) {
      if (value is Identifier) {
        return value.toString();
      } else {
        return '"$value"';
      }
    } else {
      return '';
    }
  }

  @override
  AttributeSelector clone() =>
      AttributeSelector(_name as Identifier, _op, value, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitAttributeSelector(this);

  @override
  String toString() => '[$name${matchOperator()}${valueToString()}]';
}

// #id
class IdSelector extends SimpleSelector {
  IdSelector(Identifier super.name, super.span);
  @override
  IdSelector clone() => IdSelector(_name as Identifier, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIdSelector(this);

  @override
  String toString() => '#$_name';
}

// .class
class ClassSelector extends SimpleSelector {
  ClassSelector(Identifier super.name, super.span);
  @override
  ClassSelector clone() => ClassSelector(_name as Identifier, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitClassSelector(this);

  @override
  String toString() => '.$_name';
}

// :pseudoClass
class PseudoClassSelector extends SimpleSelector {
  PseudoClassSelector(Identifier super.name, super.span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPseudoClassSelector(this);

  @override
  PseudoClassSelector clone() => PseudoClassSelector(_name as Identifier, span);

  @override
  String toString() => ':$name';
}

// ::pseudoElement
class PseudoElementSelector extends SimpleSelector {
  // If true, this is a CSS2.1 pseudo-element with only a single ':'.
  final bool isLegacy;

  PseudoElementSelector(Identifier super.name, super.span,
      {this.isLegacy = false});
  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoElementSelector(this);

  @override
  PseudoElementSelector clone() =>
      PseudoElementSelector(_name as Identifier, span);

  @override
  String toString() => "${isLegacy ? ':' : '::'}$name";
}

// :pseudoClassFunction(argument)
class PseudoClassFunctionSelector extends PseudoClassSelector {
  final TreeNode argument; // Selector, SelectorExpression

  PseudoClassFunctionSelector(Identifier name, this.argument, SourceSpan? span)
      : super(name, span);

  @override
  PseudoClassFunctionSelector clone() =>
      PseudoClassFunctionSelector(_name as Identifier, argument, span);

  Selector get selector => argument as Selector;
  SelectorExpression get expression => argument as SelectorExpression;

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoClassFunctionSelector(this);
}

// ::pseudoElementFunction(expression)
class PseudoElementFunctionSelector extends PseudoElementSelector {
  final SelectorExpression expression;

  PseudoElementFunctionSelector(
      Identifier name, this.expression, SourceSpan? span)
      : super(name, span);

  @override
  PseudoElementFunctionSelector clone() =>
      PseudoElementFunctionSelector(_name as Identifier, expression, span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitPseudoElementFunctionSelector(this);
}

class SelectorExpression extends TreeNode {
  final List<Expression> expressions;

  SelectorExpression(this.expressions, SourceSpan? span) : super(span);

  @override
  SourceSpan get span => super.span!;

  @override
  SelectorExpression clone() =>
      SelectorExpression(expressions.map((e) => e.clone()).toList(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSelectorExpression(this);
}

// :NOT(negation_arg)
class NegationSelector extends SimpleSelector {
  final SimpleSelector? negationArg;

  NegationSelector(this.negationArg, SourceSpan? span)
      : super(Negation(span), span);

  @override
  NegationSelector clone() => NegationSelector(negationArg, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNegationSelector(this);
}

class NoOp extends TreeNode {
  NoOp() : super(null);

  @override
  NoOp clone() => NoOp();

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNoOp(this);
}

class StyleSheet extends TreeNode {
  /// Contains charset, ruleset, directives (media, page, etc.), and selectors.
  final List<TreeNode> topLevels;

  StyleSheet(this.topLevels, SourceSpan? span) : super(span) {
    for (final node in topLevels) {
      assert(node is TopLevelProduction || node is Directive);
    }
  }

  /// Selectors only in this tree.
  StyleSheet.selector(this.topLevels, SourceSpan? span) : super(span);

  @override
  SourceSpan get span => super.span!;

  @override
  StyleSheet clone() {
    var clonedTopLevels = topLevels.map((e) => e.clone()).toList();
    return StyleSheet(clonedTopLevels, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitStyleSheet(this);
}

class TopLevelProduction extends TreeNode {
  TopLevelProduction(super.span);
  @override
  SourceSpan get span => super.span!;
  @override
  TopLevelProduction clone() => TopLevelProduction(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this);
}

class RuleSet extends TopLevelProduction {
  final SelectorGroup? selectorGroup;
  final DeclarationGroup declarationGroup;

  RuleSet(this.selectorGroup, this.declarationGroup, SourceSpan? span)
      : super(span);

  @override
  RuleSet clone() {
    var cloneSelectorGroup = selectorGroup!.clone();
    var cloneDeclarationGroup = declarationGroup.clone();
    return RuleSet(cloneSelectorGroup, cloneDeclarationGroup, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitRuleSet(this);
}

class Directive extends TreeNode {
  Directive(super.span);

  bool get isBuiltIn => true; // Known CSS directive?
  bool get isExtension => false; // SCSS extension?

  @override
  SourceSpan get span => super.span!;

  @override
  Directive clone() => Directive(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDirective(this);
}

class DocumentDirective extends Directive {
  final List<LiteralTerm> functions;
  final List<TreeNode> groupRuleBody;

  DocumentDirective(this.functions, this.groupRuleBody, SourceSpan? span)
      : super(span);

  @override
  DocumentDirective clone() {
    var clonedFunctions = <LiteralTerm>[];
    for (var function in functions) {
      clonedFunctions.add(function.clone());
    }
    var clonedGroupRuleBody = <TreeNode>[];
    for (var rule in groupRuleBody) {
      clonedGroupRuleBody.add(rule.clone());
    }
    return DocumentDirective(clonedFunctions, clonedGroupRuleBody, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDocumentDirective(this);
}

class SupportsDirective extends Directive {
  final SupportsCondition? condition;
  final List<TreeNode> groupRuleBody;

  SupportsDirective(this.condition, this.groupRuleBody, SourceSpan? span)
      : super(span);

  @override
  SupportsDirective clone() {
    var clonedCondition = condition!.clone() as SupportsCondition;
    var clonedGroupRuleBody = <TreeNode>[];
    for (var rule in groupRuleBody) {
      clonedGroupRuleBody.add(rule.clone());
    }
    return SupportsDirective(clonedCondition, clonedGroupRuleBody, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsDirective(this);
}

abstract class SupportsCondition extends TreeNode {
  SupportsCondition(super.span);
  @override
  SourceSpan get span => super.span!;
}

class SupportsConditionInParens extends SupportsCondition {
  /// A [Declaration] or nested [SupportsCondition].
  final TreeNode? condition;

  SupportsConditionInParens(Declaration? declaration, super.span)
      : condition = declaration;

  SupportsConditionInParens.nested(this.condition, SourceSpan? span)
      : super(span);

  @override
  SupportsConditionInParens clone() =>
      SupportsConditionInParens(condition!.clone() as Declaration, span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitSupportsConditionInParens(this);
}

class SupportsNegation extends SupportsCondition {
  final SupportsConditionInParens condition;

  SupportsNegation(this.condition, SourceSpan? span) : super(span);

  @override
  SupportsNegation clone() => SupportsNegation(condition.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsNegation(this);
}

class SupportsConjunction extends SupportsCondition {
  final List<SupportsConditionInParens> conditions;

  SupportsConjunction(this.conditions, SourceSpan? span) : super(span);

  @override
  SupportsConjunction clone() {
    var clonedConditions = <SupportsConditionInParens>[];
    for (var condition in conditions) {
      clonedConditions.add(condition.clone());
    }
    return SupportsConjunction(clonedConditions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsConjunction(this);
}

class SupportsDisjunction extends SupportsCondition {
  final List<SupportsConditionInParens> conditions;

  SupportsDisjunction(this.conditions, SourceSpan? span) : super(span);

  @override
  SupportsDisjunction clone() {
    var clonedConditions = <SupportsConditionInParens>[];
    for (var condition in conditions) {
      clonedConditions.add(condition.clone());
    }
    return SupportsDisjunction(clonedConditions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitSupportsDisjunction(this);
}

class ViewportDirective extends Directive {
  final String name;
  final DeclarationGroup declarations;

  ViewportDirective(this.name, this.declarations, SourceSpan? span)
      : super(span);

  @override
  ViewportDirective clone() =>
      ViewportDirective(name, declarations.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitViewportDirective(this);
}

class ImportDirective extends Directive {
  /// import name specified.
  final String import;

  /// Any media queries for this import.
  final List<MediaQuery> mediaQueries;

  ImportDirective(this.import, this.mediaQueries, SourceSpan? span)
      : super(span);

  @override
  ImportDirective clone() {
    var cloneMediaQueries = <MediaQuery>[];
    for (var mediaQuery in mediaQueries) {
      cloneMediaQueries.add(mediaQuery.clone());
    }
    return ImportDirective(import, cloneMediaQueries, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitImportDirective(this);
}

/// MediaExpression grammar:
///
///     '(' S* media_feature S* [ ':' S* expr ]? ')' S*
class MediaExpression extends TreeNode {
  final bool andOperator;
  final Identifier _mediaFeature;
  final Expressions exprs;

  MediaExpression(
      this.andOperator, this._mediaFeature, this.exprs, SourceSpan? span)
      : super(span);

  String get mediaFeature => _mediaFeature.name;

  @override
  SourceSpan get span => super.span!;

  @override
  MediaExpression clone() {
    var clonedExprs = exprs.clone();
    return MediaExpression(andOperator, _mediaFeature, clonedExprs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaExpression(this);
}

/// MediaQuery grammar:
///
///      : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
///      | media_expression [ AND S* media_expression ]*
///     media_type
///      : IDENT
///     media_expression
///      : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
///     media_feature
///      : IDENT
class MediaQuery extends TreeNode {
  /// not, only or no operator.
  final int _mediaUnary;
  final Identifier? _mediaType;
  final List<MediaExpression> expressions;

  MediaQuery(
      this._mediaUnary, this._mediaType, this.expressions, SourceSpan? span)
      : super(span);

  bool get hasMediaType => _mediaType != null;
  String get mediaType => _mediaType!.name;

  bool get hasUnary => _mediaUnary != -1;
  String get unary =>
      TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary)!
          .toUpperCase();

  @override
  SourceSpan get span => super.span!;

  @override
  MediaQuery clone() {
    var cloneExpressions = <MediaExpression>[];
    for (var expr in expressions) {
      cloneExpressions.add(expr.clone());
    }
    return MediaQuery(_mediaUnary, _mediaType, cloneExpressions, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaQuery(this);
}

class MediaDirective extends Directive {
  final List<MediaQuery> mediaQueries;
  final List<TreeNode> rules;

  MediaDirective(this.mediaQueries, this.rules, SourceSpan? span) : super(span);

  @override
  MediaDirective clone() {
    var cloneQueries = <MediaQuery>[];
    for (var mediaQuery in mediaQueries) {
      cloneQueries.add(mediaQuery.clone());
    }
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return MediaDirective(cloneQueries, cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMediaDirective(this);
}

class HostDirective extends Directive {
  final List<TreeNode> rules;

  HostDirective(this.rules, SourceSpan? span) : super(span);

  @override
  HostDirective clone() {
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return HostDirective(cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHostDirective(this);
}

class PageDirective extends Directive {
  final String? _ident;
  final String? _pseudoPage;
  final List<DeclarationGroup> _declsMargin;

  PageDirective(
      this._ident, this._pseudoPage, this._declsMargin, SourceSpan? span)
      : super(span);

  @override
  PageDirective clone() {
    var cloneDeclsMargin = <DeclarationGroup>[];
    for (var declMargin in _declsMargin) {
      cloneDeclsMargin.add(declMargin.clone());
    }
    return PageDirective(_ident, _pseudoPage, cloneDeclsMargin, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPageDirective(this);

  bool get hasIdent => _ident?.isNotEmpty ?? false;
  bool get hasPseudoPage => _pseudoPage?.isNotEmpty ?? false;
}

class CharsetDirective extends Directive {
  final String charEncoding;

  CharsetDirective(this.charEncoding, SourceSpan? span) : super(span);
  @override
  CharsetDirective clone() => CharsetDirective(charEncoding, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitCharsetDirective(this);
}

class KeyFrameDirective extends Directive {
  // Either @keyframe or keyframe prefixed with @-webkit-, @-moz-, @-ms-, @-o-.
  final int _keyframeName;
  final Identifier? name;
  final List<KeyFrameBlock> _blocks;

  KeyFrameDirective(this._keyframeName, this.name, SourceSpan? span)
      : _blocks = [],
        super(span);

  void add(KeyFrameBlock block) {
    _blocks.add(block);
  }

  String? get keyFrameName => switch (_keyframeName) {
        TokenKind.DIRECTIVE_KEYFRAMES ||
        TokenKind.DIRECTIVE_MS_KEYFRAMES =>
          '@keyframes',
        TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES => '@-webkit-keyframes',
        TokenKind.DIRECTIVE_MOZ_KEYFRAMES => '@-moz-keyframes',
        TokenKind.DIRECTIVE_O_KEYFRAMES => '@-o-keyframes',
        _ => null
      };

  @override
  KeyFrameDirective clone() {
    var directive = KeyFrameDirective(_keyframeName, name!.clone(), span);
    for (var block in _blocks) {
      directive.add(block.clone());
    }
    return directive;
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this);
}

class KeyFrameBlock extends Expression {
  final Expressions _blockSelectors;
  final DeclarationGroup _declarations;

  KeyFrameBlock(this._blockSelectors, this._declarations, SourceSpan? span)
      : super(span);

  @override
  KeyFrameBlock clone() =>
      KeyFrameBlock(_blockSelectors.clone(), _declarations.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this);
}

class FontFaceDirective extends Directive {
  final DeclarationGroup _declarations;

  FontFaceDirective(this._declarations, SourceSpan? span) : super(span);

  @override
  FontFaceDirective clone() => FontFaceDirective(_declarations.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this);
}

class StyletDirective extends Directive {
  final String dartClassName;
  final List<TreeNode> rules;

  StyletDirective(this.dartClassName, this.rules, SourceSpan? span)
      : super(span);

  @override
  bool get isBuiltIn => false;
  @override
  bool get isExtension => true;

  @override
  StyletDirective clone() {
    var cloneRules = <TreeNode>[];
    for (var rule in rules) {
      cloneRules.add(rule.clone());
    }
    return StyletDirective(dartClassName, cloneRules, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitStyletDirective(this);
}

class NamespaceDirective extends Directive {
  /// Namespace prefix.
  final String _prefix;

  /// URI associated with this namespace.
  final String? _uri;

  NamespaceDirective(this._prefix, this._uri, SourceSpan? span) : super(span);

  @override
  NamespaceDirective clone() => NamespaceDirective(_prefix, _uri, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this);

  String get prefix => _prefix.isNotEmpty ? '$_prefix ' : '';
}

/// To support Less syntax @name: expression
class VarDefinitionDirective extends Directive {
  final VarDefinition def;

  VarDefinitionDirective(this.def, SourceSpan? span) : super(span);

  @override
  VarDefinitionDirective clone() => VarDefinitionDirective(def.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitVarDefinitionDirective(this);
}

class MixinDefinition extends Directive {
  final String name;
  final List<TreeNode> definedArgs;
  final bool varArgs;

  MixinDefinition(this.name, this.definedArgs, this.varArgs, SourceSpan? span)
      : super(span);

  @override
  MixinDefinition clone() {
    var cloneDefinedArgs = <TreeNode>[];
    for (var definedArg in definedArgs) {
      cloneDefinedArgs.add(definedArg.clone());
    }
    return MixinDefinition(name, cloneDefinedArgs, varArgs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMixinDefinition(this);
}

/// Support a Sass @mixin. See http://sass-lang.com for description.
class MixinRulesetDirective extends MixinDefinition {
  final List<TreeNode> rulesets;

  MixinRulesetDirective(String name, List<TreeNode> args, bool varArgs,
      this.rulesets, SourceSpan? span)
      : super(name, args, varArgs, span);

  @override
  MixinRulesetDirective clone() {
    var clonedArgs = <VarDefinition>[];
    for (var arg in definedArgs) {
      clonedArgs.add(arg.clone() as VarDefinition);
    }
    var clonedRulesets = <TreeNode>[];
    for (var ruleset in rulesets) {
      clonedRulesets.add(ruleset.clone());
    }
    return MixinRulesetDirective(
        name, clonedArgs, varArgs, clonedRulesets, span);
  }

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitMixinRulesetDirective(this);
}

class MixinDeclarationDirective extends MixinDefinition {
  final DeclarationGroup declarations;

  MixinDeclarationDirective(String name, List<TreeNode> args, bool varArgs,
      this.declarations, SourceSpan? span)
      : super(name, args, varArgs, span);

  @override
  MixinDeclarationDirective clone() {
    var clonedArgs = <TreeNode>[];
    for (var arg in definedArgs) {
      clonedArgs.add(arg.clone());
    }
    return MixinDeclarationDirective(
        name, clonedArgs, varArgs, declarations.clone(), span);
  }

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitMixinDeclarationDirective(this);
}

/// To support consuming a Sass mixin @include.
class IncludeDirective extends Directive {
  final String name;
  final List<List<Expression>> args;

  IncludeDirective(this.name, this.args, SourceSpan? span) : super(span);

  @override
  IncludeDirective clone() {
    var cloneArgs = <List<Expression>>[];
    for (var arg in args) {
      cloneArgs.add(arg.map((term) => term.clone()).toList());
    }
    return IncludeDirective(name, cloneArgs, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIncludeDirective(this);
}

/// To support Sass @content.
class ContentDirective extends Directive {
  ContentDirective(super.span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitContentDirective(this);
}

class Declaration extends TreeNode {
  final Identifier? _property;
  final Expression? expression;

  /// Style exposed to Dart.
  DartStyleExpression? dartStyle;
  final bool important;

  /// IE CSS hacks that can only be read by a particular IE version.
  /// 7 implies IE 7 or older property (e.g., `*background: blue;`)
  ///
  /// * Note:  IE 8 or older property (e.g., `background: green\9;`) is handled
  ///   by IE8Term in declaration expression handling.
  /// * Note:  IE 6 only property with a leading underscore is a valid IDENT
  ///   since an ident can start with underscore (e.g., `_background: red;`)
  final bool isIE7;

  Declaration(this._property, this.expression, this.dartStyle, SourceSpan? span,
      {this.important = false, bool ie7 = false})
      : isIE7 = ie7,
        super(span);

  String get property => isIE7 ? '*${_property!.name}' : _property!.name;

  bool get hasDartStyle => dartStyle != null;

  @override
  SourceSpan get span => super.span!;

  @override
  Declaration clone() =>
      Declaration(_property!.clone(), expression!.clone(), dartStyle, span,
          important: important);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDeclaration(this);
}

// TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and
//              dynamic when in a declaration.  Currently, Less syntax
//              '@foo: expression' and 'var-foo: expression' in a declaration
//              are statically resolved. Better solution, if @foo or var-foo
//              are top-level are then statically resolved and var-foo in a
//              declaration group (surrounded by a selector) would be dynamic.
class VarDefinition extends Declaration {
  bool badUsage = false;

  VarDefinition(Identifier? definedName, Expression? expr, SourceSpan? span)
      : super(definedName, expr, null, span);

  String get definedName => _property!.name;

  @override
  VarDefinition clone() =>
      VarDefinition(_property!.clone(), expression?.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitVarDefinition(this);
}

/// Node for usage of @include mixin[(args,...)] found in a declaration group
/// instead of at a ruleset (toplevel) e.g.,
///
///     div {
///       @include mixin1;
///     }
class IncludeMixinAtDeclaration extends Declaration {
  final IncludeDirective include;

  IncludeMixinAtDeclaration(this.include, SourceSpan? span)
      : super(null, null, null, span);

  @override
  IncludeMixinAtDeclaration clone() =>
      IncludeMixinAtDeclaration(include.clone(), span);

  @override
  dynamic visit(VisitorBase visitor) =>
      visitor.visitIncludeMixinAtDeclaration(this);
}

class ExtendDeclaration extends Declaration {
  final List<TreeNode> selectors;

  ExtendDeclaration(this.selectors, SourceSpan? span)
      : super(null, null, null, span);

  @override
  ExtendDeclaration clone() {
    var newSelector = selectors.map((s) => s.clone()).toList();
    return ExtendDeclaration(newSelector, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExtendDeclaration(this);
}

class DeclarationGroup extends TreeNode {
  /// Can be either Declaration or RuleSet (if nested selector).
  final List<TreeNode> declarations;

  DeclarationGroup(this.declarations, SourceSpan? span) : super(span);

  @override
  SourceSpan get span => super.span!;

  @override
  DeclarationGroup clone() {
    var clonedDecls = declarations.map((d) => d.clone()).toList();
    return DeclarationGroup(clonedDecls, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this);
}

class MarginGroup extends DeclarationGroup {
  // ignore: non_constant_identifier_names
  final int margin_sym; // TokenType for for @margin sym.

  MarginGroup(this.margin_sym, List<TreeNode> decls, SourceSpan? span)
      : super(decls, span);
  @override
  MarginGroup clone() =>
      MarginGroup(margin_sym, super.clone().declarations, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMarginGroup(this);
}

class VarUsage extends Expression {
  final String name;
  final List<Expression> defaultValues;

  VarUsage(this.name, this.defaultValues, SourceSpan? span) : super(span);

  @override
  VarUsage clone() {
    var clonedValues = <Expression>[];
    for (var expr in defaultValues) {
      clonedValues.add(expr.clone());
    }
    return VarUsage(name, clonedValues, span);
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitVarUsage(this);
}

class OperatorSlash extends Expression {
  OperatorSlash(super.span);
  @override
  OperatorSlash clone() => OperatorSlash(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorSlash(this);
}

class OperatorComma extends Expression {
  OperatorComma(super.span);
  @override
  OperatorComma clone() => OperatorComma(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorComma(this);
}

class OperatorPlus extends Expression {
  OperatorPlus(super.span);
  @override
  OperatorPlus clone() => OperatorPlus(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorPlus(this);
}

class OperatorMinus extends Expression {
  OperatorMinus(super.span);
  @override
  OperatorMinus clone() => OperatorMinus(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitOperatorMinus(this);
}

class UnicodeRangeTerm extends Expression {
  final String? first;
  final String? second;

  UnicodeRangeTerm(this.first, this.second, SourceSpan? span) : super(span);

  bool get hasSecond => second != null;

  @override
  UnicodeRangeTerm clone() => UnicodeRangeTerm(first, second, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this);
}

class LiteralTerm extends Expression {
  // TODO(terry): value and text fields can be made final once all CSS resources
  //              are copied/symlink'd in the build tool and UriVisitor in
  //              web_ui is removed.
  Object value;
  String text;

  LiteralTerm(this.value, this.text, SourceSpan? span) : super(span);

  @override
  LiteralTerm clone() => LiteralTerm(value, text, span);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitLiteralTerm(this);
}

class NumberTerm extends LiteralTerm {
  NumberTerm(super.value, super.text, super.span);
  @override
  NumberTerm clone() => NumberTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitNumberTerm(this);
}

class UnitTerm extends LiteralTerm {
  final int unit;

  UnitTerm(super.value, super.text, super.span, this.unit);

  @override
  UnitTerm clone() => UnitTerm(value, text, span, unit);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnitTerm(this);

  String? unitToString() => TokenKind.unitToString(unit);

  @override
  String toString() => '$text${unitToString()}';
}

class LengthTerm extends UnitTerm {
  LengthTerm(super.value, super.text, super.span,
      [super.unit = TokenKind.UNIT_LENGTH_PX]) {
    assert(unit == TokenKind.UNIT_LENGTH_PX ||
        unit == TokenKind.UNIT_LENGTH_CM ||
        unit == TokenKind.UNIT_LENGTH_MM ||
        unit == TokenKind.UNIT_LENGTH_IN ||
        unit == TokenKind.UNIT_LENGTH_PT ||
        unit == TokenKind.UNIT_LENGTH_PC);
  }
  @override
  LengthTerm clone() => LengthTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitLengthTerm(this);
}

class PercentageTerm extends LiteralTerm {
  PercentageTerm(super.value, super.text, super.span);
  @override
  PercentageTerm clone() => PercentageTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPercentageTerm(this);
}

class EmTerm extends LiteralTerm {
  EmTerm(super.value, super.text, super.span);
  @override
  EmTerm clone() => EmTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitEmTerm(this);
}

class ExTerm extends LiteralTerm {
  ExTerm(super.value, super.text, super.span);
  @override
  ExTerm clone() => ExTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExTerm(this);
}

class AngleTerm extends UnitTerm {
  AngleTerm(super.value, super.text, super.span,
      [super.unit = TokenKind.UNIT_LENGTH_PX]) {
    assert(unit == TokenKind.UNIT_ANGLE_DEG ||
        unit == TokenKind.UNIT_ANGLE_RAD ||
        unit == TokenKind.UNIT_ANGLE_GRAD ||
        unit == TokenKind.UNIT_ANGLE_TURN);
  }

  @override
  AngleTerm clone() => AngleTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitAngleTerm(this);
}

class TimeTerm extends UnitTerm {
  TimeTerm(super.value, super.text, super.span,
      [super.unit = TokenKind.UNIT_LENGTH_PX]) {
    assert(unit == TokenKind.UNIT_ANGLE_DEG ||
        unit == TokenKind.UNIT_TIME_MS ||
        unit == TokenKind.UNIT_TIME_S);
  }

  @override
  TimeTerm clone() => TimeTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitTimeTerm(this);
}

class FreqTerm extends UnitTerm {
  FreqTerm(Object value, String text, SourceSpan? span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_FREQ_HZ || unit == TokenKind.UNIT_FREQ_KHZ);
  }

  @override
  FreqTerm clone() => FreqTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFreqTerm(this);
}

class FractionTerm extends LiteralTerm {
  FractionTerm(super.value, super.text, super.span);

  @override
  FractionTerm clone() => FractionTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFractionTerm(this);
}

class UriTerm extends LiteralTerm {
  UriTerm(String value, SourceSpan? span) : super(value, value, span);

  @override
  UriTerm clone() => UriTerm(value as String, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUriTerm(this);
}

class ResolutionTerm extends UnitTerm {
  ResolutionTerm(Object value, String text, SourceSpan? span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_RESOLUTION_DPI ||
        unit == TokenKind.UNIT_RESOLUTION_DPCM ||
        unit == TokenKind.UNIT_RESOLUTION_DPPX);
  }

  @override
  ResolutionTerm clone() => ResolutionTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitResolutionTerm(this);
}

class ChTerm extends UnitTerm {
  ChTerm(Object value, String text, SourceSpan? span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_CH);
  }

  @override
  ChTerm clone() => ChTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitChTerm(this);
}

class RemTerm extends UnitTerm {
  RemTerm(Object value, String text, SourceSpan? span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_REM);
  }

  @override
  RemTerm clone() => RemTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitRemTerm(this);
}

class LineHeightTerm extends UnitTerm {
  LineHeightTerm(Object value, String text, SourceSpan? span, int unit)
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_LH || unit == TokenKind.UNIT_RLH);
  }
  @override
  LineHeightTerm clone() => LineHeightTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitLineHeightTerm(this);
}

class ViewportTerm extends UnitTerm {
  ViewportTerm(Object value, String text, SourceSpan? span,
      [int unit = TokenKind.UNIT_LENGTH_PX])
      : super(value, text, span, unit) {
    assert(unit == TokenKind.UNIT_VIEWPORT_VW ||
        unit == TokenKind.UNIT_VIEWPORT_VH ||
        unit == TokenKind.UNIT_VIEWPORT_VMIN ||
        unit == TokenKind.UNIT_VIEWPORT_VMAX);
  }

  @override
  ViewportTerm clone() => ViewportTerm(value, text, span, unit);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitViewportTerm(this);
}

/// Type to signal a bad hex value for HexColorTerm.value.
// ignore: camel_case_types
class BAD_HEX_VALUE {}

class HexColorTerm extends LiteralTerm {
  HexColorTerm(super.value, super.text, super.span);

  @override
  HexColorTerm clone() => HexColorTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHexColorTerm(this);
}

class FunctionTerm extends LiteralTerm {
  final Expressions _params;

  FunctionTerm(Object value, String text, this._params, SourceSpan? span)
      : super(value, text, span);

  @override
  FunctionTerm clone() => FunctionTerm(value, text, _params.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFunctionTerm(this);
}

/// A "\9" was encountered at the end of the expression and before a semi-colon.
/// This is an IE trick to ignore a property or value except by IE 8 and older
/// browsers.
class IE8Term extends LiteralTerm {
  IE8Term(SourceSpan? span) : super('\\9', '\\9', span);
  @override
  IE8Term clone() => IE8Term(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitIE8Term(this);
}

class GroupTerm extends Expression {
  final List<LiteralTerm> _terms;

  GroupTerm(super.span) : _terms = [];

  void add(LiteralTerm term) {
    _terms.add(term);
  }

  @override
  GroupTerm clone() => GroupTerm(span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitGroupTerm(this);
}

class ItemTerm extends NumberTerm {
  ItemTerm(super.value, super.text, super.span);

  @override
  ItemTerm clone() => ItemTerm(value, text, span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitItemTerm(this);
}

class Expressions extends Expression {
  final List<Expression> expressions = [];

  Expressions(super.span);

  void add(Expression expression) {
    expressions.add(expression);
  }

  @override
  Expressions clone() {
    var clonedExprs = Expressions(span);
    for (var expr in expressions) {
      clonedExprs.add(expr.clone());
    }
    return clonedExprs;
  }

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitExpressions(this);
}

class BinaryExpression extends Expression {
  final Token op;
  final Expression x;
  final Expression y;

  BinaryExpression(this.op, this.x, this.y, SourceSpan? span) : super(span);

  @override
  BinaryExpression clone() => BinaryExpression(op, x.clone(), y.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBinaryExpression(this);
}

class UnaryExpression extends Expression {
  final Token op;
  final Expression self;

  UnaryExpression(this.op, this.self, SourceSpan? span) : super(span);

  @override
  UnaryExpression clone() => UnaryExpression(op, self.clone(), span);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitUnaryExpression(this);
}

abstract class DartStyleExpression extends TreeNode {
  static const int unknownType = 0;
  static const int fontStyle = 1;
  static const int marginStyle = 2;
  static const int borderStyle = 3;
  static const int paddingStyle = 4;
  static const int heightStyle = 5;
  static const int widthStyle = 6;

  final int? _styleType;
  int? priority;

  DartStyleExpression(this._styleType, SourceSpan? span) : super(span);

  // Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
  // e.g., FontExpression, etc.) will merge if the two expressions are of the
  // same property name (implies same exact type e.g, FontExpression).
  DartStyleExpression? merged(DartStyleExpression newDartExpr);

  bool get isUnknown => _styleType == 0 || _styleType == null;
  bool get isFont => _styleType == fontStyle;
  bool get isMargin => _styleType == marginStyle;
  bool get isBorder => _styleType == borderStyle;
  bool get isPadding => _styleType == paddingStyle;
  bool get isHeight => _styleType == heightStyle;
  bool get isWidth => _styleType == widthStyle;
  bool get isBoxExpression => isMargin || isBorder || isPadding;

  bool isSame(DartStyleExpression other) => _styleType == other._styleType;

  @override
  SourceSpan get span => super.span!;

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this);
}

class FontExpression extends DartStyleExpression {
  final Font font;

  //   font-style font-variant font-weight font-size/line-height font-family
  // TODO(terry): Only px/pt for now need to handle all possible units to
  //              support calc expressions on units.
  FontExpression(SourceSpan? span,
      {Object? /* LengthTerm | num */ size,
      List<String>? family,
      int? weight,
      String? style,
      String? variant,
      LineHeight? lineHeight})
      : font = Font(
            size: (size is LengthTerm ? size.value : size) as num?,
            family: family,
            weight: weight,
            style: style,
            variant: variant,
            lineHeight: lineHeight),
        super(DartStyleExpression.fontStyle, span);

  @override
  FontExpression? merged(DartStyleExpression newDartExpr) {
    if (newDartExpr is FontExpression && isFont && newDartExpr.isFont) {
      return FontExpression.merge(this, newDartExpr);
    }
    return null;
  }

  /// Merge the two FontExpression and return the result.
  factory FontExpression.merge(FontExpression x, FontExpression y) =>
      FontExpression._merge(x, y, y.span);

  FontExpression._merge(FontExpression x, FontExpression y, SourceSpan? span)
      : font = Font.merge(x.font, y.font)!,
        super(DartStyleExpression.fontStyle, span);

  @override
  FontExpression clone() => FontExpression(span,
      size: font.size,
      family: font.family,
      weight: font.weight,
      style: font.style,
      variant: font.variant,
      lineHeight: font.lineHeight);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitFontExpression(this);
}

abstract class BoxExpression extends DartStyleExpression {
  final BoxEdge? box;

  BoxExpression(super.styleType, super.span, this.box);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBoxExpression(this);

  String get formattedBoxEdge {
    if (box!.top == box!.left &&
        box!.top == box!.bottom &&
        box!.top == box!.right) {
      return '.uniform(${box!.top})';
    } else {
      var left = box!.left ?? 0;
      var top = box!.top ?? 0;
      var right = box!.right ?? 0;
      var bottom = box!.bottom ?? 0;
      return '.clockwiseFromTop($top,$right,$bottom,$left)';
    }
  }
}

class MarginExpression extends BoxExpression {
  // TODO(terry): Does auto for margin need to be exposed to Dart UI framework?
  /// Margin expression ripped apart.
  MarginExpression(SourceSpan? span,
      {num? top, num? right, num? bottom, num? left})
      : super(DartStyleExpression.marginStyle, span,
            BoxEdge(left, top, right, bottom));

  MarginExpression.boxEdge(SourceSpan? span, BoxEdge? box)
      : super(DartStyleExpression.marginStyle, span, box);

  @override
  MarginExpression? merged(DartStyleExpression newDartExpr) {
    if (newDartExpr is MarginExpression && isMargin && newDartExpr.isMargin) {
      return MarginExpression.merge(this, newDartExpr);
    }

    return null;
  }

  /// Merge the two MarginExpressions and return the result.
  factory MarginExpression.merge(MarginExpression x, MarginExpression y) =>
      MarginExpression._merge(x, y, y.span);

  MarginExpression._merge(
      MarginExpression x, MarginExpression y, SourceSpan? span)
      : super(x._styleType, span, BoxEdge.merge(x.box, y.box));

  @override
  MarginExpression clone() => MarginExpression(span,
      top: box!.top, right: box!.right, bottom: box!.bottom, left: box!.left);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitMarginExpression(this);
}

class BorderExpression extends BoxExpression {
  /// Border expression ripped apart.
  BorderExpression(SourceSpan? span,
      {num? top, num? right, num? bottom, num? left})
      : super(DartStyleExpression.borderStyle, span,
            BoxEdge(left, top, right, bottom));

  BorderExpression.boxEdge(SourceSpan? span, BoxEdge box)
      : super(DartStyleExpression.borderStyle, span, box);

  @override
  BorderExpression? merged(DartStyleExpression newDartExpr) {
    if (newDartExpr is BorderExpression && isBorder && newDartExpr.isBorder) {
      return BorderExpression.merge(this, newDartExpr);
    }

    return null;
  }

  /// Merge the two BorderExpression and return the result.
  factory BorderExpression.merge(BorderExpression x, BorderExpression y) =>
      BorderExpression._merge(x, y, y.span);

  BorderExpression._merge(
      BorderExpression x, BorderExpression y, SourceSpan? span)
      : super(
            DartStyleExpression.borderStyle, span, BoxEdge.merge(x.box, y.box));

  @override
  BorderExpression clone() => BorderExpression(span,
      top: box!.top, right: box!.right, bottom: box!.bottom, left: box!.left);

  @override
  dynamic visit(VisitorBase visitor) => visitor.visitBorderExpression(this);
}

class HeightExpression extends DartStyleExpression {
  final dynamic height;

  HeightExpression(SourceSpan? span, this.height)
      : super(DartStyleExpression.heightStyle, span);

  @override
  HeightExpression? merged(DartStyleExpression newDartExpr) {
    if (isHeight && newDartExpr.isHeight) {
      return newDartExpr as HeightExpression;
    }

    return null;
  }

  @override
  HeightExpression clone() => HeightExpression(span, height);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitHeightExpression(this);
}

class WidthExpression extends DartStyleExpression {
  final dynamic width;

  WidthExpression(SourceSpan? span, this.width)
      : super(DartStyleExpression.widthStyle, span);

  @override
  WidthExpression? merged(DartStyleExpression newDartExpr) {
    if (newDartExpr is WidthExpression && isWidth && newDartExpr.isWidth) {
      return newDartExpr;
    }

    return null;
  }

  @override
  WidthExpression clone() => WidthExpression(span, width);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitWidthExpression(this);
}

class PaddingExpression extends BoxExpression {
  /// Padding expression ripped apart.
  PaddingExpression(SourceSpan? span,
      {num? top, num? right, num? bottom, num? left})
      : super(DartStyleExpression.paddingStyle, span,
            BoxEdge(left, top, right, bottom));

  PaddingExpression.boxEdge(SourceSpan? span, BoxEdge? box)
      : super(DartStyleExpression.paddingStyle, span, box);

  @override
  PaddingExpression? merged(DartStyleExpression newDartExpr) {
    if (newDartExpr is PaddingExpression &&
        isPadding &&
        newDartExpr.isPadding) {
      return PaddingExpression.merge(this, newDartExpr);
    }

    return null;
  }

  /// Merge the two PaddingExpression and return the result.
  factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) =>
      PaddingExpression._merge(x, y, y.span);

  PaddingExpression._merge(
      PaddingExpression x, PaddingExpression y, SourceSpan? span)
      : super(DartStyleExpression.paddingStyle, span,
            BoxEdge.merge(x.box, y.box));

  @override
  PaddingExpression clone() => PaddingExpression(span,
      top: box!.top, right: box!.right, bottom: box!.bottom, left: box!.left);
  @override
  dynamic visit(VisitorBase visitor) => visitor.visitPaddingExpression(this);
}
