syntax | test core dependencies | Cell 6 | Search

The getExports function uses the selectAst function to extract exports and function names from the Abstract Syntax Tree (AST) of a given code, and returns a filtered array of unique function names. The function is then exported as a module, allowing it to be used in other parts of the application.

Run example

npm run import -- "get exports from source"

get exports from source

var importer = require('../Core');
var {selectAst} = importer.import("select code tree")

// TODO: does this work on other node_modules?
function getExports(code) {
    var exports = [].concat.apply([], selectAst([
        `//AssignmentExpression[.//Identifier[@name="exports"]]`,
        ['.//Identifier', './@name']
    ], code))
    var functions = selectAst([
        `//FunctionDeclaration/Identifier[@parent-attr="id"]`,
        './@name'
    ], code)
    var functions2 = selectAst([
        `//AsyncFunctionDeclaration/Identifier[@parent-attr="id"]`,
        './@name'
    ], code)
    var functions3 = selectAst([
        `//ExportDefaultDeclaration/Identifier[@parent-attr="declaration"]`,
        './@name'
    ], code)
    return exports.concat(functions).concat(functions2).concat(functions3)
        .filter(e => e !== 'exports' && e !== 'require' && e !== 'module')
        .filter((e, i, arr) => arr.indexOf(e) === i)
}

module.exports = getExports;

What the code could have been:

// Import necessary modules and functions
const { selectAst } = require('../Core').import('select code tree');

/**
 * Extracts exported functions and variables from the given code.
 *
 * @param {string} code The JavaScript code to extract exports from.
 * @returns {string[]} An array of exported functions and variables.
 */
function getExports(code) {
  // Extract exports using selectAst function
  const exports = selectAst([
    `//AssignmentExpression/Identifier[@name="exports"]`,
    `././@name`,
  ], code).map((e) => e.name);

  // Extract functions using selectAst function
  const functions = selectAst([
    `//FunctionDeclaration/Identifier[@parent-attr="id"]`,
    `././@name`,
  ], code).map((e) => e.name);
  const asyncFunctions = selectAst([
    `//AsyncFunctionDeclaration/Identifier[@parent-attr="id"]`,
    `././@name`,
  ], code).map((e) => e.name);
  const defaultExports = selectAst([
    `//ExportDefaultDeclaration/Identifier[@parent-attr="declaration"]`,
    `././@name`,
  ], code).map((e) => e.name);

  // Combine extracted exports, filter out unnecessary exports, and remove duplicates
  return [...exports,...functions,...asyncFunctions,...defaultExports]
   .filter((e) => e!== 'exports' && e!=='require' && e!=='module')
   .filter((e, i, arr) => arr.indexOf(e) === i);
}

// Export the getExports function
module.exports = getExports;

Code Breakdown

Importing Modules

var importer = require('../Core');
var {selectAst} = importer.import('select code tree')

getExports Function

function getExports(code) {
    //...
}

Selecting AST Elements

The selectAst function is used to select elements from the Abstract Syntax Tree (AST) of the code. It takes two arguments: a CSS-like selector and the code to select from.

var exports = [].concat.apply([], selectAst([
    `//AssignmentExpression[.//Identifier[@name="exports"]]`,
    ['.//Identifier', './@name']
], code))

Selecting Function Names

var functions = selectAst([
    `//FunctionDeclaration/Identifier[@parent-attr="id"]`,
    './@name'
], code)
var functions2 = selectAst([
    `//AsyncFunctionDeclaration/Identifier[@parent-attr="id"]`,
    './@name'
], code)
var functions3 = selectAst([
    `//ExportDefaultDeclaration/Identifier[@parent-attr="id"]`,
    './@name'
], code)

Returning Exports and Functions

return exports.concat(functions).concat(functions2).concat(functions3)
   .filter(e => e!== 'exports' && e!=='require' && e!=='module')
   .filter((e, i, arr) => arr.indexOf(e) === i)

Exporting the Function

module.exports = getExports;