// Copyright (c) 2014, 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.

library js_ast.template;

import 'nodes.dart';

class TemplateManager {
  Map<String, Template> expressionTemplates = {};
  Map<String, Template> statementTemplates = {};

  TemplateManager();

  Template? lookupExpressionTemplate(String source) {
    return expressionTemplates[source];
  }

  Template defineExpressionTemplate(String source, Node ast) {
    Template template =
        Template(source, ast, isExpression: true, forceCopy: false);
    expressionTemplates[source] = template;
    return template;
  }

  Template? lookupStatementTemplate(String source) {
    return statementTemplates[source];
  }

  Template defineStatementTemplate(String source, Node ast) {
    Template template =
        Template(source, ast, isExpression: false, forceCopy: false);
    statementTemplates[source] = template;
    return template;
  }
}

/// A Template is created with JavaScript AST containing placeholders (interface
/// InterpolatedNode).
///
/// The [instantiate] method creates an AST that looks like the original with
/// the placeholders replaced by the arguments to [instantiate].
class Template {
  final String? source;
  final bool isExpression;
  final bool forceCopy;
  final Node ast;
  final Instantiator instantiator;
  final int positionalArgumentCount;

  // Names of named holes, empty if there are no named holes.
  final List<String> holeNames;

  bool get isPositional => holeNames.isEmpty;

  Template._(this.source, this.ast,
      {required this.instantiator,
      required this.isExpression,
      required this.forceCopy,
      required this.positionalArgumentCount,
      this.holeNames = const []});

  factory Template(String? source, Node ast,
      {bool isExpression = true, bool forceCopy = false}) {
    assert(isExpression ? ast is Expression : ast is Statement);

    final generator = InstantiatorGeneratorVisitor(forceCopy);
    final instantiator = generator.compile(ast);
    final positionalArgumentCount = generator.analysis.count;
    final names = generator.analysis.holeNames;
    final holeNames = names.toList(growable: false);

    return Template._(source, ast,
        instantiator: instantiator,
        isExpression: isExpression,
        forceCopy: forceCopy,
        positionalArgumentCount: positionalArgumentCount,
        holeNames: holeNames);
  }

  factory Template.withExpressionResult(Expression ast) {
    assert(_checkNoPlaceholders(ast));
    return Template._(null, ast,
        instantiator: (arguments) => ast,
        isExpression: true,
        forceCopy: false,
        positionalArgumentCount: 0);
  }

  factory Template.withStatementResult(Statement ast) {
    assert(_checkNoPlaceholders(ast));
    return Template._(null, ast,
        instantiator: (arguments) => ast,
        isExpression: false,
        forceCopy: false,
        positionalArgumentCount: 0);
  }

  static bool _checkNoPlaceholders(Node ast) {
    InstantiatorGeneratorVisitor generator =
        InstantiatorGeneratorVisitor(false);
    generator.compile(ast);
    return generator.analysis.count == 0;
  }

  /// Instantiates the template with the given [arguments].
  ///
  /// This method fills in the holes with the given arguments. The [arguments]
  /// must be either a [List] or a [Map].
  Node instantiate(Object arguments) {
    if (arguments is List) {
      if (arguments.length != positionalArgumentCount) {
        throw 'Wrong number of template arguments, given ${arguments.length}, '
            'expected $positionalArgumentCount'
            ', source: "$source"';
      }
      return instantiator(arguments);
    }
    if (arguments is Map) {
      if (holeNames.length < arguments.length) {
        // This search is in O(n), but we only do it in case of an error, and
        // the number of holes should be quite limited.
        String unusedNames = arguments.keys
            .where((name) => !holeNames.contains(name))
            .join(', ');
        throw 'Template arguments has unused mappings: $unusedNames';
      }
      if (!holeNames.every((String name) => arguments.containsKey(name))) {
        String notFound =
            holeNames.where((name) => !arguments.containsKey(name)).join(', ');
        throw 'Template arguments is missing mappings for: $notFound';
      }
      return instantiator(arguments);
    }
    throw ArgumentError.value(arguments, 'arguments', 'Must be a List or Map');
  }
}

/// An Instantiator is a Function that generates a JS AST tree or List of
/// trees.
///
/// [arguments] is a List for positional templates, or Map for named templates.
typedef Instantiator = /*Node|Iterable<Node>*/ Function(dynamic arguments);

