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

import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/changes_selector.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_fragment_parser.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/expression.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/modify_parameters.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/rename_parameter.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/variable_scope.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:meta/meta.dart';
import 'package:yaml/yaml.dart';

/// Information used to report errors when translating a node.
class ErrorContext {
  /// The name of the key used to identify the node that has an error associated
  /// with it.
  final String key;

  /// The node that should be used to compute the highlight region for the
  /// diagnostic.
  final YamlNode parentNode;

  /// Initialize a newly created error context.
  ErrorContext({@required this.key, @required this.parentNode});
}

/// A parser used to read a transform set from a file.
class TransformSetParser {
  static const String _argumentValueKey = 'argumentValue';
  static const String _bulkApplyKey = 'bulkApply';
  static const String _changesKey = 'changes';
  static const String _classKey = 'class';
  static const String _constantKey = 'constant';
  static const String _constructorKey = 'constructor';
  static const String _dateKey = 'date';
  static const String _elementKey = 'element';
  static const String _enumKey = 'enum';
  static const String _expressionKey = 'expression';
  static const String _extendsKey = 'extends';
  static const String _extensionKey = 'extension';
  static const String _fieldKey = 'field';
  static const String _functionKey = 'function';
  static const String _getterKey = 'getter';
  static const String _ifKey = 'if';
  static const String _inClassKey = 'inClass';
  static const String _inEnumKey = 'inEnum';
  static const String _inExtensionKey = 'inExtension';
  static const String _indexKey = 'index';
  static const String _inMixinKey = 'inMixin';
  static const String _kindKey = 'kind';
  static const String _methodKey = 'method';
  static const String _mixinKey = 'mixin';
  static const String _nameKey = 'name';
  static const String _newNameKey = 'newName';
  static const String _oldNameKey = 'oldName';
  static const String _oneOfKey = 'oneOf';
  static const String _requiredIfKey = 'requiredIf';
  static const String _setterKey = 'setter';
  static const String _styleKey = 'style';
  static const String _titleKey = 'title';
  static const String _transformsKey = 'transforms';
  static const String _typedefKey = 'typedef';
  static const String _urisKey = 'uris';
  static const String _valueKey = 'value';
  static const String _variableKey = 'variable';
  static const String _variablesKey = 'variables';
  static const String _versionKey = 'version';

  /// A table mapping top-level keys for member elements to the list of keys for
  /// the possible containers of that element.
  static const Map<String, List<String>> _containerKeyMap = {
    _constructorKey: [_inClassKey],
    _constantKey: [_inEnumKey],
    _fieldKey: [_inClassKey, _inExtensionKey, _inMixinKey],
    _getterKey: [_inClassKey, _inExtensionKey, _inMixinKey],
    _methodKey: [_inClassKey, _inExtensionKey, _inMixinKey],
    _setterKey: [_inClassKey, _inExtensionKey, _inMixinKey],
  };

  static const String _addParameterKind = 'addParameter';
  static const String _addTypeParameterKind = 'addTypeParameter';
  static const String _fragmentKind = 'fragment';
  static const String _importKind = 'import';
  static const String _removeParameterKind = 'removeParameter';
  static const String _renameKind = 'rename';
  static const String _renameParameterKind = 'renameParameter';

  /// The valid values for the [_styleKey] in an [_addParameterKind] change.
  static const List<String> validStyles = [
    'optional_named',
    'optional_positional',
    'required_named',
    'required_positional'
  ];

  static const String _openComponent = '{%';
  static const String _closeComponent = '%}';

  /// The lowest file version supported by this parser.
  static const int oldestVersion = 1;

  /// The highest file version supported by this parser. The version needs to be
  /// incremented any time the parser is updated to disallow input that would
  /// have been valid in the most recently published version of server. This
  /// includes removing support for keys and adding a new required key.
  static const int currentVersion = 1;

  /// The error reporter to which diagnostics will be reported.
  final ErrorReporter errorReporter;

  /// The name of the package from which the data file being translated was
  /// found.
  final String packageName;

  /// The variable scope defined for the current transform.
  VariableScope transformVariableScope = VariableScope.empty;

  /// The parameter modifications associated with the current transform, or
  /// `null` if the current transform does not yet have any such modifications.
  List<ParameterModification> _parameterModifications;

  /// Initialize a newly created parser to report diagnostics to the
  /// [errorReporter].
  TransformSetParser(this.errorReporter, this.packageName);

