chore(providence-analytics): apply "custom projects" in find-exports

This commit is contained in:
Thijs Louisse 2022-09-14 17:01:18 +02:00 committed by Thijs Louisse
parent 0b95d906e3
commit 3865a2433f
5 changed files with 160 additions and 129 deletions

View file

@ -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,
});
/**

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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.

View file

@ -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?