Instruction generate(List linkParams, List<Instruction> ancestorInstructions, [ _aux = false ])

Given a normalized list with component names and params like: ['user', {id: 3 }] generates a url with a leading slash relative to the provided parentComponent.

If the optional param _aux is true, then we generate starting at an auxiliary route boundary.

Source

Instruction generate(
    List<dynamic> linkParams, List<Instruction> ancestorInstructions,
    [_aux = false]) {
  var params = splitAndFlattenLinkParams(linkParams);
  var prevInstruction;
  // The first segment should be either '.' (generate from parent) or '' (generate from root).
  // When we normalize above, we strip all the slashes, './' becomes '.' and '/' becomes ''.
  if (params.first == "") {
    params.removeAt(0);
    prevInstruction = ancestorInstructions.first;
    ancestorInstructions = [];
  } else {
    prevInstruction = ancestorInstructions.length > 0
        ? ancestorInstructions.removeLast()
        : null;
    if (params.first == ".") {
      params.removeAt(0);
    } else if (params.first == "..") {
      while (params.first == "..") {
        if (ancestorInstructions.length <= 0) {
          throw new BaseException(
              '''Link "$linkParams" has too many "../" segments.''');
        }
        prevInstruction = ancestorInstructions.removeLast();
        params = params.sublist(1);
      }
    } else {
      // we must only peak at the link param, and not consume it
      var routeName = params.first;
      var parentComponentType = this._rootComponent;
      var grandparentComponentType;
      if (ancestorInstructions.length > 1) {
        var parentComponentInstruction =
            ancestorInstructions[ancestorInstructions.length - 1];
        var grandComponentInstruction =
            ancestorInstructions[ancestorInstructions.length - 2];
        parentComponentType =
            parentComponentInstruction.component.componentType;
        grandparentComponentType =
            grandComponentInstruction.component.componentType;
      } else if (ancestorInstructions.length == 1) {
        parentComponentType = ancestorInstructions[0].component.componentType;
        grandparentComponentType = this._rootComponent;
      }
      // For a link with no leading `./`, `/`, or `../`, we look for a sibling and child.
 
      // If both exist, we throw. Otherwise, we prefer whichever exists.
      var childRouteExists = this.hasRoute(routeName, parentComponentType);
      var parentRouteExists = grandparentComponentType != null &&
          this.hasRoute(routeName, grandparentComponentType);
      if (parentRouteExists && childRouteExists) {
        var msg =
            '''Link "$linkParams" is ambiguous, use "./" or "../" to disambiguate.''';
        throw new BaseException(msg);
      }
      if (parentRouteExists) {
        prevInstruction = ancestorInstructions.removeLast();
      }
    }
  }
  if (params[params.length - 1] == "") {
    params.removeLast();
  }
  if (params.length > 0 && params[0] == "") {
    params.removeAt(0);
  }
  if (params.length < 1) {
    var msg = '''Link "$linkParams" must include a route name.''';
    throw new BaseException(msg);
  }
  var generatedInstruction = this._generate(
      params, ancestorInstructions, prevInstruction, _aux, linkParams);
  // we don't clone the first (root) element
  for (var i = ancestorInstructions.length - 1; i >= 0; i--) {
    var ancestorInstruction = ancestorInstructions[i];
    if (ancestorInstruction == null) {
      break;
    }
    generatedInstruction =
        ancestorInstruction.replaceChild(generatedInstruction);
  }
  return generatedInstruction;
}