/// InstantiatorGeneratorVisitor compiles a template.  This class compiles a
/// tree containing [InterpolatedNode]s into a function that will create a copy
/// of the tree with the interpolated nodes substituted with provided values.
class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
  final bool forceCopy;

  InterpolatedNodeAnalysis analysis = InterpolatedNodeAnalysis();

  /// The entire tree is cloned if [forceCopy] is true.
  InstantiatorGeneratorVisitor(this.forceCopy);

  Instantiator compile(Node node) {
    analysis.visit(node);
    return visit(node);
  }

  static Never error(String message) {
    throw message;
  }

  static Instantiator same(Node node) => (arguments) => node;
  static Null makeNull(arguments) => null;

  Instantiator visit(Node node) {
    if (forceCopy || analysis.containsInterpolatedNodes(node)) {
      return node.accept(this);
    }
    return same(node);
  }

  Instantiator visitNullable(Node? node) {
    if (node == null) return makeNull;
    return visit(node);
  }

  Instantiator visitSplayable(Node node) {
    // TODO(sra): Process immediate [InterpolatedNode]s, permitting splaying.
    return visit(node);
  }

  Instantiator visitNode(Node node) {
    throw 'Unimplemented InstantiatorGeneratorVisitor for $node';
  }

  static RegExp identifierRE = RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$');

  static Expression convertStringToVariableUse(String value) {
    assert(identifierRE.hasMatch(value));
    return VariableUse(value);
  }

  static Expression convertStringToVariableDeclaration(String value) {
    assert(identifierRE.hasMatch(value));
    return VariableDeclaration(value);
  }

  @override
  Instantiator visitInterpolatedExpression(InterpolatedExpression node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Expression) return value;
      if (value is String) return convertStringToVariableUse(value);
      throw error(
          'Interpolated value #$nameOrPosition is not an Expression: $value');
    };
  }

  @override
  Instantiator visitInterpolatedDeclaration(InterpolatedDeclaration node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Declaration) return value;
      if (value is String) return convertStringToVariableDeclaration(value);
      throw error(
          'Interpolated value #$nameOrPosition is not a declaration: $value');
    };
  }

  Instantiator visitSplayableExpression(Node node) {
    if (node is InterpolatedExpression) {
      var nameOrPosition = node.nameOrPosition;
      return (arguments) {
        var value = arguments[nameOrPosition];
        Expression toExpression(item) {
          if (item is Expression) return item;
          if (item is String) return convertStringToVariableUse(item);
          throw error('Interpolated value #$nameOrPosition is not '
              'an Expression or List of Expressions: $value');
        }

        if (value is Iterable) return value.map(toExpression);
        return toExpression(value);
      };
    }
    return visit(node);
  }

  @override
  Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Literal || value is DeferredExpression) return value;
      error('Interpolated value #$nameOrPosition is not a Literal: $value');
    };
  }

  @override
  Instantiator visitInterpolatedParameter(InterpolatedParameter node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];

      Parameter toParameter(item) {
        if (item is Parameter) return item;
        if (item is String) return Parameter(item);
        throw error('Interpolated value #$nameOrPosition is not a Parameter or'
            ' List of Parameters: $value');
      }

      if (value is Iterable) return value.map(toParameter);
      return toParameter(value);
    };
  }

  @override
  Instantiator visitInterpolatedSelector(InterpolatedSelector node) {
    // A selector is an expression, as in `a[selector]`.
    // A String argument converted into a LiteralString, so `a.#` with argument
    // 'foo' generates `a["foo"]` which prints as `a.foo`.
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Expression) return value;
      if (value is String) return LiteralString(value);
      throw error(
          'Interpolated value #$nameOrPosition is not a selector: $value');
    };
  }

  @override
  Instantiator visitInterpolatedStatement(InterpolatedStatement node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Node) return value.toStatement();
      throw error(
          'Interpolated value #$nameOrPosition is not a Statement: $value');
    };
  }

  Instantiator visitSplayableStatement(Node node) {
    if (node is InterpolatedStatement) {
      var nameOrPosition = node.nameOrPosition;
      return (arguments) {
        var value = arguments[nameOrPosition];
        Statement toStatement(item) {
          if (item is Statement) return item;
          if (item is Expression) return item.toStatement();
          throw error('Interpolated value #$nameOrPosition is not '
              'a Statement or List of Statements: $value');
        }

        if (value is Iterable) return value.map(toStatement);
        return toStatement(value);
      };
    }
    return visit(node);
  }

  @override
  Instantiator visitProgram(Program node) {
    List<Instantiator> instantiators =
        node.body.map(visitSplayableStatement).toList();
    return (arguments) => Program(splayStatements(instantiators, arguments));
  }

  List<Statement> splayStatements(List<Instantiator> instantiators, arguments) {
    var statements = <Statement>[];
    for (var instantiator in instantiators) {
      final node = instantiator(arguments);
      if (node is EmptyStatement) continue;
      if (node is Iterable) {
        statements.addAll(node as Iterable<Statement>);
      } else if (node is Block /*&& !node.isScope*/) {
        statements.addAll(node.statements);
      } else if (node is Statement) {
        statements.add(node);
      } else {
        error('Not splayable as statement: $node');
      }
    }
    return statements;
  }

  @override
  Instantiator visitBlock(Block node) {
    List<Instantiator> instantiators =
        node.statements.map(visitSplayableStatement).toList();
    return (arguments) => Block(splayStatements(instantiators, arguments));
  }

  @override
  Instantiator visitExpressionStatement(ExpressionStatement node) {
    Instantiator buildExpression = visit(node.expression);
    return (arguments) => buildExpression(arguments).toStatement();
  }

  @override
  Instantiator visitEmptyStatement(EmptyStatement node) =>
      (arguments) => EmptyStatement();

  @override
  Instantiator visitIf(If node) {
    final condition = node.condition;
    if (condition is InterpolatedExpression) {
      return visitIfConditionalCompilation(node, condition);
    } else {
      return visitIfNormal(node);
    }
  }

  Instantiator visitIfConditionalCompilation(
      If node, InterpolatedExpression condition) {
    final nameOrPosition = condition.nameOrPosition;
    Instantiator makeThen = visit(node.then);
    Instantiator makeOtherwise = visit(node.otherwise);
    return (arguments) {
      // Allow booleans to be used for conditional compilation.
      var value = arguments[nameOrPosition];
      if (value is bool) {
        return value ? makeThen(arguments) : makeOtherwise(arguments);
      }
      Expression newCondition;
      if (value is Expression) {
        newCondition = value;
      } else if (value is String) {
        newCondition = convertStringToVariableUse(value);
      } else {
        error('Interpolated value #$nameOrPosition '
            'is not an Expression: $value');
      }
      return If(newCondition, makeThen(arguments), makeOtherwise(arguments));
    };
  }

  Instantiator visitIfNormal(If node) {
    Instantiator makeCondition = visit(node.condition);
    Instantiator makeThen = visit(node.then);
    Instantiator makeOtherwise = visit(node.otherwise);
    return (arguments) => If(makeCondition(arguments), makeThen(arguments),
        makeOtherwise(arguments));
  }

  @override
  Instantiator visitFor(For node) {
    Instantiator makeInit = visitNullable(node.init);
    Instantiator makeCondition = visitNullable(node.condition);
    Instantiator makeUpdate = visitNullable(node.update);
    Instantiator makeBody = visit(node.body);
    return (arguments) => For(makeInit(arguments), makeCondition(arguments),
        makeUpdate(arguments), makeBody(arguments));
  }

  @override
  Instantiator visitForIn(ForIn node) {
    Instantiator makeLeftHandSide = visit(node.leftHandSide);
    Instantiator makeObject = visit(node.object);
    Instantiator makeBody = visit(node.body);
    return (arguments) => ForIn(makeLeftHandSide(arguments),
        makeObject(arguments), makeBody(arguments));
  }

  Never TODO(String name) {
    throw UnimplementedError('$this.$name');
  }

  @override
  Instantiator visitWhile(While node) {
    Instantiator makeCondition = visit(node.condition);
    Instantiator makeBody = visit(node.body);
    return (arguments) => While(makeCondition(arguments), makeBody(arguments));
  }

  @override
  Instantiator visitDo(Do node) {
    Instantiator makeBody = visit(node.body);
    Instantiator makeCondition = visit(node.condition);
    return (arguments) => Do(makeBody(arguments), makeCondition(arguments));
  }

  @override
  Instantiator visitContinue(Continue node) =>
      (arguments) => Continue(node.targetLabel);

  @override
  Instantiator visitBreak(Break node) => (arguments) => Break(node.targetLabel);

  @override
  Instantiator visitReturn(Return node) {
    Instantiator makeExpression = visitNullable(node.value);
    return (arguments) => Return(makeExpression(arguments));
  }

  @override
  Instantiator visitDartYield(DartYield node) {
    Instantiator makeExpression = visit(node.expression);
    return (arguments) => DartYield(makeExpression(arguments), node.hasStar);
  }

  @override
  Instantiator visitThrow(Throw node) {
    Instantiator makeExpression = visit(node.expression);
    return (arguments) => Throw(makeExpression(arguments));
  }

  @override
  Instantiator visitTry(Try node) {
    Instantiator makeBody = visit(node.body);
    Instantiator makeCatch = visitNullable(node.catchPart);
    Instantiator makeFinally = visitNullable(node.finallyPart);
    return (arguments) =>
        Try(makeBody(arguments), makeCatch(arguments), makeFinally(arguments));
  }

  @override
  Instantiator visitCatch(Catch node) {
    Instantiator makeDeclaration = visit(node.declaration);
    Instantiator makeBody = visit(node.body);
    return (arguments) =>
        Catch(makeDeclaration(arguments), makeBody(arguments));
  }

  @override
  Instantiator visitSwitch(Switch node) {
    Instantiator makeKey = visit(node.key);
    Iterable<Instantiator> makeCases = node.cases.map(visit);
    return (arguments) {
      return Switch(
          makeKey(arguments),
          makeCases
              .map<SwitchClause>((Instantiator makeCase) => makeCase(arguments))
              .toList());
    };
  }

  @override
  Instantiator visitCase(Case node) {
    Instantiator makeExpression = visit(node.expression);
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return Case(makeExpression(arguments), makeBody(arguments));
    };
  }

  @override
  Instantiator visitDefault(Default node) {
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return Default(makeBody(arguments));
    };
  }

  @override
  Instantiator visitFunctionDeclaration(FunctionDeclaration node) {
    Instantiator makeName = visit(node.name);
    Instantiator makeFunction = visit(node.function);
    return (arguments) =>
        FunctionDeclaration(makeName(arguments), makeFunction(arguments));
  }

  @override
  Instantiator visitLabeledStatement(LabeledStatement node) {
    Instantiator makeBody = visit(node.body);
    return (arguments) => LabeledStatement(node.label, makeBody(arguments));
  }

  @override
  Instantiator visitLiteralStatement(LiteralStatement node) =>
      TODO('visitLiteralStatement');
  @override
  Instantiator visitLiteralExpression(LiteralExpression node) =>
      TODO('visitLiteralExpression');

  @override
  Instantiator visitVariableDeclarationList(VariableDeclarationList node) {
    List<Instantiator> declarationMakers =
        node.declarations.map(visit).toList();
    return (arguments) {
      List<VariableInitialization> declarations = [];
      for (Instantiator instantiator in declarationMakers) {
        var result = instantiator(arguments);
        declarations.add(result);
      }
      return VariableDeclarationList(declarations);
    };
  }

  @override
  Instantiator visitAssignment(Assignment node) {
    Instantiator makeLeftHandSide = visit(node.leftHandSide);
    String? op = node.op;
    Instantiator makeValue = visit(node.value);
    return (arguments) {
      return Assignment.compound(
          makeLeftHandSide(arguments), op, makeValue(arguments));
    };
  }

  @override
  Instantiator visitVariableInitialization(VariableInitialization node) {
    Instantiator makeDeclaration = visit(node.declaration);
    Instantiator makeValue = visitNullable(node.value);
    return (arguments) => VariableInitialization(
        makeDeclaration(arguments), makeValue(arguments));
  }

  @override
  Instantiator visitConditional(Conditional cond) {
    Instantiator makeCondition = visit(cond.condition);
    Instantiator makeThen = visit(cond.then);
    Instantiator makeOtherwise = visit(cond.otherwise);
    return (arguments) => Conditional(makeCondition(arguments),
        makeThen(arguments), makeOtherwise(arguments));
  }

  @override
  Instantiator visitNew(New node) =>
      handleCallOrNew(node, (target, arguments) => New(target, arguments));

  @override
  Instantiator visitCall(Call node) =>
      handleCallOrNew(node, (target, arguments) => Call(target, arguments));

  Instantiator handleCallOrNew(Call node, Function(dynamic, dynamic) finish) {
    Instantiator makeTarget = visit(node.target);
    Iterable<Instantiator> argumentMakers =
        node.arguments.map(visitSplayableExpression).toList();

    // TODO(sra): Avoid copying call arguments if no interpolation or forced
    // copying.
    return (arguments) {
      Node target = makeTarget(arguments);
      List<Expression> callArguments = splay(argumentMakers, arguments);
      return finish(target, callArguments.toList(growable: false));
    };
  }

  @override
  Instantiator visitBinary(Binary node) {
    Instantiator makeLeft = visit(node.left);
    Instantiator makeRight = visit(node.right);
    String op = node.op;
    return (arguments) => Binary(op, makeLeft(arguments), makeRight(arguments));
  }

  @override
  Instantiator visitPrefix(Prefix node) {
    Instantiator makeOperand = visit(node.argument);
    String op = node.op;
    return (arguments) => Prefix(op, makeOperand(arguments));
  }

  @override
  Instantiator visitPostfix(Postfix node) {
    Instantiator makeOperand = visit(node.argument);
    String op = node.op;
    return (arguments) => Postfix(op, makeOperand(arguments));
  }

  @override
  Instantiator visitVariableUse(VariableUse node) =>
      (arguments) => VariableUse(node.name);

  @override
  Instantiator visitThis(This node) => (arguments) => This();

  @override
  Instantiator visitVariableDeclaration(VariableDeclaration node) =>
      (arguments) => VariableDeclaration(node.name);

  @override
  Instantiator visitParameter(Parameter node) =>
      (arguments) => Parameter(node.name);

  @override
  Instantiator visitAccess(PropertyAccess node) {
    Instantiator makeReceiver = visit(node.receiver);
    Instantiator makeSelector = visit(node.selector);
    return (arguments) =>
        PropertyAccess(makeReceiver(arguments), makeSelector(arguments));
  }

  @override
  Instantiator visitNamedFunction(NamedFunction node) {
    Instantiator makeDeclaration = visit(node.name);
    Instantiator makeFunction = visit(node.function);
    return (arguments) =>
        NamedFunction(makeDeclaration(arguments), makeFunction(arguments));
  }

  @override
  Instantiator visitFun(Fun node) {
    List<Instantiator> paramMakers = node.params.map(visitSplayable).toList();
    Instantiator makeBody = visit(node.body);
    // TODO(sra): Avoid copying params if no interpolation or forced copying.
    return (arguments) {
      List<Parameter> params = splayParameters(paramMakers, arguments);
      Block body = makeBody(arguments);
      return Fun(params, body);
    };
  }

  @override
  Instantiator visitArrowFunction(ArrowFunction node) {
    List<Instantiator> paramMakers = node.params.map(visitSplayable).toList();
    Instantiator makeBody = visit(node.body);
    // TODO(sra): Avoid copying params if no interpolation or forced copying.
    return (arguments) {
      List<Parameter> params = splayParameters(paramMakers, arguments);
      // Either a Block or Expression.
      Node body = makeBody(arguments);
      return ArrowFunction(params, body);
    };
  }

  List<Parameter> splayParameters(List<Instantiator> instantiators, arguments) {
    // TODO(sra): This will be different when parameters include destructuring
    // and default values.
    return splay<Parameter>(instantiators, arguments);
  }

  List<T> splay<T>(Iterable<Instantiator> instantiators, arguments) {
    List<T> results = [];
    for (Instantiator instantiator in instantiators) {
      var result = instantiator(arguments);
      if (result is Iterable) {
        for (final item in result) {
          results.add(item as T);
        }
      } else {
        results.add(result as T);
      }
    }
    return results;
  }

  @override
  Instantiator visitDeferredExpression(DeferredExpression node) => same(node);

  @override
  Instantiator visitDeferredStatement(DeferredStatement node) => same(node);

  @override
  Instantiator visitDeferredNumber(DeferredNumber node) => same(node);

  @override
  Instantiator visitDeferredString(DeferredString node) => (arguments) => node;

  @override
  Instantiator visitLiteralBool(LiteralBool node) =>
      (arguments) => LiteralBool(node.value);

  @override
  Instantiator visitLiteralString(LiteralString node) =>
      (arguments) => LiteralString(node.value);

  @override
  Instantiator visitLiteralNumber(LiteralNumber node) =>
      (arguments) => LiteralNumber(node.value);

  @override
  Instantiator visitLiteralNull(LiteralNull node) =>
      (arguments) => LiteralNull();

  @override
  Instantiator visitStringConcatenation(StringConcatenation node) {
    List<Instantiator> partMakers =
        node.parts.map(visit).toList(growable: false);
    return (arguments) {
      List<Literal> parts = [
        for (final instantiator in partMakers)
          instantiator(arguments) as Literal
      ];
      return StringConcatenation(parts);
    };
  }

  @override
  Instantiator visitName(Name node) => same(node);

  @override
  Instantiator visitParentheses(Parentheses node) {
    Instantiator makeEnclosed = visit(node.enclosed);
    return (arguments) {
      Expression enclosed = makeEnclosed(arguments);
      return Parentheses(enclosed);
    };
  }

  @override
  Instantiator visitArrayInitializer(ArrayInitializer node) {
    // TODO(sra): Implement splicing?
    List<Instantiator> elementMakers =
        node.elements.map(visit).toList(growable: false);
    return (arguments) {
      List<Expression> elements = elementMakers
          .map<Expression>(
              (Instantiator instantiator) => instantiator(arguments))
          .toList(growable: false);
      return ArrayInitializer(elements);
    };
  }

  @override
  Instantiator visitArrayHole(ArrayHole node) {
    return (arguments) => ArrayHole();
  }

  @override
  Instantiator visitObjectInitializer(ObjectInitializer node) {
    List<Instantiator> propertyMakers =
        node.properties.map(visitSplayable).toList();
    bool isOneLiner = node.isOneLiner;
    return (arguments) {
      List<Property> properties = splay(propertyMakers, arguments);
      return ObjectInitializer(properties, isOneLiner: isOneLiner);
    };
  }

  @override
  Instantiator visitProperty(Property node) {
    Instantiator makeName = visit(node.name);
    Instantiator makeValue = visit(node.value);
    return (arguments) {
      return Property(makeName(arguments), makeValue(arguments));
    };
  }

  @override
  Instantiator visitMethodDefinition(MethodDefinition node) {
    Instantiator makeName = visit(node.name);
    Instantiator makeFunction = visit(node.function);
    return (arguments) {
      return MethodDefinition(makeName(arguments), makeFunction(arguments));
    };
  }

  @override
  Instantiator visitRegExpLiteral(RegExpLiteral node) =>
      (arguments) => RegExpLiteral(node.pattern);

  @override
  Instantiator visitComment(Comment node) => TODO('visitComment');

  @override
  Instantiator visitAwait(Await node) {
    Instantiator makeExpression = visit(node.expression);
    return (arguments) {
      return Await(makeExpression(arguments));
    };
  }
}

/// InterpolatedNodeAnalysis determines which AST trees contain
/// [InterpolatedNode]s, and the names of the named interpolated nodes.
class InterpolatedNodeAnalysis extends BaseVisitorVoid {
  final Set<Node> containsInterpolatedNode = {};
  final Set<String> holeNames = {};
  int count = 0;

  InterpolatedNodeAnalysis();

  bool containsInterpolatedNodes(Node node) =>
      containsInterpolatedNode.contains(node);

  void visit(Node node) {
    node.accept(this);
  }

  @override
  void visitNode(Node node) {
    int before = count;
    node.visitChildren(this);
    if (count != before) containsInterpolatedNode.add(node);
  }

  @override
  void visitInterpolatedNode(InterpolatedNode node) {
    containsInterpolatedNode.add(node);
    if (node.isNamed) holeNames.add(node.nameOrPosition);
    ++count;
  }
}
