private static inNode()

in src/submodule-reference.ts [17:59]


  private static inNode(
    node: ts.Node,
    typeChecker: ts.TypeChecker,
    importDeclarations: ReadonlySet<ts.Symbol>,
    map = new Map<
      ts.PropertyAccessExpression | ts.LeftHandSideExpression | ts.Identifier | ts.PrivateIdentifier,
      SubmoduleReference
    >(),
  ): Map<
    ts.PropertyAccessExpression | ts.LeftHandSideExpression | ts.Identifier | ts.PrivateIdentifier,
    SubmoduleReference
  > {
    if (ts.isPropertyAccessExpression(node)) {
      const [head, ...tail] = propertyPath(node);
      const symbol = typeChecker.getSymbolAtLocation(head.name);
      if (symbol && importDeclarations.has(symbol)) {
        // This is a reference within an imported namespace, so we need to record that...
        const firstNonNamespace = tail.findIndex((item) => !isLikelyNamespace(item.name, typeChecker));
        if (firstNonNamespace < 0) {
          map.set(node.expression, new SubmoduleReference(symbol, node.expression, []));
        } else {
          const tailEnd = tail[firstNonNamespace].expression;
          const path = tail.slice(0, firstNonNamespace).map((item) => item.name);
          map.set(tailEnd, new SubmoduleReference(symbol, tailEnd, path));
        }
      }

      return map;
    }

    // Faster than ||-ing a bung of if statements to avoid traversing uninteresting nodes...
    switch (node.kind) {
      case ts.SyntaxKind.ImportDeclaration:
      case ts.SyntaxKind.ExportDeclaration:
        break;
      default:
        for (const child of node.getChildren()) {
          map = SubmoduleReference.inNode(child, typeChecker, importDeclarations, map);
        }
    }

    return map;
  }