Skip to content

⬅️ Back to Table of Contents

📄 selectedRange

📊 Analysis Summary

Metric Count
🔧 Functions 6
📦 Imports 5

📚 Table of Contents

🛠️ File Location:

📂 packages/website/src/components/ast/selectedRange.ts

📦 Imports

Name Source
ParentNodeType ./types
filterProperties ./utils
isESNode ./utils
isRecord ./utils
isTSNode ./utils

Functions

findSelectionPath(node: object, cursorPosition: number): { node: object | null; path: string[] }

Parameters:

  • node object
  • cursorPosition number

Returns: { node: object | null; path: string[] }

Calls:

  • visited.has
  • visited.add
  • findInObject
  • nodePath.push

Internal Comments:

// infinite loop guard

Code
export function findSelectionPath(
  node: object,
  cursorPosition: number,
): { node: object | null; path: string[] } {
  const nodePath = ['ast'];
  const visited = new Set<unknown>();
  let currentNode: unknown = node;
  while (currentNode) {
    // infinite loop guard
    if (visited.has(currentNode)) {
      break;
    }
    visited.add(currentNode);

    const result = findInObject(currentNode, cursorPosition, visited);
    if (result) {
      currentNode = result.value;
      nodePath.push(...result.key);
    } else {
      return { node: currentNode, path: nodePath };
    }
  }
  return { node: null, path: nodePath };
}

isInRange(offset: number, value: object): boolean

Parameters:

  • offset number
  • value object

Returns: boolean

Calls:

  • getRangeFromNode
Code
function isInRange(offset: number, value: object): boolean {
  const range = getRangeFromNode(value);
  return !!range && offset > range[0] && offset <= range[1];
}

geNodeType(value: unknown): ParentNodeType

Parameters:

  • value unknown

Returns: ParentNodeType

Calls:

  • isRecord (from ./utils)
  • isESNode (from ./utils)
  • isTSNode (from ./utils)
Code
function geNodeType(value: unknown): ParentNodeType {
  if (isRecord(value)) {
    return isESNode(value) ? 'esNode' : isTSNode(value) ? 'tsNode' : undefined;
  }
  return undefined;
}

isIterable(key: string, value: unknown): boolean

Parameters:

  • key string
  • value unknown

Returns: boolean

Calls:

  • filterProperties (from ./utils)
  • geNodeType
Code
function isIterable(key: string, value: unknown): boolean {
  return filterProperties(key, value, geNodeType(value));
}

getRangeFromNode(value: object): [number, number] | null

Parameters:

  • value object

Returns: [number, number] | null

Calls:

  • isESNode (from ./utils)
  • isTSNode (from ./utils)
Code
function getRangeFromNode(value: object): [number, number] | null {
  if (isESNode(value)) {
    return value.range;
  }
  if (isTSNode(value)) {
    return [value.pos, value.end];
  }
  return null;
}

findInObject(iter: object, cursorPosition: number, visited: Set<unknown>): { key: string[]; value: unknown; } | null

Parameters:

  • iter object
  • cursorPosition number
  • visited Set<unknown>

Returns: { key: string[]; value: unknown; } | null

Calls:

  • Object.entries
  • visited.has
  • isIterable
  • visited.add
  • isRecord (from ./utils)
  • isInRange
  • Array.isArray
  • String

Internal Comments:

// we do not want to select parents in case if we do filter with esquery
// typescript array like elements have other iterable items

Code
function findInObject(
  iter: object,
  cursorPosition: number,
  visited: Set<unknown>,
): {
  key: string[];
  value: unknown;
} | null {
  const children = Object.entries(iter);
  for (const [name, child] of children) {
    // we do not want to select parents in case if we do filter with esquery
    if (visited.has(child) || name === 'parent' || !isIterable(name, child)) {
      continue;
    }
    visited.add(iter);

    if (isRecord(child)) {
      if (isInRange(cursorPosition, child)) {
        return {
          key: [name],
          value: child,
        };
      }
    } else if (Array.isArray(child)) {
      for (let index = 0; index < child.length; ++index) {
        const arrayChild: unknown = child[index];
        // typescript array like elements have other iterable items
        if (
          typeof index === 'number' &&
          isRecord(arrayChild) &&
          isInRange(cursorPosition, arrayChild)
        ) {
          return {
            key: [name, String(index)],
            value: arrayChild,
          };
        }
      }
    }
  }
  return null;
}

Generated by Syntax Scribe