chore(providence-analytics): getSourceCodeFragmentOfDeclaration track down imports

This commit is contained in:
Thijs Louisse 2022-09-22 01:13:10 +02:00 committed by Thomas Allmer
parent 7e4cbecdc2
commit d92860a565
2 changed files with 60 additions and 8 deletions

View file

@ -1,6 +1,8 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path');
const babelTraversePkg = require('@babel/traverse'); const babelTraversePkg = require('@babel/traverse');
const { AstService } = require('../services/AstService.js'); const { AstService } = require('../services/AstService.js');
const { trackDownIdentifier } = require('../analyzers/helpers/track-down-identifier.js');
/** /**
* Assume we had: * Assume we had:
@ -22,6 +24,10 @@ function getReferencedDeclaration({ referencedIdentifierName, globalScopeBinding
([key]) => key === referencedIdentifierName, ([key]) => key === referencedIdentifierName,
); );
if (refDeclaratorBinding.path.type === 'ImportSpecifier') {
return refDeclaratorBinding.path;
}
if (refDeclaratorBinding.path.node.init.type === 'Identifier') { if (refDeclaratorBinding.path.node.init.type === 'Identifier') {
return getReferencedDeclaration({ return getReferencedDeclaration({
referencedIdentifierName: refDeclaratorBinding.path.node.init.name, referencedIdentifierName: refDeclaratorBinding.path.node.init.name,
@ -36,7 +42,11 @@ function getReferencedDeclaration({ referencedIdentifierName, globalScopeBinding
* *
* @param {{ filePath: string; exportedIdentifier: string; }} opts * @param {{ filePath: string; exportedIdentifier: string; }} opts
*/ */
async function getSourceCodeFragmentOfDeclaration({ filePath, exportedIdentifier }) { async function getSourceCodeFragmentOfDeclaration({
filePath,
exportedIdentifier,
projectRootPath,
}) {
const code = fs.readFileSync(filePath, 'utf-8'); const code = fs.readFileSync(filePath, 'utf-8');
const ast = AstService.getAst(code, 'babel'); const ast = AstService.getAst(code, 'babel');
@ -73,17 +83,19 @@ async function getSourceCodeFragmentOfDeclaration({ filePath, exportedIdentifier
} else { } else {
const variableDeclaratorPath = babelPath.scope.getBinding(exportedIdentifier).path; const variableDeclaratorPath = babelPath.scope.getBinding(exportedIdentifier).path;
const isReferenced = variableDeclaratorPath.node.init?.type === 'Identifier'; const isReferenced = variableDeclaratorPath.node.init?.type === 'Identifier';
const contentPath = variableDeclaratorPath.node.init
? variableDeclaratorPath.get('init')
: variableDeclaratorPath;
const name = variableDeclaratorPath.node.init
? variableDeclaratorPath.node.init.name
: variableDeclaratorPath.node.id.name;
if (!isReferenced) { if (!isReferenced) {
// it must be an exported declaration // it must be an exported declaration
finalNodePath = variableDeclaratorPath.node.init finalNodePath = contentPath;
? variableDeclaratorPath.get('init')
: variableDeclaratorPath;
} else { } else {
finalNodePath = getReferencedDeclaration({ finalNodePath = getReferencedDeclaration({
referencedIdentifierName: variableDeclaratorPath.node.init referencedIdentifierName: name,
? variableDeclaratorPath.node.init.name
: variableDeclaratorPath.node.id.name,
globalScopeBindings, globalScopeBindings,
}); });
} }
@ -91,9 +103,28 @@ async function getSourceCodeFragmentOfDeclaration({ filePath, exportedIdentifier
}, },
}); });
if (finalNodePath.type === 'ImportSpecifier') {
const importDeclNode = finalNodePath.parentPath.node;
const source = importDeclNode.source.value;
const identifierName = finalNodePath.node.imported.name;
const currentFilePath = filePath;
const rootFile = await trackDownIdentifier(
source,
identifierName,
currentFilePath,
projectRootPath,
);
return getSourceCodeFragmentOfDeclaration({
filePath: path.resolve(projectRootPath, rootFile.file),
exportedIdentifier: rootFile.specifier,
});
}
return { return {
sourceNodePath: finalNodePath, sourceNodePath: finalNodePath,
sourceFragment: code.slice(finalNodePath.node.start, finalNodePath.node.end), sourceFragment: code.slice(finalNodePath.node?.start, finalNodePath.node?.end),
}; };
} }

View file

@ -53,6 +53,27 @@ describe('getSourceCodeFragmentOfDeclaration', () => {
expect(sourceFragment).to.equal('88'); expect(sourceFragment).to.equal('88');
}); });
it('finds source code for imported referenced specifiers', async () => {
const fakeFs = {
'/my/proj/exports/file-1.js': `
export const black59 = '#aaa';
`,
'/my/proj/exports/file-2.js': `
import { black59 } from './file-1.js';
export const black67 = black59;
`,
};
mock(fakeFs);
const { sourceFragment } = await getSourceCodeFragmentOfDeclaration({
filePath: '/my/proj/exports/file-2.js',
exportedIdentifier: 'black67',
projectRootPath: '/my/proj',
});
expect(sourceFragment).to.equal("'#aaa'");
});
describe('Different types of declarations', () => { describe('Different types of declarations', () => {
it('handles class declarations', async () => { it('handles class declarations', async () => {
const fakeFs = { const fakeFs = {