  /// Return the result of parsing the file [content] into a transform set, or
  /// `null` if the content does not represent a valid transform set.
  TransformSet parse(String content) {
    assert(content != null);
    var map = _parseYaml(content);
    if (map == null) {
      // The error has already been reported.
      return null;
    }
    return _translateTransformSet(map);
  }

  /// Convert the given [template] into a list of components. Variable
  /// references in the template are looked up in the map of [generators].
  List<TemplateComponent> _extractTemplateComponents(
      String template, VariableScope variableScope, int templateOffset) {
    var components = <TemplateComponent>[];
    var textStart = 0;
    var variableStart = template.indexOf(_openComponent);
    while (variableStart >= 0) {
      if (textStart < variableStart) {
        // TODO(brianwilkerson) Check for an end brace without a start brace.
        components
            .add(TemplateText(template.substring(textStart, variableStart)));
      }
      var endIndex = template.indexOf(_closeComponent, variableStart + 2);
      if (endIndex < 0) {
        errorReporter.reportErrorForOffset(
            TransformSetErrorCode.missingTemplateEnd,
            templateOffset + variableStart,
            2);
        // Ignore the invalid component, treating it as if it extended to the
        // end of the template.
        return components;
      } else {
        var name = template.substring(variableStart + 2, endIndex).trim();
        var generator = variableScope.lookup(name);
        if (generator == null) {
          errorReporter.reportErrorForOffset(
              TransformSetErrorCode.undefinedVariable,
              templateOffset + template.indexOf(name, variableStart),
              name.length,
              [name]);
          // Ignore the invalid component.
        } else {
          components.add(TemplateVariable(generator));
        }
      }
      textStart = endIndex + 2;
      variableStart = template.indexOf(_openComponent, textStart);
    }
    if (textStart < template.length) {
      // TODO(brianwilkerson) Check for an end brace without a start brace.
      components.add(TemplateText(template.substring(textStart)));
    }
    // TODO(brianwilkerson) If there are no other errors, then report
    //  unreferenced variables.
    return components;
  }

  /// Return a textual description of the type of value represented by the
  /// [node].
  String _nodeType(YamlNode node) {
    if (node is YamlScalar) {
      return node.value.runtimeType.toString();
    } else if (node is YamlList) {
      return 'List';
    } else if (node is YamlMap) {
      return 'Map';
    }
    // We shouldn't get here.
    return node.runtimeType.toString();
  }

  /// Return the offset of the first character in the [string], exclusive of any
  /// surrounding quotes.
  int _offsetOfString(YamlScalar string) {
    if (string.style == ScalarStyle.PLAIN) {
      return string.span.start.offset;
    }
    return string.span.start.offset + 1;
  }

  /// Return the result of parsing the file [content] into a YAML node.
  YamlNode _parseYaml(String content) {
    try {
      return loadYamlNode(content);
    } on YamlException catch (e) {
      var span = e.span;
      errorReporter.reportErrorForOffset(TransformSetErrorCode.yamlSyntaxError,
          span.start.offset, span.length, [e.message]);
    }
    return null;
  }

  /// Report a diagnostic with the given [code] associated with the given
  /// [node]. A list of [arguments] should be provided if the diagnostic message
  /// has parameters.
  void _reportError(TransformSetErrorCode code, YamlNode node,
      [List<String> arguments]) {
    var span = node.span;
    errorReporter.reportErrorForOffset(
        code, span.start.offset, span.length, arguments);
  }

  /// Report that the value represented by the [node] does not have the
  /// [expectedType], using the [context] to get the key to use in the message.
  Null _reportInvalidValue(
      YamlNode node, ErrorContext context, String expectedType) {
    _reportError(TransformSetErrorCode.invalidValue, node,
        [context.key, expectedType, _nodeType(node)]);
    return null;
  }

  /// Report that the value represented by the [node] does not have the
  /// [expectedType], using the [context] to get the key to use in the message.
  Null _reportInvalidValueOneOf(
      YamlNode node, ErrorContext context, List<String> allowedValues) {
    _reportError(TransformSetErrorCode.invalidValueOneOf, node,
        [context.key, allowedValues.join(', ')]);
    return null;
  }

  /// Report that a required key is missing, using the [context] to locate the
  /// node associated with the diagnostic and the key to use in the message.
  Null _reportMissingKey(ErrorContext context) {
    _reportError(
        TransformSetErrorCode.missingKey, context.parentNode, [context.key]);
    return null;
  }

