<commit_before>// @flow
import {is} from 'immutable';

import type {ASTNode, ASTPath, Direction, HorizontalDirection, VerticalDirection} from '../types';
import findVerticalNeighborPath from './find-vertical-neighbor-path';
import findVerticalPathIn from './find-vertical-path-in';

function traverseVertically(direction: VerticalDirection, ast: ASTNode, path: ASTPath) {
  const neighborPath = findVerticalNeighborPath(direction, ast, path);
  if (
    (neighborPath.isEmpty() && direction === 'UP')
    || (!is(path, neighborPath) && neighborPath.get(-2) === 'elements')
  ) return neighborPath;
  return neighborPath.concat(findVerticalPathIn(direction, ast.getIn(neighborPath)));
}

function traverseHorizontally(direction: HorizontalDirection, ast: ASTNode, path: ASTPath) {
  const isLeft = direction === 'LEFT';

  const parentPath = path.slice(0, -1);
  const newKey = isLeft ? 'key' : 'value';
  if (ast.getIn(parentPath).get('type') === 'ObjectProperty' && newKey !== path.last()) {
    return parentPath.push(newKey);
  }

  const newPath = traverseVertically(isLeft ? 'UP' : 'DOWN', ast, path);
  return isLeft && ast.getIn(newPath.slice(0, -1)).get('type') === 'ObjectProperty'
    ? traverseHorizontally('RIGHT', ast, newPath)
    : newPath
}<commit_msg>fix looping when navigating past the end of an object/array<commit_after>// @flow
import {is} from 'immutable';

import type {ASTNode, ASTPath, Direction, HorizontalDirection, VerticalDirection} from '../types';
import findVerticalNeighborPath from './find-vertical-neighbor-path';
import findVerticalPathIn from './find-vertical-path-in';

function traverseVertically(direction: VerticalDirection, ast: ASTNode, path: ASTPath) {
  const isUp = direction === 'UP';
  if (!isUp && path.last() === 'end' && path.size === 2) return path;

  const neighborPath = findVerticalNeighborPath(direction, ast, path);
  if (
    (neighborPath.isEmpty() && isUp)
    || (!is(path, neighborPath) && neighborPath.get(-2) === 'elements')
  ) return neighborPath;
  return neighborPath.concat(findVerticalPathIn(direction, ast.getIn(neighborPath)));
}

function traverseHorizontally(direction: HorizontalDirection, ast: ASTNode, path: ASTPath) {
  const isLeft = direction === 'LEFT';

  const parentPath = path.slice(0, -1);
  const newKey = isLeft ? 'key' : 'value';
  if (ast.getIn(parentPath).get('type') === 'ObjectProperty' && newKey !== path.last()) {
    return parentPath.push(newKey);
  }

  const newPath = traverseVertically(isLeft ? 'UP' : 'DOWN', ast, path);
  return isLeft && ast.getIn(newPath.slice(0, -1)).get('type') === 'ObjectProperty'
    ? traverseHorizontally('RIGHT', ast, newPath)
    : newPath
}
{'fraction_non_alphanumeric': 0.15669409124906508, 'fraction_numerical': 0.004113687359760658, 'mean_word_length': 5.25, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4188551', 'n_tokens_mistral': 842, 'n_tokens_neox': 809, 'n_words': 202}