chore: clean and lint providence
This commit is contained in:
parent
f601d59d77
commit
e7a65a1e51
12 changed files with 76 additions and 846 deletions
|
|
@ -1,272 +0,0 @@
|
|||
/* eslint-disable no-shadow, no-param-reassign */
|
||||
import pathLib from 'path';
|
||||
import babelTraverse from '@babel/traverse';
|
||||
import { Analyzer } from '../core/Analyzer.js';
|
||||
import { trackDownIdentifier } from './helpers/track-down-identifier--legacy.js';
|
||||
import { normalizeSourcePaths } from './helpers/normalize-source-paths.js';
|
||||
import { getReferencedDeclaration } from '../utils/get-source-code-fragment-of-declaration.js';
|
||||
import { LogService } from '../core/LogService.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('@babel/types').File} File
|
||||
* @typedef {import('@babel/types').Node} Node
|
||||
* @typedef {import('../../../types/index.js').AnalyzerName} AnalyzerName
|
||||
* @typedef {import('../../../types/index.js').FindExportsAnalyzerResult} FindExportsAnalyzerResult
|
||||
* @typedef {import('../../../types/index.js').FindExportsAnalyzerEntry} FindExportsAnalyzerEntry
|
||||
* @typedef {import('../../../types/index.js').PathRelativeFromProjectRoot} PathRelativeFromProjectRoot
|
||||
* @typedef {import('./helpers/track-down-identifier.js').RootFile} RootFile
|
||||
* @typedef {object} RootFileMapEntry
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {FindExportsSpecifierObj[]} transformedFile
|
||||
*/
|
||||
async function trackdownRoot(transformedFile, relativePath, projectPath) {
|
||||
const fullCurrentFilePath = pathLib.resolve(projectPath, relativePath);
|
||||
for (const specObj of transformedFile) {
|
||||
/** @type {RootFileMap} */
|
||||
const rootFileMap = [];
|
||||
if (specObj.exportSpecifiers[0] === '[file]') {
|
||||
rootFileMap.push(undefined);
|
||||
} else {
|
||||
/**
|
||||
* './src/origin.js': `export class MyComp {}`
|
||||
* './index.js:' `export { MyComp as RenamedMyComp } from './src/origin'`
|
||||
*
|
||||
* Goes from specifier like 'RenamedMyComp' to object for rootFileMap like:
|
||||
* {
|
||||
* currentFileSpecifier: 'RenamedMyComp',
|
||||
* rootFile: {
|
||||
* file: './src/origin.js',
|
||||
* specifier: 'MyCompDefinition',
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
for (const specifier of specObj.exportSpecifiers) {
|
||||
let rootFile;
|
||||
let localMapMatch;
|
||||
if (specObj.localMap) {
|
||||
localMapMatch = specObj.localMap.find(m => m.exported === specifier);
|
||||
}
|
||||
|
||||
// TODO: find out if possible to use trackDownIdentifierFromScope
|
||||
if (specObj.source) {
|
||||
// TODO: see if still needed: && (localMapMatch || specifier === '[default]')
|
||||
const importedIdentifier = localMapMatch?.local || specifier;
|
||||
|
||||
rootFile = await trackDownIdentifier(
|
||||
specObj.source,
|
||||
importedIdentifier,
|
||||
fullCurrentFilePath,
|
||||
projectPath,
|
||||
);
|
||||
|
||||
/** @type {RootFileMapEntry} */
|
||||
const entry = {
|
||||
currentFileSpecifier: specifier,
|
||||
rootFile,
|
||||
};
|
||||
rootFileMap.push(entry);
|
||||
} else {
|
||||
/** @type {RootFileMapEntry} */
|
||||
const entry = {
|
||||
currentFileSpecifier: specifier,
|
||||
rootFile: { file: '[current]', specifier },
|
||||
};
|
||||
rootFileMap.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
specObj.rootFileMap = rootFileMap;
|
||||
}
|
||||
return transformedFile;
|
||||
}
|
||||
|
||||
function cleanup(transformedFile) {
|
||||
transformedFile.forEach(specObj => {
|
||||
if (specObj.__tmp) {
|
||||
delete specObj.__tmp;
|
||||
}
|
||||
});
|
||||
return transformedFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getExportSpecifiers(node) {
|
||||
// handles default [export const g = 4];
|
||||
if (node.declaration) {
|
||||
if (node.declaration.declarations) {
|
||||
return [node.declaration.declarations[0].id.name];
|
||||
}
|
||||
if (node.declaration.id) {
|
||||
return [node.declaration.id.name];
|
||||
}
|
||||
}
|
||||
|
||||
// handles (re)named specifiers [export { x (as y)} from 'y'];
|
||||
return node.specifiers.map(s => {
|
||||
let specifier;
|
||||
if (s.exported) {
|
||||
// { x as y }
|
||||
specifier = s.exported.name === 'default' ? '[default]' : s.exported.name;
|
||||
} else {
|
||||
// { x }
|
||||
specifier = s.local.name;
|
||||
}
|
||||
return specifier;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {object[]}
|
||||
*/
|
||||
function getLocalNameSpecifiers(node) {
|
||||
return node.specifiers
|
||||
.map(s => {
|
||||
if (s.exported && s.local && s.exported.name !== s.local.name) {
|
||||
return {
|
||||
// if reserved keyword 'default' is used, translate it into 'providence keyword'
|
||||
local: s.local.name === 'default' ? '[default]' : s.local.name,
|
||||
exported: s.exported.name,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.filter(s => s);
|
||||
}
|
||||
|
||||
const isImportingSpecifier = pathOrNode =>
|
||||
pathOrNode.type === 'ImportDefaultSpecifier' || pathOrNode.type === 'ImportSpecifier';
|
||||
|
||||
/**
|
||||
* Finds import specifiers and sources for a given ast result
|
||||
* @param {File} babelAst
|
||||
* @param {FindExportsConfig} config
|
||||
*/
|
||||
function findExportsPerAstFile(babelAst, { skipFileImports }) {
|
||||
LogService.debug(`Analyzer "find-exports": started findExportsPerAstFile method`);
|
||||
|
||||
// Visit AST...
|
||||
|
||||
/** @type {FindExportsSpecifierObj[]} */
|
||||
const transformedFile = [];
|
||||
// Unfortunately, we cannot have async functions in babel traverse.
|
||||
// Therefore, we store a temp reference to path that we use later for
|
||||
// async post processing (tracking down original export Identifier)
|
||||
let globalScopeBindings;
|
||||
|
||||
babelTraverse.default(babelAst, {
|
||||
Program(babelPath) {
|
||||
// enter(babelPath) {
|
||||
const body = babelPath.get('body');
|
||||
if (body.length) {
|
||||
globalScopeBindings = body[0].scope.bindings;
|
||||
}
|
||||
// },
|
||||
},
|
||||
ExportNamedDeclaration(astPath) {
|
||||
const exportSpecifiers = getExportSpecifiers(astPath.node);
|
||||
const localMap = getLocalNameSpecifiers(astPath.node);
|
||||
const source = astPath.node.source?.value;
|
||||
const entry = { exportSpecifiers, localMap, source, __tmp: { astPath } };
|
||||
if (astPath.node.assertions?.length) {
|
||||
entry.assertionType = astPath.node.assertions[0].value?.value;
|
||||
}
|
||||
transformedFile.push(entry);
|
||||
},
|
||||
ExportDefaultDeclaration(defaultExportPath) {
|
||||
const exportSpecifiers = ['[default]'];
|
||||
let source;
|
||||
if (defaultExportPath.node.declaration?.type !== 'Identifier') {
|
||||
source = defaultExportPath.node.declaration.name;
|
||||
} else {
|
||||
const importOrDeclPath = getReferencedDeclaration({
|
||||
referencedIdentifierName: defaultExportPath.node.declaration.name,
|
||||
globalScopeBindings,
|
||||
});
|
||||
if (isImportingSpecifier(importOrDeclPath)) {
|
||||
source = importOrDeclPath.parentPath.node.source.value;
|
||||
}
|
||||
}
|
||||
transformedFile.push({ exportSpecifiers, source, __tmp: { astPath: defaultExportPath } });
|
||||
},
|
||||
});
|
||||
|
||||
if (!skipFileImports) {
|
||||
// Always add an entry for just the file 'relativePath'
|
||||
// (since this also can be imported directly from a search target project)
|
||||
transformedFile.push({
|
||||
exportSpecifiers: ['[file]'],
|
||||
// source: relativePath,
|
||||
});
|
||||
}
|
||||
|
||||
return transformedFile;
|
||||
}
|
||||
|
||||
export default class FindExportsAnalyzer extends Analyzer {
|
||||
/** @type {AnalyzerName} */
|
||||
static analyzerName = 'find-exports';
|
||||
|
||||
/** @type {'babel'|'swc-to-babel'} */
|
||||
static requiredAst = 'swc-to-babel';
|
||||
|
||||
/**
|
||||
* Finds export specifiers and sources
|
||||
* @param {FindExportsConfig} customConfig
|
||||
*/
|
||||
async execute(customConfig = {}) {
|
||||
/**
|
||||
* @typedef FindExportsConfig
|
||||
* @property {boolean} [onlyInternalSources=false]
|
||||
* @property {boolean} [skipFileImports=false] Instead of both focusing on specifiers like
|
||||
* [import {specifier} 'lion-based-ui/foo.js'], and [import 'lion-based-ui/foo.js'] as a result,
|
||||
* not list file exports
|
||||
*/
|
||||
const cfg = {
|
||||
targetProjectPath: null,
|
||||
skipFileImports: false,
|
||||
...customConfig,
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare
|
||||
*/
|
||||
const cachedAnalyzerResult = this._prepare(cfg);
|
||||
if (cachedAnalyzerResult) {
|
||||
return cachedAnalyzerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse
|
||||
*/
|
||||
const projectPath = cfg.targetProjectPath;
|
||||
|
||||
const traverseEntryFn = async (ast, { relativePath }) => {
|
||||
let transformedFile = findExportsPerAstFile(ast, cfg);
|
||||
|
||||
transformedFile = await normalizeSourcePaths(transformedFile, relativePath, projectPath);
|
||||
transformedFile = await trackdownRoot(transformedFile, relativePath, projectPath);
|
||||
transformedFile = cleanup(transformedFile);
|
||||
|
||||
return { result: transformedFile };
|
||||
};
|
||||
|
||||
const queryOutput = await this._traverse({
|
||||
traverseEntryFn,
|
||||
filePaths: cfg.targetFilePaths,
|
||||
projectPath: cfg.targetProjectPath,
|
||||
});
|
||||
|
||||
/**
|
||||
* Finalize
|
||||
*/
|
||||
return this._finalize(queryOutput, cfg);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
/* eslint-disable no-shadow, no-param-reassign */
|
||||
import babelTraverse from '@babel/traverse';
|
||||
import { isRelativeSourcePath } from '../utils/relative-source-path.js';
|
||||
import { normalizeSourcePaths } from './helpers/normalize-source-paths.js';
|
||||
import { Analyzer } from '../core/Analyzer.js';
|
||||
import { LogService } from '../core/LogService.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('@babel/types').File} File
|
||||
* @typedef {import('@babel/types').Node} Node
|
||||
* @typedef {import('../../../types/index.js').AnalyzerName} AnalyzerName
|
||||
* @typedef {import('../../../types/index.js').AnalyzerConfig} AnalyzerConfig
|
||||
* @typedef {import('../../../types/index.js').FindImportsAnalyzerResult} FindImportsAnalyzerResult
|
||||
* @typedef {import('../../../types/index.js').FindImportsAnalyzerEntry} FindImportsAnalyzerEntry
|
||||
* @typedef {import('../../../types/index.js').PathRelativeFromProjectRoot} PathRelativeFromProjectRoot
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options that allow to filter 'on a file basis'.
|
||||
* We can also filter on the total result
|
||||
*/
|
||||
const /** @type {AnalyzerConfig} */ options = {
|
||||
/**
|
||||
* Only leaves entries with external sources:
|
||||
* - keeps: '@open-wc/testing'
|
||||
* - drops: '../testing'
|
||||
* @param {FindImportsAnalyzerQueryOutput} result
|
||||
* @param {string} targetSpecifier for instance 'LitElement'
|
||||
*/
|
||||
onlyExternalSources(result) {
|
||||
return result.filter(entry => !isRelativeSourcePath(entry.source));
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
*/
|
||||
function getImportOrReexportsSpecifiers(node) {
|
||||
return node.specifiers.map(s => {
|
||||
if (
|
||||
s.type === 'ImportDefaultSpecifier' ||
|
||||
s.type === 'ExportDefaultSpecifier' ||
|
||||
(s.type === 'ExportSpecifier' && s.exported?.name === 'default')
|
||||
) {
|
||||
return '[default]';
|
||||
}
|
||||
if (s.type === 'ImportNamespaceSpecifier' || s.type === 'ExportNamespaceSpecifier') {
|
||||
return '[*]';
|
||||
}
|
||||
if ((s.imported && s.type === 'ImportNamespaceSpecifier') || s.type === 'ImportSpecifier') {
|
||||
return s.imported.name;
|
||||
}
|
||||
if (s.exported && s.type === 'ExportNamespaceSpecifier') {
|
||||
return s.exported.name;
|
||||
}
|
||||
return s.local.name;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds import specifiers and sources
|
||||
* @param {File} babelAst
|
||||
*/
|
||||
function findImportsPerAstFile(babelAst, context) {
|
||||
LogService.debug(`Analyzer "find-imports": started findImportsPerAstFile method`);
|
||||
|
||||
// https://github.com/babel/babel/blob/672a58660f0b15691c44582f1f3fdcdac0fa0d2f/packages/babel-core/src/transformation/index.ts#L110
|
||||
// Visit AST...
|
||||
/** @type {Partial<FindImportsAnalyzerEntry>[]} */
|
||||
const transformedFile = [];
|
||||
babelTraverse.default(babelAst, {
|
||||
ImportDeclaration(path) {
|
||||
const importSpecifiers = getImportOrReexportsSpecifiers(path.node);
|
||||
if (!importSpecifiers.length) {
|
||||
importSpecifiers.push('[file]'); // apparently, there was just a file import
|
||||
}
|
||||
const source = path.node.source.value;
|
||||
const entry = /** @type {Partial<FindImportsAnalyzerEntry>} */ ({ importSpecifiers, source });
|
||||
if (path.node.assertions?.length) {
|
||||
entry.assertionType = path.node.assertions[0].value?.value;
|
||||
}
|
||||
transformedFile.push(entry);
|
||||
},
|
||||
// Dynamic imports
|
||||
CallExpression(path) {
|
||||
if (path.node.callee?.type !== 'Import') {
|
||||
return;
|
||||
}
|
||||
// TODO: check for specifiers catched via obj destructuring?
|
||||
// TODO: also check for ['file']
|
||||
const importSpecifiers = ['[default]'];
|
||||
let source = path.node.arguments[0].value;
|
||||
if (!source) {
|
||||
// TODO: with advanced retrieval, we could possibly get the value
|
||||
source = '[variable]';
|
||||
}
|
||||
transformedFile.push({ importSpecifiers, source });
|
||||
},
|
||||
ExportNamedDeclaration(path) {
|
||||
if (!path.node.source) {
|
||||
return; // we are dealing with a regular export, not a reexport
|
||||
}
|
||||
const importSpecifiers = getImportOrReexportsSpecifiers(path.node);
|
||||
const source = path.node.source.value;
|
||||
const entry = /** @type {Partial<FindImportsAnalyzerEntry>} */ ({ importSpecifiers, source });
|
||||
if (path.node.assertions?.length) {
|
||||
entry.assertionType = path.node.assertions[0].value?.value;
|
||||
}
|
||||
transformedFile.push(entry);
|
||||
},
|
||||
// ExportAllDeclaration(path) {
|
||||
// if (!path.node.source) {
|
||||
// return; // we are dealing with a regular export, not a reexport
|
||||
// }
|
||||
// const importSpecifiers = ['[*]'];
|
||||
// const source = path.node.source.value;
|
||||
// transformedFile.push({ importSpecifiers, source });
|
||||
// },
|
||||
});
|
||||
|
||||
return transformedFile;
|
||||
}
|
||||
|
||||
export default class FindImportsAnalyzer extends Analyzer {
|
||||
/** @type {AnalyzerName} */
|
||||
static analyzerName = 'find-imports';
|
||||
|
||||
/** @type {'babel'|'swc-to-babel'} */
|
||||
requiredAst = 'swc-to-babel';
|
||||
|
||||
/**
|
||||
* Finds import specifiers and sources
|
||||
* @param {FindImportsConfig} customConfig
|
||||
*/
|
||||
async execute(customConfig = {}) {
|
||||
/**
|
||||
* @typedef FindImportsConfig
|
||||
* @property {boolean} [keepInternalSources=false] by default, relative paths like '../x.js' are
|
||||
* filtered out. This option keeps them.
|
||||
* means that 'external-dep/file' will be resolved to 'external-dep/file.js' will both be stored
|
||||
* as the latter
|
||||
*/
|
||||
const cfg = {
|
||||
targetProjectPath: null,
|
||||
// post process file
|
||||
keepInternalSources: false,
|
||||
...customConfig,
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare
|
||||
*/
|
||||
const cachedAnalyzerResult = this._prepare(cfg);
|
||||
if (cachedAnalyzerResult) {
|
||||
return cachedAnalyzerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse
|
||||
*/
|
||||
const queryOutput = await this._traverse(async (ast, context) => {
|
||||
let transformedFile = findImportsPerAstFile(ast, context);
|
||||
// Post processing based on configuration...
|
||||
transformedFile = await normalizeSourcePaths(
|
||||
transformedFile,
|
||||
context.relativePath,
|
||||
cfg.targetProjectPath,
|
||||
);
|
||||
|
||||
if (!cfg.keepInternalSources) {
|
||||
transformedFile = options.onlyExternalSources(transformedFile);
|
||||
}
|
||||
|
||||
return { result: transformedFile };
|
||||
});
|
||||
|
||||
// if (cfg.sortBySpecifier) {
|
||||
// queryOutput = sortBySpecifier.execute(queryOutput, {
|
||||
// ...cfg,
|
||||
// specifiersKey: 'importSpecifiers',
|
||||
// });
|
||||
// }
|
||||
|
||||
/**
|
||||
* Finalize
|
||||
*/
|
||||
return this._finalize(queryOutput, cfg);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import { LogService } from '../core/LogService.js';
|
|||
* @param {SwcNode} node
|
||||
*/
|
||||
function getImportOrReexportsSpecifiers(node) {
|
||||
// @ts-expect-error
|
||||
return node.specifiers.map(s => {
|
||||
if (
|
||||
s.type === 'ImportDefaultSpecifier' ||
|
||||
|
|
@ -40,7 +41,7 @@ function getImportOrReexportsSpecifiers(node) {
|
|||
* Finds import specifiers and sources
|
||||
* @param {SwcAstModule} swcAst
|
||||
*/
|
||||
function findImportsPerAstFile(swcAst, context) {
|
||||
function findImportsPerAstFile(swcAst) {
|
||||
LogService.debug(`Analyzer "find-imports": started findImportsPerAstFile method`);
|
||||
|
||||
// https://github.com/babel/babel/blob/672a58660f0b15691c44582f1f3fdcdac0fa0d2f/packages/babel-core/src/transformation/index.ts#L110
|
||||
|
|
@ -129,15 +130,18 @@ export default class FindImportsSwcAnalyzer extends Analyzer {
|
|||
* Traverse
|
||||
*/
|
||||
const queryOutput = await this._traverse(async (swcAst, context) => {
|
||||
let transformedFile = findImportsPerAstFile(swcAst, context);
|
||||
// @ts-expect-error
|
||||
let transformedFile = findImportsPerAstFile(swcAst);
|
||||
// Post processing based on configuration...
|
||||
transformedFile = await normalizeSourcePaths(
|
||||
transformedFile,
|
||||
context.relativePath,
|
||||
// @ts-expect-error
|
||||
cfg.targetProjectPath,
|
||||
);
|
||||
|
||||
if (!cfg.keepInternalSources) {
|
||||
// @ts-expect-error
|
||||
transformedFile = transformedFile.filter(entry => !isRelativeSourcePath(entry.source));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-disable no-shadow */
|
||||
// @ts-nocheck
|
||||
import fs from 'fs';
|
||||
import pathLib from 'path';
|
||||
import babelTraverse from '@babel/traverse';
|
||||
|
|
|
|||
|
|
@ -39,16 +39,16 @@ function isExternalProject(source, projectName) {
|
|||
* Other than with import, no binding is created for MyClass by Babel(?)
|
||||
* This means 'path.scope.getBinding('MyClass')' returns undefined
|
||||
* and we have to find a different way to retrieve this value.
|
||||
* @param {SwcPath} astPath Babel ast traversal path
|
||||
* @param {SwcPath} swcPath Babel ast traversal path
|
||||
* @param {IdentifierName} identifierName the name that should be tracked (and that exists inside scope of astPath)
|
||||
*/
|
||||
function getBindingAndSourceReexports(astPath, identifierName) {
|
||||
function getBindingAndSourceReexports(swcPath, identifierName) {
|
||||
// Get to root node of file and look for exports like `export { identifierName } from 'src';`
|
||||
let source;
|
||||
let bindingType;
|
||||
let bindingPath;
|
||||
|
||||
let curPath = astPath;
|
||||
let curPath = swcPath;
|
||||
while (curPath.parentPath) {
|
||||
curPath = curPath.parentPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import { trackDownIdentifier } from '../analyzers/helpers/track-down-identifier.
|
|||
import { toPosixPath } from './to-posix-path.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('@babel/types').Node} Node
|
||||
* @typedef {import('@babel/traverse').NodePath} NodePath
|
||||
* @typedef {import('@swc/core').Node} SwcNode
|
||||
* @typedef {import('../../../types/index.js').SwcPath} SwcPath
|
||||
* @typedef {import('../../../types/index.js').SwcBinding} SwcBinding
|
||||
* @typedef {import('../../../types/index.js').PathRelativeFromProjectRoot} PathRelativeFromProjectRoot
|
||||
* @typedef {import('../../../types/index.js').PathFromSystemRoot} PathFromSystemRoot
|
||||
|
|
@ -39,13 +39,10 @@ export function getFilePathOrExternalSource({ rootPath, localPath }) {
|
|||
* - Is it a ref? Call ourselves with referencedIdentifierName ('x' in example above)
|
||||
* - is it a non ref declaration? Return the path of the node
|
||||
* @param {{ referencedIdentifierName:string, globalScopeBindings:{[key:string]:SwcBinding}; }} opts
|
||||
* @returns {NodePath}
|
||||
* @returns {SwcPath|null}
|
||||
*/
|
||||
export function getReferencedDeclaration({ referencedIdentifierName, globalScopeBindings }) {
|
||||
// We go from referencedIdentifierName 'y' to binding (VariableDeclarator path) 'y';
|
||||
// const [, refDeclaratorBinding] =
|
||||
// Object.entries(globalScopeBindings).find(([key]) => key === referencedIdentifierName) || [];
|
||||
|
||||
const refDeclaratorBinding = globalScopeBindings[referencedIdentifierName];
|
||||
|
||||
// We provided a referencedIdentifierName that is not in the globalScopeBindings
|
||||
|
|
@ -80,7 +77,7 @@ export function getReferencedDeclaration({ referencedIdentifierName, globalScope
|
|||
* ```
|
||||
*
|
||||
* @param {{ filePath: PathFromSystemRoot; exportedIdentifier: string; projectRootPath: PathFromSystemRoot }} opts
|
||||
* @returns {Promise<{ sourceNodePath: string; sourceFragment: string|null; externalImportSource: string; }>}
|
||||
* @returns {Promise<{ sourceNodePath: SwcPath; sourceFragment: string|null; externalImportSource: string|null; }>}
|
||||
*/
|
||||
export async function getSourceCodeFragmentOfDeclaration({
|
||||
filePath,
|
||||
|
|
@ -94,7 +91,7 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
// TODO: fix swc-to-babel lib to make this compatible with 'swc-to-babel' mode of getAst
|
||||
const swcAst = AstService._getSwcAst(code);
|
||||
|
||||
/** @type {NodePath} */
|
||||
/** @type {SwcPath} */
|
||||
let finalNodePath;
|
||||
|
||||
swcTraverse(
|
||||
|
|
@ -114,20 +111,25 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
const globalScopeBindings = getPathFromNode(astPath.node.body?.[0])?.scope.bindings;
|
||||
|
||||
if (exportedIdentifier === '[default]') {
|
||||
const defaultExportPath = getPathFromNode(
|
||||
astPath.node.body.find(child =>
|
||||
const defaultExportPath = /** @type {SwcPath} */ (
|
||||
getPathFromNode(
|
||||
astPath.node.body.find((/** @type {{ type: string; }} */ child) =>
|
||||
['ExportDefaultDeclaration', 'ExportDefaultExpression'].includes(child.type),
|
||||
),
|
||||
)
|
||||
);
|
||||
const isReferenced = defaultExportPath?.node.expression?.type === 'Identifier';
|
||||
|
||||
if (!isReferenced) {
|
||||
finalNodePath = defaultExportPath.get('decl') || defaultExportPath.get('expression');
|
||||
} else {
|
||||
finalNodePath = getReferencedDeclaration({
|
||||
finalNodePath = /** @type {SwcPath} */ (
|
||||
getReferencedDeclaration({
|
||||
referencedIdentifierName: defaultExportPath.node.expression.value,
|
||||
// @ts-expect-error
|
||||
globalScopeBindings,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const variableDeclaratorPath = astPath.scope.bindings[exportedIdentifier].path;
|
||||
|
|
@ -145,10 +147,13 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
// it must be an exported declaration
|
||||
finalNodePath = contentPath;
|
||||
} else {
|
||||
finalNodePath = getReferencedDeclaration({
|
||||
finalNodePath = /** @type {SwcPath} */ (
|
||||
getReferencedDeclaration({
|
||||
referencedIdentifierName: name,
|
||||
// @ts-expect-error
|
||||
globalScopeBindings,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -156,9 +161,12 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
{ needsAdvancedPaths: true },
|
||||
);
|
||||
|
||||
// @ts-expect-error
|
||||
if (finalNodePath.type === 'ImportSpecifier') {
|
||||
// @ts-expect-error
|
||||
const importDeclNode = finalNodePath.parentPath.node;
|
||||
const source = importDeclNode.source.value;
|
||||
// @ts-expect-error
|
||||
const identifierName = finalNodePath.node.imported?.value || finalNodePath.node.local?.value;
|
||||
const currentFilePath = filePath;
|
||||
|
||||
|
|
@ -170,13 +178,14 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
);
|
||||
const filePathOrSrc = getFilePathOrExternalSource({
|
||||
rootPath: projectRootPath,
|
||||
localPath: rootFile.file,
|
||||
localPath: /** @type {PathRelativeFromProjectRoot} */ (rootFile.file),
|
||||
});
|
||||
|
||||
// TODO: allow resolving external project file paths
|
||||
if (!filePathOrSrc.startsWith('/')) {
|
||||
// So we have external project; smth like '@lion/input/x.js'
|
||||
return {
|
||||
// @ts-expect-error
|
||||
sourceNodePath: finalNodePath,
|
||||
sourceFragment: null,
|
||||
externalImportSource: filePathOrSrc,
|
||||
|
|
@ -184,17 +193,20 @@ export async function getSourceCodeFragmentOfDeclaration({
|
|||
}
|
||||
|
||||
return getSourceCodeFragmentOfDeclaration({
|
||||
filePath: filePathOrSrc,
|
||||
filePath: /** @type {PathFromSystemRoot} */ (filePathOrSrc),
|
||||
exportedIdentifier: rootFile.specifier,
|
||||
projectRootPath,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
// @ts-expect-error
|
||||
sourceNodePath: finalNodePath,
|
||||
sourceFragment: code.slice(
|
||||
finalNodePath.node?.span?.start - 1 - offset,
|
||||
finalNodePath.node?.span?.end - 1 - offset,
|
||||
// @ts-expect-error
|
||||
finalNodePath.node.span.start - 1 - offset,
|
||||
// @ts-expect-error
|
||||
finalNodePath.node.span.end - 1 - offset,
|
||||
),
|
||||
// sourceFragment: finalNodePath.node?.raw || finalNodePath.node?.value,
|
||||
externalImportSource: null,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { isBuiltin } from 'node:module';
|
||||
import { isBuiltin } from 'module';
|
||||
import path from 'path';
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
import { LogService } from '../core/LogService.js';
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ export function getPathFromNode(node) {
|
|||
* @returns {SwcPath}
|
||||
*/
|
||||
function createSwcPath(node, parent, stop, scope) {
|
||||
/** @type {SwcPath} */
|
||||
const swcPath = {
|
||||
node,
|
||||
parent,
|
||||
|
|
@ -78,9 +79,9 @@ function createSwcPath(node, parent, stop, scope) {
|
|||
// TODO: "pre-traverse" the missing scope parts instead via getter that adds refs and bindings for current scope
|
||||
scope,
|
||||
parentPath: parent ? getPathFromNode(parent) : null,
|
||||
get(/** @type {string} */ name) {
|
||||
const swcPathForNode = getPathFromNode(node[name]);
|
||||
if (node[name] && !swcPathForNode) {
|
||||
get(/** @type {string} */ id) {
|
||||
const swcPathForNode = getPathFromNode(node[id]);
|
||||
if (node[id] && !swcPathForNode) {
|
||||
// throw new Error(
|
||||
// `[swcTraverse]: Use {needsAdvancedPaths: true} to find path for node: ${node[name]}`,
|
||||
// );
|
||||
|
|
|
|||
|
|
@ -1,330 +0,0 @@
|
|||
import { expect } from 'chai';
|
||||
import { it } from 'mocha';
|
||||
import { providence } from '../../../src/program/providence.js';
|
||||
import { QueryService } from '../../../src/program/core/QueryService.js';
|
||||
import { setupAnalyzerTest } from '../../../test-helpers/setup-analyzer-test.js';
|
||||
import { mockProject, getEntry, getEntries } from '../../../test-helpers/mock-project-helpers.js';
|
||||
import FindExportsAnalyzer from '../../../src/program/analyzers/find-exports.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('../../../types/index.js').ProvidenceConfig} ProvidenceConfig
|
||||
*/
|
||||
|
||||
setupAnalyzerTest();
|
||||
|
||||
describe('Analyzer "find-exports"', async () => {
|
||||
const findExportsQueryConfig = await QueryService.getQueryConfigFromAnalyzer(FindExportsAnalyzer);
|
||||
|
||||
/** @type {Partial<ProvidenceConfig>} */
|
||||
const _providenceCfg = {
|
||||
targetProjectPaths: ['/fictional/project'], // defined in mockProject
|
||||
};
|
||||
|
||||
describe('Export notations', () => {
|
||||
it(`supports [export const x = 0] (named specifier)`, async () => {
|
||||
mockProject([`export const x = 0`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstResult = getEntry(queryResults[0]).result[0];
|
||||
|
||||
expect(firstResult.exportSpecifiers).to.eql(['x']);
|
||||
expect(firstResult.source).to.be.undefined;
|
||||
});
|
||||
|
||||
it(`supports [export default class X {}] (default export)`, async () => {
|
||||
mockProject([`export default class X {}`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstResult = getEntry(queryResults[0]).result[0];
|
||||
expect(firstResult.exportSpecifiers).to.eql(['[default]']);
|
||||
expect(firstResult.source).to.be.undefined;
|
||||
});
|
||||
|
||||
it(`supports [export default fn(){}] (default export)`, async () => {
|
||||
mockProject([`export default x => x * 3`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstResult = getEntry(queryResults[0]).result[0];
|
||||
|
||||
expect(firstResult.exportSpecifiers).to.eql(['[default]']);
|
||||
expect(firstResult.source).to.equal(undefined);
|
||||
});
|
||||
|
||||
it(`supports [export {default as x} from 'y'] (default re-export)`, async () => {
|
||||
mockProject({
|
||||
'./file-with-default-export.js': 'export default 1;',
|
||||
'./file-with-default-re-export.js':
|
||||
"export { default as namedExport } from './file-with-default-export.js';",
|
||||
});
|
||||
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstResult = getEntry(queryResults[0]).result[0];
|
||||
expect(firstResult).to.eql({
|
||||
exportSpecifiers: ['[default]'],
|
||||
source: undefined,
|
||||
rootFileMap: [
|
||||
{
|
||||
currentFileSpecifier: '[default]',
|
||||
rootFile: { file: '[current]', specifier: '[default]' },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const secondEntry = getEntry(queryResults[0], 1);
|
||||
expect(secondEntry.result[0]).to.eql({
|
||||
exportSpecifiers: ['namedExport'],
|
||||
source: './file-with-default-export.js',
|
||||
localMap: [{ exported: 'namedExport', local: '[default]' }],
|
||||
normalizedSource: './file-with-default-export.js',
|
||||
rootFileMap: [
|
||||
{
|
||||
currentFileSpecifier: 'namedExport',
|
||||
rootFile: { file: './file-with-default-export.js', specifier: '[default]' },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it(`supports [import {x} from 'y'; export default x] (named re-export as default)`, async () => {
|
||||
mockProject([`import {x} from 'y'; export default x;`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('[default]');
|
||||
expect(firstEntry.result[0].source).to.equal('y');
|
||||
});
|
||||
|
||||
it(`supports [import x from 'y'; export default x] (default re-export as default)`, async () => {
|
||||
mockProject([`import x from 'y'; export default x;`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('[default]');
|
||||
expect(firstEntry.result[0].source).to.equal('y');
|
||||
});
|
||||
|
||||
it(`supports [export { x } from 'my/source'] (re-export named specifier)`, async () => {
|
||||
mockProject([`export { x } from 'my/source'`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('x');
|
||||
expect(firstEntry.result[0].source).to.equal('my/source');
|
||||
});
|
||||
|
||||
it(`supports [export { x as y } from 'my/source'] (re-export renamed specifier)`, async () => {
|
||||
mockProject([`export { x as y } from 'my/source'`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('y');
|
||||
expect(firstEntry.result[0].source).to.equal('my/source');
|
||||
});
|
||||
|
||||
it(`supports [export styles from './styles.css' assert { type: "css" }] (import assertions)`, async () => {
|
||||
mockProject({
|
||||
'./styles.css': '.block { display:block; };',
|
||||
'./x.js': `export { styles as default } from './styles.css' assert { type: "css" };`,
|
||||
});
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('[default]');
|
||||
expect(firstEntry.result[0].source).to.equal('./styles.css');
|
||||
expect(firstEntry.result[0].rootFileMap[0]).to.eql({
|
||||
currentFileSpecifier: '[default]',
|
||||
rootFile: {
|
||||
file: './styles.css',
|
||||
specifier: '[default]',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`supports [import styles from './styles.css' assert { type: "css" }; export default styles;] (import assertions)`, async () => {
|
||||
mockProject({
|
||||
'./styles.css': '.block { display:block; };',
|
||||
'./x.js': `import styles from './styles.css' assert { type: "css" }; export default styles;`,
|
||||
});
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(1);
|
||||
expect(firstEntry.result[0].exportSpecifiers[0]).to.equal('[default]');
|
||||
expect(firstEntry.result[0].source).to.equal('./styles.css');
|
||||
expect(firstEntry.result[0].rootFileMap[0]).to.eql({
|
||||
currentFileSpecifier: '[default]',
|
||||
rootFile: {
|
||||
file: './styles.css',
|
||||
specifier: '[default]',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`stores meta info(local name) of renamed specifiers`, async () => {
|
||||
mockProject([`export { x as y } from 'my/source'`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
// This info will be relevant later to identify 'transitive' relations
|
||||
expect(firstEntry.result[0].localMap).to.eql([
|
||||
{
|
||||
local: 'x',
|
||||
exported: 'y',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it(`supports [export { x, y } from 'my/source'] (multiple re-exported named specifiers)`, async () => {
|
||||
mockProject([`export { x, y } from 'my/source'`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers.length).to.equal(2);
|
||||
expect(firstEntry.result[0].exportSpecifiers).to.eql(['x', 'y']);
|
||||
expect(firstEntry.result[0].source).to.equal('my/source');
|
||||
});
|
||||
|
||||
it(`stores rootFileMap of an exported Identifier`, async () => {
|
||||
mockProject({
|
||||
'./src/OriginalComp.js': `export class OriginalComp {}`,
|
||||
'./src/inbetween.js': `export { OriginalComp as InBetweenComp } from './OriginalComp.js'`,
|
||||
'./index.js': `export { InBetweenComp as MyComp } from './src/inbetween.js'`,
|
||||
});
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
const secondEntry = getEntry(queryResults[0], 1);
|
||||
const thirdEntry = getEntry(queryResults[0], 2);
|
||||
|
||||
expect(firstEntry.result[0].rootFileMap).to.eql([
|
||||
{
|
||||
currentFileSpecifier: 'MyComp', // this is the local name in the file we track from
|
||||
rootFile: {
|
||||
file: './src/OriginalComp.js', // the file containing declaration
|
||||
specifier: 'OriginalComp', // the specifier that was exported in file
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(secondEntry.result[0].rootFileMap).to.eql([
|
||||
{
|
||||
currentFileSpecifier: 'InBetweenComp',
|
||||
rootFile: {
|
||||
file: './src/OriginalComp.js',
|
||||
specifier: 'OriginalComp',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(thirdEntry.result[0].rootFileMap).to.eql([
|
||||
{
|
||||
currentFileSpecifier: 'OriginalComp',
|
||||
rootFile: {
|
||||
file: '[current]',
|
||||
specifier: 'OriginalComp',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it(`stores rootFileMap of an exported Identifier`, async () => {
|
||||
mockProject({
|
||||
'./src/reexport.js': `
|
||||
// a direct default import
|
||||
import RefDefault from 'exporting-ref-project';
|
||||
|
||||
export default RefDefault;
|
||||
`,
|
||||
'./index.js': `
|
||||
import ExtendRefDefault from './src/reexport.js';
|
||||
|
||||
export default ExtendRefDefault;
|
||||
`,
|
||||
});
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
|
||||
expect(firstEntry.result[0].rootFileMap).to.eql([
|
||||
{
|
||||
currentFileSpecifier: '[default]',
|
||||
rootFile: {
|
||||
file: 'exporting-ref-project',
|
||||
specifier: '[default]',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it(`correctly handles empty files`, async () => {
|
||||
// These can be encountered while scanning repos.. They should not break the code...
|
||||
mockProject([`// some comment here...`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
expect(firstEntry.result[0].exportSpecifiers).to.eql(['[file]']);
|
||||
expect(firstEntry.result[0].source).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Export variable types', () => {
|
||||
it(`classes`, async () => {
|
||||
mockProject([`export class X {}`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
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.undefined;
|
||||
});
|
||||
|
||||
it(`functions`, async () => {
|
||||
mockProject([`export function y() {}`]);
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const firstEntry = getEntry(queryResults[0]);
|
||||
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.undefined;
|
||||
});
|
||||
|
||||
// ...etc?
|
||||
// ...TODO: create custom hooks to store meta info about types etc.
|
||||
});
|
||||
|
||||
describe('Default post processing', () => {
|
||||
// onlyInternalSources: false,
|
||||
// keepOriginalSourcePaths: false,
|
||||
// filterSpecifier: null,
|
||||
});
|
||||
|
||||
describe('Options', () => {
|
||||
// TODO: Move to dashboard
|
||||
it.skip(`"metaConfig.categoryConfig"`, async () => {
|
||||
mockProject(
|
||||
[
|
||||
`export const foo = null`, // firstEntry
|
||||
`export const bar = null`, // secondEntry
|
||||
`export const baz = null`, // thirdEntry
|
||||
],
|
||||
{
|
||||
projectName: 'my-project',
|
||||
filePaths: ['./foo.js', './packages/bar/test/bar.test.js', './temp/baz.js'],
|
||||
},
|
||||
);
|
||||
|
||||
const findExportsCategoryQueryObj = await QueryService.getQueryConfigFromAnalyzer(
|
||||
'find-exports',
|
||||
{
|
||||
metaConfig: {
|
||||
categoryConfig: [
|
||||
{
|
||||
project: 'my-project',
|
||||
categories: {
|
||||
fooCategory: localFilePath => localFilePath.startsWith('./foo'),
|
||||
barCategory: localFilePath => localFilePath.startsWith('./packages/bar'),
|
||||
testCategory: localFilePath => localFilePath.includes('/test/'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const queryResult = queryResults[0];
|
||||
const [firstEntry, secondEntry, thirdEntry] = getEntries(queryResult);
|
||||
expect(firstEntry.meta.categories).to.eql(['fooCategory']);
|
||||
// not mutually exclusive...
|
||||
expect(secondEntry.meta.categories).to.eql(['barCategory', 'testCategory']);
|
||||
expect(thirdEntry.meta.categories).to.eql([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -301,23 +301,23 @@ describe('Analyzer "find-exports"', async () => {
|
|||
},
|
||||
);
|
||||
|
||||
const findExportsCategoryQueryObj = await QueryService.getQueryConfigFromAnalyzer(
|
||||
'find-exports',
|
||||
{
|
||||
metaConfig: {
|
||||
categoryConfig: [
|
||||
{
|
||||
project: 'my-project',
|
||||
categories: {
|
||||
fooCategory: localFilePath => localFilePath.startsWith('./foo'),
|
||||
barCategory: localFilePath => localFilePath.startsWith('./packages/bar'),
|
||||
testCategory: localFilePath => localFilePath.includes('/test/'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
// const findExportsCategoryQueryObj = await QueryService.getQueryConfigFromAnalyzer(
|
||||
// 'find-exports',
|
||||
// {
|
||||
// metaConfig: {
|
||||
// categoryConfig: [
|
||||
// {
|
||||
// project: 'my-project',
|
||||
// categories: {
|
||||
// fooCategory: localFilePath => localFilePath.startsWith('./foo'),
|
||||
// barCategory: localFilePath => localFilePath.startsWith('./packages/bar'),
|
||||
// testCategory: localFilePath => localFilePath.includes('/test/'),
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
|
||||
const queryResults = await providence(findExportsQueryConfig, _providenceCfg);
|
||||
const queryResult = queryResults[0];
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
"outDir": "./dist-types",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": ["src", "types"],
|
||||
"include": ["types"],
|
||||
"exclude": ["dist-types"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export type SwcScope = {
|
||||
id: number;
|
||||
parentScope?: Scope;
|
||||
bindings: { [key: string]: Binding };
|
||||
bindings: { [key: string]: SwcBinding };
|
||||
path: SwcPath | null;
|
||||
_pendingRefsWithoutBinding: SwcNode[];
|
||||
_isIsolatedBlockStatement: boolean;
|
||||
|
|
@ -12,15 +12,17 @@ export type SwcBinding = {
|
|||
identifier: SwcNode;
|
||||
// kind: string;
|
||||
refs: SwcNode[];
|
||||
path: SwcPath;
|
||||
path: SwcPath | null | undefined;
|
||||
};
|
||||
|
||||
export type SwcPath = {
|
||||
node: SwcNode;
|
||||
parent: SwcNode;
|
||||
stop: function;
|
||||
scope: SwcScope;
|
||||
parentPath: SwcPath;
|
||||
scope: SwcScope | undefined;
|
||||
parentPath: SwcPath | null | undefined;
|
||||
get: (id: string) => SwcPath | undefined;
|
||||
type: string;
|
||||
};
|
||||
|
||||
type SwcVisitorFn = (swcPath: SwcPath) => void;
|
||||
|
|
|
|||
Loading…
Reference in a new issue