  /// Report any keys in the [map] whose values are not in [validKeys].
  void _reportUnsupportedKeys(YamlMap map, Set<String> validKeys) {
    for (var keyNode in map.nodes.keys) {
      var key = _translateKey(keyNode);
      if (key != null && !validKeys.contains(key)) {
        _reportError(TransformSetErrorCode.unsupportedKey, keyNode, [key]);
      }
    }
  }

  /// Given a [map] and a set of [validKeys], ensure that exactly one of those
  /// keys is in the map and return it. If more than one of the keys is in the
  /// map, report a diagnostic for each extra key. If [required] is `true` and
  /// none of the keys is in the map, report a diagnostic at the [errorNode].
  String _singleKey(YamlMap map, List<String> validKeys, YamlNode errorNode,
      {bool required = true}) {
    assert(validKeys != null);
    var foundKeys = <String>[];
    var keyToNodeMap = <String, YamlNode>{};
    for (var keyNode in map.nodes.keys) {
      if (keyNode is YamlScalar && keyNode.value is String) {
        var key = keyNode.value as String;
        if (key != null && validKeys.contains(key)) {
          foundKeys.add(key);
          keyToNodeMap[key] = keyNode;
        }
      }
    }
    if (foundKeys.isEmpty) {
      if (required) {
        var validKeysList = validKeys.map((key) => "'$key'").join(', ');
        _reportError(TransformSetErrorCode.missingOneOfMultipleKeys, errorNode,
            [validKeysList]);
      }
      return null;
    }
    var firstKey = foundKeys[0];
    for (var i = 1; i < foundKeys.length; i++) {
      var foundKey = foundKeys[i];
      var invalidNode = keyToNodeMap[foundKey];
      _reportError(TransformSetErrorCode.conflictingKey, invalidNode,
          [foundKey, firstKey]);
    }
    return firstKey;
  }

