extendSelector method

List<Selector> extendSelector(
  1. List<MatchSelector> matches,
  2. List<Selector> selectorPath,
  3. Selector replacementSelector,
  4. {bool isVisible = false}
)

For a set of matches, replace each match with the replacement selector

Implementation

List<Selector> extendSelector(List<MatchSelector> matches,
    List<Selector> selectorPath, Selector replacementSelector,
    {bool isVisible = false}) {
  //
  var currentSelectorPathElementIndex = 0;
  var currentSelectorPathIndex = 0;
  final path = <Selector>[];

  for (var matchIndex = 0; matchIndex < matches.length; matchIndex++) {
    final match = matches[matchIndex];
    final selector = selectorPath[match.pathIndex];
    final firstElement = Element(
      match.initialCombinator,
      replacementSelector.elements[0].value,
      isVariable: replacementSelector.elements[0].isVariable,
      index: replacementSelector.elements[0].index,
      currentFileInfo: replacementSelector.elements[0].currentFileInfo,
    );

    if (match.pathIndex > currentSelectorPathIndex &&
        currentSelectorPathElementIndex > 0) {
      path.last.elements.addAll(selectorPath[currentSelectorPathIndex]
          .elements
          .sublist(currentSelectorPathElementIndex));
      currentSelectorPathElementIndex = 0;
      currentSelectorPathIndex++;
    }

    final newElements = selector.elements
        .sublist(currentSelectorPathElementIndex, match.index)
          ..add(firstElement)
          ..addAll(replacementSelector.elements.sublist(1));

    if (currentSelectorPathIndex == match.pathIndex && matchIndex > 0) {
      path.last.elements.addAll(newElements);
    } else {
      path
        ..addAll(
            selectorPath.sublist(currentSelectorPathIndex, match.pathIndex))
        ..add(Selector(newElements));
    }
    currentSelectorPathIndex = match.endPathIndex;
    currentSelectorPathElementIndex = match.endPathElementIndex;
    if (currentSelectorPathElementIndex >=
        selectorPath[currentSelectorPathIndex].elements.length) {
      currentSelectorPathElementIndex = 0;
      currentSelectorPathIndex++;
    }
  }

  if (currentSelectorPathIndex < selectorPath.length &&
      currentSelectorPathElementIndex > 0) {
    path.last.elements.addAll(selectorPath[currentSelectorPathIndex]
        .elements
        .sublist(currentSelectorPathElementIndex));
    currentSelectorPathIndex++;
  }

  path.addAll(
      selectorPath.sublist(currentSelectorPathIndex, selectorPath.length));

  return path.map((Selector currentValue) {
    // we can re-use elements here, because the visibility property
    // matters only for selectors
    final derived = currentValue.createDerived(currentValue.elements);
    if (isVisible ?? false) {
      derived.ensureVisibility();
    } else {
      derived.ensureInvisibility();
    }
    return derived;
  }).toList();

// 3.5.0.beta 20180625
//  extendSelector:function (matches, selectorPath, replacementSelector, isVisible) {
//
//      // for a set of matches, replace each match with the replacement selector
//
//      var currentSelectorPathIndex = 0,
//          currentSelectorPathElementIndex = 0,
//          path = [],
//          matchIndex,
//          selector,
//          firstElement,
//          match,
//          newElements;
//
//      for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
//          match = matches[matchIndex];
//          selector = selectorPath[match.pathIndex];
//          firstElement = new tree.Element(
//              match.initialCombinator,
//              replacementSelector.elements[0].value,
//              replacementSelector.elements[0].isVariable,
//              replacementSelector.elements[0].getIndex(),
//              replacementSelector.elements[0].fileInfo()
//          );
//
//          if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
//              path[path.length - 1].elements = path[path.length - 1]
//                  .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
//              currentSelectorPathElementIndex = 0;
//              currentSelectorPathIndex++;
//          }
//
//          newElements = selector.elements
//              .slice(currentSelectorPathElementIndex, match.index)
//              .concat([firstElement])
//              .concat(replacementSelector.elements.slice(1));
//
//          if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
//              path[path.length - 1].elements =
//                  path[path.length - 1].elements.concat(newElements);
//          } else {
//              path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
//
//              path.push(new tree.Selector(
//                  newElements
//              ));
//          }
//          currentSelectorPathIndex = match.endPathIndex;
//          currentSelectorPathElementIndex = match.endPathElementIndex;
//          if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
//              currentSelectorPathElementIndex = 0;
//              currentSelectorPathIndex++;
//          }
//      }
//
//      if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
//          path[path.length - 1].elements = path[path.length - 1]
//              .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
//          currentSelectorPathIndex++;
//      }
//
//      path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
//      path = path.map(function (currentValue) {
//          // we can re-use elements here, because the visibility property matters only for selectors
//          var derived = currentValue.createDerived(currentValue.elements);
//          if (isVisible) {
//              derived.ensureVisibility();
//          } else {
//              derived.ensureInvisibility();
//          }
//          return derived;
//      });
//      return path;
//  },
}