diff --git a/packages-node/providence-analytics/src/program/analyzers/find-exports.js b/packages-node/providence-analytics/src/program/analyzers/find-exports.js index 3cf668033..12c5b5029 100644 --- a/packages-node/providence-analytics/src/program/analyzers/find-exports.js +++ b/packages-node/providence-analytics/src/program/analyzers/find-exports.js @@ -4,23 +4,24 @@ const { default: traverse } = require('@babel/traverse'); const { Analyzer } = require('./helpers/Analyzer.js'); const { trackDownIdentifier } = require('./helpers/track-down-identifier.js'); const { normalizeSourcePaths } = require('./helpers/normalize-source-paths.js'); -const { aForEach } = require('../utils/async-array-utils.js'); const { LogService } = require('../services/LogService.js'); /** * @typedef {import('./helpers/track-down-identifier.js').RootFile} RootFile * @typedef {object} RootFileMapEntry - * @property {string} currentFileSpecifier this is the local name in the file we track from - * @property {RootFile} rootFile contains file(filePath) and specifier + * @typedef {string} currentFileSpecifier this is the local name in the file we track from + * @typedef {RootFile} rootFile contains file(filePath) and specifier + * @typedef {RootFileMapEntry[]} RootFileMap + * + * @typedef {{ exportSpecifiers:string[]; localMap: object; source:string, __tmp: { path:string } }} FindExportsSpecifierObj */ /** - * @typedef {RootFileMapEntry[]} RootFileMap + * @param {FindExportsSpecifierObj[]} transformedEntry */ - async function trackdownRoot(transformedEntry, relativePath, projectPath) { const fullCurrentFilePath = pathLib.resolve(projectPath, relativePath); - await aForEach(transformedEntry, async specObj => { + for (const specObj of transformedEntry) { /** @type {RootFileMap} */ const rootFileMap = []; if (specObj.exportSpecifiers[0] === '[file]') { @@ -39,7 +40,7 @@ async function trackdownRoot(transformedEntry, relativePath, projectPath) { * } * } */ - await aForEach(specObj.exportSpecifiers, async (/** @type {string} */ specifier) => { + for (const specifier of specObj.exportSpecifiers) { let rootFile; let localMapMatch; if (specObj.localMap) { @@ -48,7 +49,7 @@ async function trackdownRoot(transformedEntry, relativePath, projectPath) { // TODO: find out if possible to use trackDownIdentifierFromScope if (specObj.source) { // TODO: see if still needed: && (localMapMatch || specifier === '[default]') - const importedIdentifier = (localMapMatch && localMapMatch.local) || specifier; + const importedIdentifier = localMapMatch?.local || specifier; rootFile = await trackDownIdentifier( specObj.source, importedIdentifier, @@ -69,10 +70,10 @@ async function trackdownRoot(transformedEntry, relativePath, projectPath) { }; rootFileMap.push(entry); } - }); + } } specObj.rootFileMap = rootFileMap; - }); + } return transformedEntry; } @@ -139,6 +140,8 @@ function findExportsPerAstEntry(ast, { skipFileImports }) { LogService.debug(`Analyzer "find-exports": started findExportsPerAstEntry method`); // Visit AST... + + /** @type {FindExportsSpecifierObj} */ const transformedEntry = []; // Unfortunately, we cannot have async functions in babel traverse. // Therefore, we store a temp reference to path that we use later for @@ -147,7 +150,7 @@ function findExportsPerAstEntry(ast, { skipFileImports }) { ExportNamedDeclaration(path) { const exportSpecifiers = getExportSpecifiers(path.node); const localMap = getLocalNameSpecifiers(path.node); - const source = path.node.source && path.node.source.value; + const source = path.node.source?.value; transformedEntry.push({ exportSpecifiers, localMap, source, __tmp: { path } }); }, ExportDefaultDeclaration(path) { @@ -205,7 +208,8 @@ class FindExportsAnalyzer extends Analyzer { * Traverse */ const projectPath = cfg.targetProjectPath; - const queryOutput = await this._traverse(async (ast, { relativePath }) => { + + const traverseEntryFn = async (ast, { relativePath }) => { let transformedEntry = findExportsPerAstEntry(ast, cfg); transformedEntry = await normalizeSourcePaths(transformedEntry, relativePath, projectPath); @@ -213,6 +217,12 @@ class FindExportsAnalyzer extends Analyzer { transformedEntry = cleanup(transformedEntry); return { result: transformedEntry }; + }; + + const queryOutput = await this._traverse({ + traverseEntryFn, + filePaths: cfg.targetFilePaths, + projectPath: cfg.targetProjectPath, }); /** diff --git a/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-exports-output.js b/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-exports-output.js new file mode 100644 index 000000000..855a6805a --- /dev/null +++ b/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-exports-output.js @@ -0,0 +1,67 @@ +/** + * @typedef {import('../../types/analyzers').FindExportsAnalyzerResult} FindExportsAnalyzerResult + */ + +/** + * Convert to more easily iterable object + * + * From: + * ```js + * [ + * "file": "./file-1.js", + * "result": [{ + * "exportSpecifiers": [ "a", "b"], + * "localMap": [{...},{...}], + * "source": null, + * "rootFileMap": [{"currentFileSpecifier": "a", "rootFile": { "file": "[current]", "specifier": "a" }}] + * }, ...], + * ``` + * To: + * ```js + * [{ + * "file": ""./file-1.js", + * "exportSpecifier": "a", + * "localMap": {...}, + * "source": null, + * "rootFileMap": {...} + * }, + * {{ + * "file": ""./file-1.js", + * "exportSpecifier": "b", + * "localMap": {...}, + * "source": null, + * "rootFileMap": {...} + * }}], + * + * @param {FindExportsAnalyzerResult} exportsAnalyzerResult + */ +function transformIntoIterableFindExportsOutput(exportsAnalyzerResult) { + /** @type {IterableFindExportsAnalyzerEntry[]} */ + const iterableEntries = []; + + for (const { file, result } of exportsAnalyzerResult.queryOutput) { + for (const { exportSpecifiers, source, rootFileMap, localMap, meta } of result) { + if (!exportSpecifiers) { + // eslint-disable-next-line no-continue + continue; + } + for (const exportSpecifier of exportSpecifiers) { + const i = exportSpecifiers.indexOf(exportSpecifier); + /** @type {IterableFindExportsAnalyzerEntry} */ + const resultEntry = { + file, + specifier: exportSpecifier, + source, + rootFile: rootFileMap ? rootFileMap[i] : undefined, + localSpecifier: localMap ? localMap[i] : undefined, + meta, + }; + iterableEntries.push(resultEntry); + } + } + } + return iterableEntries; +} +module.exports = { + transformIntoIterableFindExportsOutput, +}; diff --git a/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-imports-output.js b/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-imports-output.js new file mode 100644 index 000000000..f4a1edc43 --- /dev/null +++ b/packages-node/providence-analytics/src/program/analyzers/helpers/transform-into-iterable-find-imports-output.js @@ -0,0 +1,62 @@ +/** + * @typedef {import('../../types/analyzers').FindImportsAnalyzerResult} FindImportsAnalyzerResult + */ + +/** + * Convert to more easily iterable object + * + * From: + * ```js + * [ + * "file": "./file-1.js", + * "result": [{ + * "importSpecifiers": [ "a", "b" ], + * "source": "exporting-ref-project", + * "normalizedSource": "exporting-ref-project" + * }], , + * ``` + * To: + * ```js + * [{ + * "file": ""./file-1.js", + * "importSpecifier": "a",, + * "source": "exporting-ref-project", + * "normalizedSource": "exporting-ref-project" + * }, + * {{ + * "file": ""./file-1.js", + * "importSpecifier": "b",, + * "source": "exporting-ref-project", + * "normalizedSource": "exporting-ref-project" + * }}], + * + * @param {FindImportsAnalyzerResult} importsAnalyzerResult + */ +function transformIntoIterableFindImportsOutput(importsAnalyzerResult) { + /** @type {IterableFindImportsAnalyzerEntry[]} */ + const iterableEntries = []; + + for (const { file, result } of importsAnalyzerResult.queryOutput) { + for (const { importSpecifiers, source, normalizedSource } of result) { + if (!importSpecifiers) { + // eslint-disable-next-line no-continue + continue; + } + for (const importSpecifier of importSpecifiers) { + /** @type {IterableFindImportsAnalyzerEntry} */ + const resultEntry = { + file, + specifier: importSpecifier, + source, + normalizedSource, + }; + iterableEntries.push(resultEntry); + } + } + } + return iterableEntries; +} + +module.exports = { + transformIntoIterableFindImportsOutput, +}; diff --git a/packages-node/providence-analytics/src/program/analyzers/match-imports.js b/packages-node/providence-analytics/src/program/analyzers/match-imports.js index 703d0cea3..1f83ecb8f 100644 --- a/packages-node/providence-analytics/src/program/analyzers/match-imports.js +++ b/packages-node/providence-analytics/src/program/analyzers/match-imports.js @@ -5,6 +5,12 @@ const FindImportsAnalyzer = require('./find-imports.js'); const FindExportsAnalyzer = require('./find-exports.js'); const { Analyzer } = require('./helpers/Analyzer.js'); const { fromImportToExportPerspective } = require('./helpers/from-import-to-export-perspective.js'); +const { + transformIntoIterableFindExportsOutput, +} = require('./helpers/transform-into-iterable-find-exports-output.js'); +const { + transformIntoIterableFindImportsOutput, +} = require('./helpers/transform-into-iterable-find-imports-output.js'); /** * @typedef {import('../types/analyzers').FindImportsAnalyzerResult} FindImportsAnalyzerResult @@ -32,120 +38,6 @@ function compareImportAndExportPaths(exportPath, translatedImportPath) { ); } -/** - * Convert to more easily iterable object - * - * From: - * ```js - * [ - * "file": "./file-1.js", - * "result": [{ - * "exportSpecifiers": [ "a", "b"], - * "localMap": [{...},{...}], - * "source": null, - * "rootFileMap": [{"currentFileSpecifier": "a", "rootFile": { "file": "[current]", "specifier": "a" }}] - * }, ...], - * ``` - * To: - * ```js - * [{ - * "file": ""./file-1.js", - * "exportSpecifier": "a", - * "localMap": {...}, - * "source": null, - * "rootFileMap": {...} - * }, - * {{ - * "file": ""./file-1.js", - * "exportSpecifier": "b", - * "localMap": {...}, - * "source": null, - * "rootFileMap": {...} - * }}], - * - * @param {FindExportsAnalyzerResult} exportsAnalyzerResult - */ -function transformIntoIterableFindExportsOutput(exportsAnalyzerResult) { - /** @type {IterableFindExportsAnalyzerEntry[]} */ - const iterableEntries = []; - - for (const { file, result } of exportsAnalyzerResult.queryOutput) { - for (const { exportSpecifiers, source, rootFileMap, localMap, meta } of result) { - if (!exportSpecifiers) { - continue; - } - for (const exportSpecifier of exportSpecifiers) { - const i = exportSpecifiers.indexOf(exportSpecifier); - /** @type {IterableFindExportsAnalyzerEntry} */ - const resultEntry = { - file, - specifier: exportSpecifier, - source, - rootFile: rootFileMap ? rootFileMap[i] : undefined, - localSpecifier: localMap ? localMap[i] : undefined, - meta, - }; - iterableEntries.push(resultEntry); - } - } - } - return iterableEntries; -} - -/** - * Convert to more easily iterable object - * - * From: - * ```js - * [ - * "file": "./file-1.js", - * "result": [{ - * "importSpecifiers": [ "a", "b" ], - * "source": "exporting-ref-project", - * "normalizedSource": "exporting-ref-project" - * }], , - * ``` - * To: - * ```js - * [{ - * "file": ""./file-1.js", - * "importSpecifier": "a",, - * "source": "exporting-ref-project", - * "normalizedSource": "exporting-ref-project" - * }, - * {{ - * "file": ""./file-1.js", - * "importSpecifier": "b",, - * "source": "exporting-ref-project", - * "normalizedSource": "exporting-ref-project" - * }}], - * - * @param {FindImportsAnalyzerResult} importsAnalyzerResult - */ -function transformIntoIterableFindImportsOutput(importsAnalyzerResult) { - /** @type {IterableFindImportsAnalyzerEntry[]} */ - const iterableEntries = []; - - for (const { file, result } of importsAnalyzerResult.queryOutput) { - for (const { importSpecifiers, source, normalizedSource } of result) { - if (!importSpecifiers) { - continue; - } - for (const importSpecifier of importSpecifiers) { - /** @type {IterableFindImportsAnalyzerEntry} */ - const resultEntry = { - file, - specifier: importSpecifier, - source, - normalizedSource, - }; - iterableEntries.push(resultEntry); - } - } - } - return iterableEntries; -} - /** * Makes a 'compatible resultsArray' (compatible with dashboard + tests + ...?) from * a conciseResultsArray. diff --git a/packages-node/providence-analytics/test-node/program/analyzers/find-exports.test.js b/packages-node/providence-analytics/test-node/program/analyzers/find-exports.test.js index 98f9be9f5..700603fa5 100644 --- a/packages-node/providence-analytics/test-node/program/analyzers/find-exports.test.js +++ b/packages-node/providence-analytics/test-node/program/analyzers/find-exports.test.js @@ -53,7 +53,7 @@ describe('Analyzer "find-exports"', () => { const firstEntry = getEntry(queryResult); expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1); expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('x'); - expect(firstEntry.result[0].source).to.be.null; + expect(firstEntry.result[0].source).to.be.undefined; }); it(`supports [export default class X {}] (default export)`, async () => { @@ -189,7 +189,7 @@ describe('Analyzer "find-exports"', () => { const firstEntry = getEntry(queryResult); expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1); expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('X'); - expect(firstEntry.result[0].source).to.be.null; + expect(firstEntry.result[0].source).to.be.undefined; }); it(`functions`, async () => { @@ -199,7 +199,7 @@ describe('Analyzer "find-exports"', () => { const firstEntry = getEntry(queryResult); expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1); expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('y'); - expect(firstEntry.result[0].source).to.be.null; + expect(firstEntry.result[0].source).to.be.undefined; }); // ...etc?