  /// Translate the [node] into a add-parameter modification.
  void _translateAddParameterChange(YamlMap node) {
    _reportUnsupportedKeys(node,
        const {_argumentValueKey, _indexKey, _kindKey, _nameKey, _styleKey});
    var index = _translateInteger(node.valueAt(_indexKey),
        ErrorContext(key: _indexKey, parentNode: node));
    if (index == null) {
      // The error has already been reported.
      return;
    }
    var name = _translateString(
        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
    if (name == null) {
      // The error has already been reported.
      return;
    }
    var styleNode = node.valueAt(_styleKey);
    var style = _translateString(
        styleNode, ErrorContext(key: _styleKey, parentNode: node));
    if (style == null) {
      // The error has already been reported.
      return;
    }
    if (!validStyles.contains(style)) {
      var validStylesList = validStyles.map((style) => "'$style'").join(', ');
      _reportError(TransformSetErrorCode.invalidParameterStyle, styleNode,
          [validStylesList]);
      return;
    }
    var isRequired = style.startsWith('required_');
    var isPositional = style.endsWith('_positional');
    var argumentValueNode = node.valueAt(_argumentValueKey);
    var argumentValue = _translateCodeTemplate(argumentValueNode,
        ErrorContext(key: _argumentValueKey, parentNode: node),
        canBeConditionallyRequired: true);
    // TODO(brianwilkerson) We really ought to require an argument value for
    //  optional positional parameters too for the case where the added
    //  parameter is being added before the end of the list and call sites might
    //  already be providing a value for subsequent parameters. Unfortunately we
    //  can't know at this point whether there are subsequent parameters in
    //  order to require it only when it's potentially necessary.
    if (isRequired && argumentValue == null) {
      // TODO(brianwilkerson) Report that required parameters must have an
      //  argument value.
      return;
    } else if (argumentValue != null &&
        argumentValue.requiredIfCondition != null) {
      if (style != 'optional_named') {
        var valueNode = argumentValueNode as YamlMap;
        _reportError(TransformSetErrorCode.invalidRequiredIf,
            valueNode.keyAtValue(valueNode.valueAt(_requiredIfKey)));
        return;
      } else if (argumentValue == null) {
        // TODO(brianwilkerson) Report that conditionally required parameters must
        //  have an argument value.
        return;
      }
    }
    _parameterModifications ??= [];
    _parameterModifications.add(
        AddParameter(index, name, isRequired, isPositional, argumentValue));
  }

  /// Translate the [node] into an add-type-parameter change. Return the
  /// resulting change, or `null` if the [node] does not represent a valid
  /// add-type-parameter change.
  AddTypeParameter _translateAddTypeParameterChange(YamlMap node) {
    _reportUnsupportedKeys(node,
        const {_extendsKey, _indexKey, _kindKey, _nameKey, _argumentValueKey});
    var index = _translateInteger(node.valueAt(_indexKey),
        ErrorContext(key: _indexKey, parentNode: node));
    var name = _translateString(
        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
    var extendedType = _translateCodeTemplate(node.valueAt(_extendsKey),
        ErrorContext(key: _extendsKey, parentNode: node),
        required: false);
    var argumentValue = _translateCodeTemplate(node.valueAt(_argumentValueKey),
        ErrorContext(key: _argumentValueKey, parentNode: node));
    if (index == null || name == null || argumentValue == null) {
      // The error has already been reported.
      return null;
    }
    // In order to support adding multiple type parameters we might need to
    // introduce a `TypeParameterModification` change, similar to
    // `ParameterModification`. That becomes more likely if we add support for
    // removing type parameters.
    return AddTypeParameter(
        index: index,
        name: name,
        extendedType: extendedType,
        argumentValue: argumentValue);
  }

  /// Translate the [node] into a bool. Return the resulting bool, or `null`
  /// if the [node] doesn't represent a valid bool. If the [node] isn't valid,
  /// use the [context] to report the error. If the [node] doesn't exist and
  /// [required] is `true`, then report an error.
  bool _translateBool(YamlNode node, ErrorContext context,
      {bool required = true}) {
    if (node is YamlScalar) {
      var value = node.value;
      if (value is bool) {
        return value;
      }
      return _reportInvalidValue(node, context, 'boolean');
    } else if (node == null) {
      if (required) {
        return _reportMissingKey(context);
      }
      return null;
    } else {
      return _reportInvalidValue(node, context, 'boolean');
    }
  }

  /// Translate the [node] into a change. Return the resulting change, or `null`
  /// if the [node] does not represent a valid change. If the [node] is not
  /// valid, use the [context] to report the error.
  Change _translateChange(YamlNode node, ErrorContext context) {
    assert(node != null);
    if (node is YamlMap) {
      var kindNode = node.valueAt(_kindKey);
      var kindContext = ErrorContext(key: _kindKey, parentNode: node);
      var kind = _translateString(kindNode, kindContext);
      if (kind == null) {
        return null;
      } else if (kind == _addParameterKind) {
        _translateAddParameterChange(node);
        return null;
      } else if (kind == _addTypeParameterKind) {
        return _translateAddTypeParameterChange(node);
      } else if (kind == _removeParameterKind) {
        _translateRemoveParameterChange(node);
        return null;
      } else if (kind == _renameKind) {
        return _translateRenameChange(node);
      } else if (kind == _renameParameterKind) {
        return _translateRenameParameterChange(node);
      }
      return _reportInvalidValueOneOf(kindNode, kindContext, [
        _addParameterKind,
        _addTypeParameterKind,
        _removeParameterKind,
        _renameKind,
        _renameParameterKind,
      ]);
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }

  /// Translate the [node] into a value generator. Return the resulting
  /// generator, or `null` if the [node] does not represent a valid value
  /// extractor.
  ValueGenerator _translateCodeFragment(YamlMap node) {
    _reportUnsupportedKeys(node, const {_kindKey, _valueKey});
    var valueNode = node.valueAt(_valueKey);
    var value = _translateString(
        valueNode, ErrorContext(key: _valueKey, parentNode: node));
    if (value == null) {
      // The error has already been reported.
      return null;
    }
    var accessors = CodeFragmentParser(errorReporter)
        .parseAccessors(value, _offsetOfString(valueNode));
    if (accessors == null) {
      // The error has already been reported.
      return null;
    }
    return CodeFragment(accessors);
  }

  /// Translate the [node] into a code template. Return the resulting template,
  /// or `null` if the [node] doesn't represent a valid code template. If the
  /// [node] isn't valid, use the [context] to report the error. If the [node]
  /// doesn't exist and [required] is `true`, then report an error.
  CodeTemplate _translateCodeTemplate(YamlNode node, ErrorContext context,
      {bool canBeConditionallyRequired = false, bool required = true}) {
    if (node is YamlMap) {
      if (canBeConditionallyRequired) {
        _reportUnsupportedKeys(
            node, const {_expressionKey, _requiredIfKey, _variablesKey});
      } else {
        _reportUnsupportedKeys(node, const {_expressionKey, _variablesKey});
      }
      var expressionNode = node.valueAt(_expressionKey);
      var template = _translateString(
          expressionNode, ErrorContext(key: _expressionKey, parentNode: node));
      var variableScope = _translateTemplateVariables(
          node.valueAt(_variablesKey),
          ErrorContext(key: _variablesKey, parentNode: node));
      Expression requiredIfCondition;
      if (canBeConditionallyRequired) {
        var requiredIfNode = node.valueAt(_requiredIfKey);
        var requiredIfText = _translateString(
            requiredIfNode, ErrorContext(key: _requiredIfKey, parentNode: node),
            required: false);
        if (requiredIfText != null) {
          requiredIfCondition = CodeFragmentParser(errorReporter,
                  scope: variableScope)
              .parseCondition(requiredIfText, _offsetOfString(requiredIfNode));
          if (requiredIfCondition == null) {
            // The error has already been reported.
            return null;
          }
        }
      }
      if (template == null) {
        // The error has already been reported.
        return null;
      }
      var templateOffset = _offsetOfString(expressionNode);
      var components =
          _extractTemplateComponents(template, variableScope, templateOffset);
      return CodeTemplate(
          CodeTemplateKind.expression, components, requiredIfCondition);
    } else if (node == null) {
      if (required) {
        _reportMissingKey(context);
      }
      return null;
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }

  void _translateConditionalChange(YamlNode node, ErrorContext context,
      Map<Expression, List<Change>> changeMap) {
    if (node is YamlMap) {
      _reportUnsupportedKeys(node, const {_ifKey, _changesKey});
      var expressionNode = node.valueAt(_ifKey);
      var expressionText = _translateString(
          expressionNode, ErrorContext(key: _ifKey, parentNode: node));
      var changes = _translateList(node.valueAt(_changesKey),
          ErrorContext(key: _changesKey, parentNode: node), _translateChange);
      if (_parameterModifications != null) {
        if (changes != null) {
          changes.add(ModifyParameters(modifications: _parameterModifications));
        }
        _parameterModifications = null;
      }
      if (expressionText != null && changes != null) {
        var expression = CodeFragmentParser(errorReporter,
                scope: transformVariableScope)
            .parseCondition(expressionText, _offsetOfString(expressionNode));
        if (expression != null) {
          changeMap[expression] = changes;
        }
      }
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }

  ChangesSelector _translateConditionalChanges(
      YamlNode node, ErrorContext context) {
    if (node is YamlList) {
      var changeMap = <Expression, List<Change>>{};
      for (var element in node.nodes) {
        _translateConditionalChange(element, context, changeMap);
      }
      return ConditionalChangesSelector(changeMap);
    } else {
      return _reportInvalidValue(node, context, 'List');
    }
  }

  /// Translate the [node] into a date. Return the resulting date, or `null`
  /// if the [node] does not represent a valid date. If the [node] is not
  /// valid, use the [context] to report the error.
  DateTime _translateDate(YamlNode node, ErrorContext context) {
    if (node is YamlScalar) {
      var value = node.value;
      if (value is String) {
        try {
          return DateTime.parse(value);
        } on FormatException {
          // Fall through to report the invalid value.
        }
      }
      return _reportInvalidValue(node, context, 'Date');
    } else if (node == null) {
      return _reportMissingKey(context);
    } else {
      return _reportInvalidValue(node, context, 'Date');
    }
  }

  /// Translate the [node] into an element descriptor. Return the resulting
  /// descriptor, or `null` if the [node] does not represent a valid element
  /// descriptor. If the [node] is not valid, use the [context] to report the
  /// error.
  ElementDescriptor _translateElement(YamlNode node, ErrorContext context) {
    if (node is YamlMap) {
      var urisNode = node.valueAt(_urisKey);
      var uris = _translateList(urisNode,
          ErrorContext(key: _urisKey, parentNode: node), _translateUri);
      var elementKey = _singleKey(
          node,
          const [
            _classKey,
            _constantKey,
            _constructorKey,
            _enumKey,
            _extensionKey,
            _fieldKey,
            _functionKey,
            _getterKey,
            _methodKey,
            _mixinKey,
            _setterKey,
            _typedefKey,
            _variableKey
          ],
          node);
      if (elementKey == null) {
        // The error has already been reported.
        return null;
      }
      var elementName = _translateString(node.valueAt(elementKey),
          ErrorContext(key: elementKey, parentNode: node));
      if (elementName == null) {
        // The error has already been reported.
        return null;
      }
      var components = [elementName];
      if (_containerKeyMap.containsKey(elementKey)) {
        var validContainerKeys = _containerKeyMap[elementKey];
        var containerKey =
            _singleKey(node, validContainerKeys, node, required: false);
        var containerName = _translateString(node.valueAt(containerKey),
            ErrorContext(key: containerKey, parentNode: node),
            required: false);
        if (containerName == null) {
          if ([_constructorKey, _constantKey, _methodKey, _fieldKey]
              .contains(elementKey)) {
            var validKeysList =
                validContainerKeys.map((key) => "'$key'").join(', ');
            _reportError(TransformSetErrorCode.missingOneOfMultipleKeys, node,
                [validKeysList]);
            return null;
          }
        } else {
          components.add(containerName);
        }
      }
      if (uris == null) {
        // The error has already been reported.
        return null;
      }
      if (uris.isEmpty) {
        if ((urisNode as YamlList).isEmpty) {
          _reportError(TransformSetErrorCode.missingUri, urisNode);
        }
        return null;
      }
      return ElementDescriptor(
          libraryUris: uris,
          kind: ElementKindUtilities.fromName(elementKey),
          components: components);
    } else if (node == null) {
      return _reportMissingKey(context);
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }

  /// Translate the [node] into a value generator. Return the resulting
  /// generator, or `null` if the [node] does not represent a valid value
  /// extractor.
  ValueGenerator _translateImportValue(YamlMap node) {
    _reportUnsupportedKeys(node, const {_kindKey, _nameKey, _urisKey});
    var urisNode = node.valueAt(_urisKey);
    var uris = _translateList(
        urisNode, ErrorContext(key: _urisKey, parentNode: node), _translateUri);
    var name = _translateString(
        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
    if (uris == null || name == null) {
      // The error has already been reported.
      return null;
    }
    if (uris.isEmpty) {
      if ((urisNode as YamlList).isEmpty) {
        _reportError(TransformSetErrorCode.missingUri, urisNode);
      }
      return null;
    }
    return ImportedName(uris, name);
  }

  /// Translate the [node] into an integer. Return the resulting integer, or
  /// `null` if the [node] does not represent a valid integer. If the [node] is
  /// not valid, use the [context] to report the error.
  int _translateInteger(YamlNode node, ErrorContext context) {
    if (node is YamlScalar) {
      var value = node.value;
      if (value is int) {
        return value;
      }
      return _reportInvalidValue(node, context, 'int');
    } else if (node == null) {
      return _reportMissingKey(context);
    } else {
      return _reportInvalidValue(node, context, 'int');
    }
  }

  /// Translate the given [node] as a key.
  String _translateKey(YamlNode node) {
    String type;
    if (node is YamlScalar) {
      if (node.value is String) {
        return node.value as String;
      }
      type = node.value.runtimeType.toString();
    } else if (node is YamlList) {
      type = 'List';
    } else if (node is YamlMap) {
      type = 'Map';
    } else {
      type = node.runtimeType.toString();
    }
    _reportError(TransformSetErrorCode.invalidKey, node, [type]);
    return null;
  }

  /// Translate the [node] into a list of objects using the [elementTranslator].
  /// Return the resulting list, or `null` if the [node] does not represent a
  /// valid list. If any of the elements of the list can't be translated, they
  /// will be omitted from the list, the [context] will be used to report the
  /// error, and the valid elements will be returned.
  List<R> _translateList<R>(YamlNode node, ErrorContext context,
      R Function(YamlNode, ErrorContext) elementTranslator) {
    if (node is YamlList) {
      var translatedList = <R>[];
      for (var element in node.nodes) {
        var result = elementTranslator(element, context);
        if (result != null) {
          translatedList.add(result);
        }
      }
      return translatedList;
    } else if (node == null) {
      return _reportMissingKey(context);
    } else {
      return _reportInvalidValue(node, context, 'List');
    }
  }

  /// Translate the [node] into a remove-parameter modification.
  void _translateRemoveParameterChange(YamlMap node) {
    _reportUnsupportedKeys(node, const {_indexKey, _kindKey, _nameKey});
    var parameterSpecKey = _singleKey(node, const [_nameKey, _indexKey], node);
    if (parameterSpecKey == null) {
      // The error has already been reported.
      return null;
    }
    ParameterReference reference;
    if (parameterSpecKey == _indexKey) {
      var index = _translateInteger(node.valueAt(_indexKey),
          ErrorContext(key: _indexKey, parentNode: node));
      if (parameterSpecKey == null) {
        // The error has already been reported.
        return null;
      }
      reference = PositionalParameterReference(index);
    } else {
      var name = _translateString(node.valueAt(_nameKey),
          ErrorContext(key: _nameKey, parentNode: node));
      if (name == null) {
        // The error has already been reported.
        return;
      }
      reference = NamedParameterReference(name);
    }
    _parameterModifications ??= [];
    _parameterModifications.add(RemoveParameter(reference));
  }

  /// Translate the [node] into a rename change. Return the resulting change, or
  /// `null` if the [node] does not represent a valid rename change.
  Rename _translateRenameChange(YamlMap node) {
    _reportUnsupportedKeys(node, const {_kindKey, _newNameKey});
    var newName = _translateString(node.valueAt(_newNameKey),
        ErrorContext(key: _newNameKey, parentNode: node));
    if (newName == null) {
      // The error has already been reported.
      return null;
    }
    return Rename(newName: newName);
  }

  /// Translate the [node] into a rename parameter change. Return the resulting
  /// change, or `null` if the [node] does not represent a valid rename change.
  RenameParameter _translateRenameParameterChange(YamlMap node) {
    _reportUnsupportedKeys(node, const {_kindKey, _newNameKey, _oldNameKey});
    var oldName = _translateString(node.valueAt(_oldNameKey),
        ErrorContext(key: _oldNameKey, parentNode: node));
    var newName = _translateString(node.valueAt(_newNameKey),
        ErrorContext(key: _newNameKey, parentNode: node));
    if (oldName == null || newName == null) {
      // The error has already been reported.
      return null;
    }
    return RenameParameter(newName: newName, oldName: oldName);
  }

  /// Translate the [node] into a string. Return the resulting string, or `null`
  /// if the [node] doesn't represent a valid string. If the [node] isn't valid,
  /// use the [context] to report the error. If the [node] doesn't exist and
  /// [required] is `true`, then report an error.
  String _translateString(YamlNode node, ErrorContext context,
      {bool required = true}) {
    if (node is YamlScalar) {
      var value = node.value;
      if (value is String) {
        return value;
      }
      return _reportInvalidValue(node, context, 'String');
    } else if (node == null) {
      if (required) {
        return _reportMissingKey(context);
      }
      return null;
    } else {
      return _reportInvalidValue(node, context, 'String');
    }
  }

  /// Translate the [node] into a variable scope. Return the resulting scope, or
  /// the enclosing scope if the [node] does not represent a valid variables
  /// map. If the [node] is not valid, use the [context] to report the error.
  VariableScope _translateTemplateVariables(
      YamlNode node, ErrorContext context) {
    if (node is YamlMap) {
      var generators = <String, ValueGenerator>{};
      for (var entry in node.nodes.entries) {
        var name = _translateKey(entry.key);
        if (name != null) {
          var value = _translateValueGenerator(
              entry.value, ErrorContext(key: name, parentNode: node));
          if (value != null) {
            generators[name] = value;
          }
        }
      }
      return VariableScope(transformVariableScope, generators);
    } else if (node == null) {
      return transformVariableScope;
    } else {
      _reportInvalidValue(node, context, 'Map');
      return transformVariableScope;
    }
  }

  /// Translate the [node] into a transform. Return the resulting transform, or
  /// `null` if the [node] does not represent a valid transform. If the [node]
  /// is not valid, use the [context] to report the error.
  Transform _translateTransform(YamlNode node, ErrorContext context) {
    assert(node != null);
    if (node is YamlMap) {
      _reportUnsupportedKeys(node, const {
        _bulkApplyKey,
        _changesKey,
        _dateKey,
        _elementKey,
        _oneOfKey,
        _titleKey,
        _variablesKey
      });
      var title = _translateString(node.valueAt(_titleKey),
          ErrorContext(key: _titleKey, parentNode: node));
      var date = _translateDate(node.valueAt(_dateKey),
          ErrorContext(key: _dateKey, parentNode: node));
      var bulkApply = _translateBool(node.valueAt(_bulkApplyKey),
              ErrorContext(key: _bulkApplyKey, parentNode: node),
              required: false) ??
          true;
      var element = _translateElement(node.valueAt(_elementKey),
          ErrorContext(key: _elementKey, parentNode: node));
      transformVariableScope = _translateTemplateVariables(
          node.valueAt(_variablesKey),
          ErrorContext(key: _variablesKey, parentNode: node));
      ChangesSelector selector;
      var key = _singleKey(
          node, const [_changesKey, _oneOfKey], context.parentNode,
          required: true);
      if (key == _oneOfKey) {
        selector = _translateConditionalChanges(node.valueAt(_oneOfKey),
            ErrorContext(key: _oneOfKey, parentNode: node));
      } else if (key == _changesKey) {
        var changes = _translateList(node.valueAt(_changesKey),
            ErrorContext(key: _changesKey, parentNode: node), _translateChange);
        if (changes == null) {
          // The error has already been reported.
          _parameterModifications = null;
          return null;
        }
        if (_parameterModifications != null) {
          changes.add(ModifyParameters(modifications: _parameterModifications));
          _parameterModifications = null;
        }
        selector = UnconditionalChangesSelector(changes);
      } else {
        // The error has already been reported.
        return null;
      }
      transformVariableScope = VariableScope.empty;
      if (title == null ||
          date == null ||
          element == null ||
          selector == null) {
        // The error has already been reported.
        return null;
      }
      return Transform(
          title: title,
          date: date,
          bulkApply: bulkApply,
          element: element,
          changesSelector: selector);
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }

  /// Translate the [node] into a transform set. Return the resulting transform
  /// set, or `null` if the [node] does not represent a valid transform set.
  TransformSet _translateTransformSet(YamlNode node) {
    assert(node != null);
    if (node is YamlMap) {
      _reportUnsupportedKeys(node, const {_transformsKey, _versionKey});
      var versionNode = node.valueAt(_versionKey);
      var version = _translateInteger(
          versionNode, ErrorContext(key: _versionKey, parentNode: node));
      if (version == null) {
        // The error has already been reported.
        return null;
      } else if (version < 1 || version > currentVersion) {
        _reportError(TransformSetErrorCode.unsupportedVersion, versionNode);
        return null;
      }
      // TODO(brianwilkerson) Version information is currently being ignored,
      //  but needs to be used to select a translator.
      var transforms = _translateList(
          node.valueAt(_transformsKey),
          ErrorContext(key: _transformsKey, parentNode: node),
          _translateTransform);
      if (transforms == null) {
        // The error has already been reported.
        return null;
      }
      transforms.sort((first, second) => first.date.compareTo(second.date));
      var set = TransformSet();
      for (var transform in transforms) {
        set.addTransform(transform);
      }
      return set;
    } else {
      // TODO(brianwilkerson) Consider having a different error code for the
      //  top-level node (instead of using 'file' as the "key").
      _reportError(TransformSetErrorCode.invalidValue, node,
          ['file', 'Map', _nodeType(node)]);
      return null;
    }
  }

  /// Translate the [node] into a URI. Return the resulting URI, or `null` if
  /// the [node] doesn't represent a valid URI. If the [node] isn't valid, use
  /// the [context] to report the error. If the [node] doesn't exist and
  /// [required] is `true`, then report an error.
  Uri _translateUri(YamlNode node, ErrorContext context,
      {bool required = true}) {
    if (node is YamlScalar) {
      var value = node.value;
      if (value is String) {
        if (!(value.startsWith('dart:') || value.startsWith('package:'))) {
          value = 'package:$packageName/$value';
        }
        return Uri.parse(value);
      }
      return _reportInvalidValue(node, context, 'URI');
    } else if (node == null) {
      if (required) {
        return _reportMissingKey(context);
      }
      return null;
    } else {
      return _reportInvalidValue(node, context, 'URI');
    }
  }

  /// Translate the [node] into a value extractor. Return the resulting
  /// extractor, or `null` if the [node] does not represent a valid value
  /// extractor. If the [node] is not valid, use the [context] to report the
  /// error.
  ValueGenerator _translateValueGenerator(YamlNode node, ErrorContext context) {
    if (node is YamlMap) {
      var kindNode = node.valueAt(_kindKey);
      var kindContext = ErrorContext(key: _kindKey, parentNode: node);
      var kind = _translateString(kindNode, kindContext);
      if (kind == null) {
        return null;
      } else if (kind == _fragmentKind) {
        return _translateCodeFragment(node);
      } else if (kind == _importKind) {
        return _translateImportValue(node);
      }
      return _reportInvalidValueOneOf(kindNode, kindContext, [
        _fragmentKind,
        _importKind,
      ]);
    } else if (node == null) {
      return _reportMissingKey(context);
    } else {
      return _reportInvalidValue(node, context, 'Map');
    }
  }
}
