tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scope-utils.js (3374B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /**
      8 * Check if the position is within this function location
      9 *
     10 * @param {object} functionLocation
     11 * @param {object} position
     12 * @returns {boolean}
     13 */
     14 function containsPosition(functionLocation, position) {
     15  // Start
     16  return (
     17    (functionLocation.start.line < position.line ||
     18      // If the start line is equal check the columns
     19      (functionLocation.start.line == position.line &&
     20        functionLocation.start.column <= position.column)) &&
     21    // End
     22    (functionLocation.end.line > position.line ||
     23      // If the end line is equal check the columns
     24      (functionLocation.end.line == position.line &&
     25        functionLocation.end.column >= position.column))
     26  );
     27 }
     28 
     29 function containsLocation(parentLocation, childLocation) {
     30  return (
     31    containsPosition(parentLocation, childLocation.start) &&
     32    containsPosition(parentLocation, childLocation.end)
     33  );
     34 }
     35 
     36 function getInnerLocations(locations, position) {
     37  // First, find the function which directly contains the specified position (line / column)
     38  let parentIndex;
     39  for (let i = locations.length - 1; i >= 0; i--) {
     40    if (containsPosition(locations[i], position)) {
     41      parentIndex = i;
     42      break;
     43    }
     44  }
     45 
     46  if (parentIndex == undefined) {
     47    return [];
     48  }
     49 
     50  const parentLoc = locations[parentIndex];
     51 
     52  // Then, from the nearest location, loop locations again and put locations into
     53  // the innerLocations array until we get to a location not enclosed by the nearest location.
     54  const innerLocations = [];
     55  for (let i = parentIndex + 1; i < locations.length; i++) {
     56    const loc = locations[i];
     57    if (!containsLocation(parentLoc, loc)) {
     58      break;
     59    }
     60    innerLocations.push(loc);
     61  }
     62 
     63  return innerLocations;
     64 }
     65 
     66 /**
     67 * Sort based on the start line
     68 *
     69 * @param {Array} locations
     70 * @returns
     71 */
     72 function sortByStart(locations) {
     73  return locations.sort((a, b) => {
     74    if (a.startLine < b.startLine) {
     75      return -1;
     76    } else if (a.startLine === b.startLine) {
     77      return b.endLine - a.endLine;
     78    }
     79    return 1;
     80  });
     81 }
     82 
     83 /**
     84 * Return a new locations array which excludes
     85 * items that are completely enclosed by another location in the input locations
     86 *
     87 * @param locations Notice! The locations MUST be sorted by `sortByStart`
     88 *                  so that we can do linear time complexity operation.
     89 */
     90 function removeOverlapLocations(locations) {
     91  if (!locations.length) {
     92    return [];
     93  }
     94  const firstParent = locations[0];
     95  return locations.reduce(deduplicateNode, [firstParent]);
     96 }
     97 
     98 function deduplicateNode(nodes, location) {
     99  const parent = nodes[nodes.length - 1];
    100  if (!containsLocation(parent, location)) {
    101    nodes.push(location);
    102  }
    103  return nodes;
    104 }
    105 
    106 function getOutOfScopeLines(outOfScopeLocations) {
    107  if (!outOfScopeLocations) {
    108    return new Set();
    109  }
    110 
    111  const uniqueLines = new Set();
    112  for (const location of outOfScopeLocations) {
    113    for (let i = location.startLine; i < location.endLine; i++) {
    114      uniqueLines.add(i);
    115    }
    116  }
    117 
    118  return uniqueLines;
    119 }
    120 
    121 module.exports = {
    122  containsPosition,
    123  containsLocation,
    124  getInnerLocations,
    125  removeOverlapLocations,
    126  getOutOfScopeLines,
    127  sortByStart,
    128 };