syntax | test parameter names | test get imports | Search

The getImports function extracts import information from a given code string by parsing an Abstract Syntax Tree (AST) and selecting specific nodes using XPath-like query strings. It is exported as a module and returns an array of import information, removing duplicates in the process.

Run example

npm run import -- "get imports from source"

get imports from source

var importer = require('../Core');
var {selectAst} = importer.import("select code tree")
var CORE_DECLARE = `//*[
    contains(@type, "Declar")
    and ./*/*[@type="Literal" and contains(@value, "Core")]
]`;
var IMPORTER = `${CORE_DECLARE}/*[@type="Identifier"]/@name`;
var IMPORTER_CALLS = `//*[contains(@type, "Call") and ./*[
    contains(@type, "Member") and contains(./Identifier/@name, "import")
] and ./Literal]`;

function getImports(code) {
    var importer = selectAst([IMPORTER], code)[0]
    return [].concat.apply([], selectAst([
        IMPORTER_CALLS.replace('importer', importer),
        [`./Identifier/@name|./*/Identifier/@name|.//Literal/@value`]
    ], code))
        .filter((i, j, arr) => arr.indexOf(i) === j)
}

module.exports = getImports;

What the code could have been:

const { selectAst } = require('../Core');

// Define the selector for Core declarations
const CORE_DECLARE_SELECTOR = `
  //[
    @type="Declar"
    and contains(@type, "Literal") and contains(@value, "Core")
  ]
`;

// Extract the importer name from the Core declaration
const IMPORTER_SELECTOR = (coreDeclaration) => `${coreDeclaration}/*[@type="Identifier"]/@name`;

// Define the selector for importer calls
const IMPORTER_CALLS_SELECTOR = `
  //[
    @type="Call"
    and./*[
      @type="Member"
      and contains(./Identifier/@name, "import")
    ]
    and./Literal
  ]
`;

/**
 * Extracts imports from the given code.
 *
 * @param {string} code - The code to extract imports from.
 * @returns {Array} An array of imports.
 */
function getImports(code) {
  // Select the Core declaration
  const coreDeclaration = selectAst([CORE_DECLARE_SELECTOR], code)[0];

  // Extract the importer name
  const importerName = IMPORTER_SELECTOR(coreDeclaration);

  // Select importer calls
  const importerCalls = selectAst([IMPORTER_CALLS_SELECTOR.replace('importer', importerName)], code);

  // Extract the import names and values
  const importNamesAndValues = importerCalls.map((importerCall) => {
    const identifier = importerCall.querySelector('.//Identifier');
    const literal = importerCall.querySelector('.//Literal');
    return [
      identifier? identifier.getAttribute('name') : null,
      identifier? identifier.querySelector('./../*[@type="Identifier"]/@name') : null,
      literal? literal.getAttribute('value') : null,
    ];
  });

  // Remove duplicates
  const uniqueImports = [...new Set(importNamesAndValues.flat())];

  return uniqueImports;
}

module.exports = getImports;

Code Breakdown

Variables and Functions

getImports Function

  1. Uses selectAst to find the first node matching the IMPORTER query in the given code, and assigns it to importer.
  2. Uses selectAst to find all nodes matching the IMPORTER_CALLS query, replacing importer with the actual node name.
  3. Concatenates the results of the previous step with an array containing the names of identifiers, their parent nodes, and literal values.
  4. Removes duplicates from the resulting array using the filter method.

Module Exports

The getImports function is exported as a module.