Merge pull request #1558 from ing-bank/fix/dedupeMatchImportsResults
Fix/dedupe match imports results
This commit is contained in:
commit
f282091750
12 changed files with 105 additions and 49 deletions
7
.changeset/kind-zoos-bathe.md
Normal file
7
.changeset/kind-zoos-bathe.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
'providence-analytics': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
- correctly dedupe match-imports exportSpecifiers
|
||||||
|
- windows compatibility
|
||||||
|
- example conf file esm compatible
|
||||||
5
.changeset/polite-hairs-shave.md
Normal file
5
.changeset/polite-hairs-shave.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'rocket-preset-extend-lion-docs': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
windows compatibility
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dashboard": "node ./dashboard/src/server.js --serve-from-package-root",
|
"dashboard": "node ./dashboard/src/server.js --serve-from-package-root",
|
||||||
"match-lion-imports": "npm run providence analyze match-imports --search-target-collection @lion-targets --reference-collection @lion-references",
|
"match-lion-imports": "npm run providence analyze match-imports --search-target-collection @lion-targets --reference-collection @lion-references",
|
||||||
"providence": "node --max-old-space-size=8192 ./src/cli/index.js",
|
"providence": "node --max-old-space-size=8192 ./src/cli/index.mjs",
|
||||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||||
"prepublishOnly": "npm run publish-docs",
|
"prepublishOnly": "npm run publish-docs",
|
||||||
"test:node": "mocha './test-node/**/*.test.js'",
|
"test:node": "mocha './test-node/**/*.test.js'",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import pathLib from 'path';
|
import pathLib, { dirname } from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
// This file is read by dashboard and cli and needs to be present under process.cwd()
|
// This file is read by dashboard and cli and needs to be present under process.cwd()
|
||||||
// It mainly serves as an example and it allows to run the dashboard locally
|
// It mainly serves as an example and it allows to run the dashboard locally
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,12 @@ async function appendProjectDependencyPaths(rootPaths, matchPattern, modes = ['n
|
||||||
let matchFn;
|
let matchFn;
|
||||||
if (matchPattern) {
|
if (matchPattern) {
|
||||||
if (matchPattern.startsWith('/') && matchPattern.endsWith('/')) {
|
if (matchPattern.startsWith('/') && matchPattern.endsWith('/')) {
|
||||||
matchFn = (_, d) => new RegExp(matchPattern.slice(1, -1)).test(d);
|
matchFn = (_, d) => {
|
||||||
|
const reString = matchPattern.slice(1, -1);
|
||||||
|
const result = new RegExp(reString).test(d);
|
||||||
|
LogService.debug(`[appendProjectDependencyPaths]: /${reString}/.test(${d} => ${result})`);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
LogService.error(
|
LogService.error(
|
||||||
`[appendProjectDependencyPaths] Please provide a matchPattern enclosed by '/'. Found: ${matchPattern}`,
|
`[appendProjectDependencyPaths] Please provide a matchPattern enclosed by '/'. Found: ${matchPattern}`,
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ const { LogService } = require('../program/services/LogService.js');
|
||||||
const JsdocCommentParser = require('../program/utils/jsdoc-comment-parser.js');
|
const JsdocCommentParser = require('../program/utils/jsdoc-comment-parser.js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desc extracts name, defaultValue, optional, type, desc from JsdocCommentParser.parse method
|
* Extracts name, defaultValue, optional, type, desc from JsdocCommentParser.parse method
|
||||||
* result
|
* result
|
||||||
* @param {array} jsdoc
|
* @param {string[]} jsdoc
|
||||||
* @returns {object}
|
* @returns {{ name:string, defaultValue:string, optional:boolean, type:string, desc:string }}
|
||||||
*/
|
*/
|
||||||
function getPropsFromParsedJsDoc(jsdoc) {
|
function getPropsFromParsedJsDoc(jsdoc) {
|
||||||
const jsdocProps = jsdoc.filter(p => p.tagName === '@property');
|
const jsdocProps = jsdoc.filter(p => p.tagName === '@property');
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,9 @@ async function matchImportsPostprocess(exportsAnalyzerResult, importsAnalyzerRes
|
||||||
* Add it to the results array
|
* Add it to the results array
|
||||||
*/
|
*/
|
||||||
const id = `${exportEntry.specifier}::${exportEntry.file}::${exportsAnalyzerResult.analyzerMeta.targetProject.name}`;
|
const id = `${exportEntry.specifier}::${exportEntry.file}::${exportsAnalyzerResult.analyzerMeta.targetProject.name}`;
|
||||||
const resultForCurrentExport = conciseResultsArray.find(entry => entry.id === id);
|
const resultForCurrentExport = conciseResultsArray.find(
|
||||||
|
entry => entry.exportSpecifier && entry.exportSpecifier.id === id,
|
||||||
|
);
|
||||||
if (resultForCurrentExport) {
|
if (resultForCurrentExport) {
|
||||||
resultForCurrentExport.importProjectFiles.push(importEntry.file);
|
resultForCurrentExport.importProjectFiles.push(importEntry.file);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
const pathLib = require('path');
|
const pathLib = require('path');
|
||||||
const { nodeResolve } = require('@rollup/plugin-node-resolve');
|
const { nodeResolve } = require('@rollup/plugin-node-resolve');
|
||||||
const { LogService } = require('../services/LogService.js');
|
const { LogService } = require('../services/LogService.js');
|
||||||
|
const { memoizeAsync } = require('./memoize.js');
|
||||||
|
const { toPosixPath } = require('./to-posix-path.js');
|
||||||
|
|
||||||
const fakePluginContext = {
|
const fakePluginContext = {
|
||||||
meta: {
|
meta: {
|
||||||
|
|
@ -27,15 +29,6 @@ const fakePluginContext = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Based on importee (in a statement "import {x} from '@lion/core'", "@lion/core" is an
|
|
||||||
* importee), which can be a bare module specifier, a filename without extension, or a folder
|
|
||||||
* name without an extension.
|
|
||||||
* @param {SpecifierSource} importee source like '@lion/core' or '../helpers/index.js'
|
|
||||||
* @param {PathFromSystemRoot} importer importing file, like '/my/project/importing-file.js'
|
|
||||||
* @param {{customResolveOptions?: {preserveSymlinks:boolean}}} [opts] nodeResolve options
|
|
||||||
* @returns {Promise<PathFromSystemRoot|null>} the resolved file system path, like '/my/project/node_modules/@lion/core/index.js'
|
|
||||||
*/
|
|
||||||
async function resolveImportPath(importee, importer, opts = {}) {
|
async function resolveImportPath(importee, importer, opts = {}) {
|
||||||
const rollupResolve = nodeResolve({
|
const rollupResolve = nodeResolve({
|
||||||
rootDir: pathLib.dirname(importer),
|
rootDir: pathLib.dirname(importer),
|
||||||
|
|
@ -59,7 +52,18 @@ async function resolveImportPath(importee, importer, opts = {}) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return result.id;
|
return toPosixPath(result.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { resolveImportPath };
|
/**
|
||||||
|
* Based on importee (in a statement "import {x} from '@lion/core'", "@lion/core" is an
|
||||||
|
* importee), which can be a bare module specifier, a filename without extension, or a folder
|
||||||
|
* name without an extension.
|
||||||
|
* @param {SpecifierSource} importee source like '@lion/core' or '../helpers/index.js'
|
||||||
|
* @param {PathFromSystemRoot} importer importing file, like '/my/project/importing-file.js'
|
||||||
|
* @param {{customResolveOptions?: {preserveSymlinks:boolean}}} [opts] nodeResolve options
|
||||||
|
* @returns {Promise<PathFromSystemRoot|null>} the resolved file system path, like '/my/project/node_modules/@lion/core/index.js'
|
||||||
|
*/
|
||||||
|
const resolveImportPathMemoized = memoizeAsync(resolveImportPath);
|
||||||
|
|
||||||
|
module.exports = { resolveImportPath: resolveImportPathMemoized };
|
||||||
|
|
|
||||||
|
|
@ -92,57 +92,41 @@
|
||||||
{
|
{
|
||||||
"name": "getterSetter",
|
"name": "getterSetter",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"kind": [
|
"kind": ["get", "set"]
|
||||||
"get",
|
|
||||||
"set"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "staticGetterSetter",
|
"name": "staticGetterSetter",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"static": true,
|
"static": true,
|
||||||
"kind": [
|
"kind": ["get", "set"]
|
||||||
"get",
|
|
||||||
"set"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "attributes",
|
"name": "attributes",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"static": true,
|
"static": true,
|
||||||
"kind": [
|
"kind": ["get"]
|
||||||
"get"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "styles",
|
"name": "styles",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"static": true,
|
"static": true,
|
||||||
"kind": [
|
"kind": ["get"]
|
||||||
"get"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "updateComplete",
|
"name": "updateComplete",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"kind": [
|
"kind": ["get"]
|
||||||
"get"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "localizeNamespaces",
|
"name": "localizeNamespaces",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"static": true,
|
"static": true,
|
||||||
"kind": [
|
"kind": ["get"]
|
||||||
"get"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "slots",
|
"name": "slots",
|
||||||
"accessType": "public",
|
"accessType": "public",
|
||||||
"kind": [
|
"kind": ["get"]
|
||||||
"get"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"methods": [
|
"methods": [
|
||||||
|
|
@ -180,7 +164,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "requestUpdate",
|
"name": "requestUpdate",
|
||||||
"accessType": "protected"
|
"accessType": "public"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "createRenderRoot",
|
"name": "createRenderRoot",
|
||||||
|
|
|
||||||
|
|
@ -484,8 +484,18 @@ describe('CLI helpers', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows a regex filter', async () => {
|
it('allows a regex filter', async () => {
|
||||||
const result = await appendProjectDependencyPaths(['/mocked/path/example-project'], '/b$/');
|
const result = await appendProjectDependencyPaths(
|
||||||
|
['/mocked/path/example-project'],
|
||||||
|
'/^dependency-/',
|
||||||
|
);
|
||||||
expect(result).to.eql([
|
expect(result).to.eql([
|
||||||
|
'/mocked/path/example-project/node_modules/dependency-a',
|
||||||
|
'/mocked/path/example-project/bower_components/dependency-b',
|
||||||
|
'/mocked/path/example-project',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result2 = await appendProjectDependencyPaths(['/mocked/path/example-project'], '/b$/');
|
||||||
|
expect(result2).to.eql([
|
||||||
'/mocked/path/example-project/bower_components/dependency-b',
|
'/mocked/path/example-project/bower_components/dependency-b',
|
||||||
'/mocked/path/example-project',
|
'/mocked/path/example-project',
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -441,6 +441,32 @@ describe('Analyzer "match-imports"', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`correctly merges/dedupes double found exports`, async () => {
|
||||||
|
const refProject = {
|
||||||
|
path: '/target/node_modules/ref',
|
||||||
|
name: 'ref',
|
||||||
|
files: [{ file: './index.js', code: `export default function x() {};` }],
|
||||||
|
};
|
||||||
|
const targetProject = {
|
||||||
|
path: '/target',
|
||||||
|
name: 'target',
|
||||||
|
files: [
|
||||||
|
{ file: './importDefault1.js', code: `import myFn1 from 'ref/index.js';` },
|
||||||
|
{ file: './importDefault2.js', code: `import myFn2 from 'ref/index.js';` },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
mockTargetAndReferenceProject(targetProject, refProject);
|
||||||
|
await providence(matchImportsQueryConfig, {
|
||||||
|
targetProjectPaths: [targetProject.path],
|
||||||
|
referenceProjectPaths: [refProject.path],
|
||||||
|
});
|
||||||
|
const queryResult = queryResults[0];
|
||||||
|
expect(queryResult.queryOutput[0].exportSpecifier.name).to.equal('[default]');
|
||||||
|
expect(queryResult.queryOutput[0].matchesPerProject).to.eql([
|
||||||
|
{ files: ['./importDefault1.js', './importDefault2.js'], project: 'target' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
describe('Inside small example project', () => {
|
describe('Inside small example project', () => {
|
||||||
it(`produces a list of all matches, sorted by project`, async () => {
|
it(`produces a list of all matches, sorted by project`, async () => {
|
||||||
mockTargetAndReferenceProject(searchTargetProject, referenceProject);
|
mockTargetAndReferenceProject(searchTargetProject, referenceProject);
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,26 @@ import visit from 'unist-util-visit';
|
||||||
|
|
||||||
/** @typedef {Node & UrlProperty} UrlNode */
|
/** @typedef {Node & UrlProperty} UrlNode */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} pathStr C:\Example\path/like/this
|
||||||
|
* @returns {string} /Example/path/like/this
|
||||||
|
*/
|
||||||
|
function toPosixPath(pathStr) {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return pathStr.replace(/^.:/, '').replace(/\\/g, '/');
|
||||||
|
}
|
||||||
|
return pathStr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} opts
|
* @param {object} opts
|
||||||
* @param {string} opts.gitHubUrl
|
* @param {string} opts.gitHubUrl
|
||||||
* @param {object} opts.page
|
* @param {{inputPath:string}} opts.page
|
||||||
* @param {string} opts.page.inputPath
|
|
||||||
* @param {string} opts.rootDir
|
* @param {string} opts.rootDir
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) {
|
export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) {
|
||||||
|
const inputPath = toPosixPath(page.inputPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {UrlNode} node
|
* @param {UrlNode} node
|
||||||
*/
|
*/
|
||||||
|
|
@ -34,10 +45,9 @@ export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) {
|
||||||
urlParts.shift();
|
urlParts.shift();
|
||||||
urlParts.shift();
|
urlParts.shift();
|
||||||
const fullUrlPath = path.join(rootDir, urlParts.join('/'));
|
const fullUrlPath = path.join(rootDir, urlParts.join('/'));
|
||||||
const fullInputPath =
|
const fullInputPath = inputPath[0] === '/' ? inputPath : path.join(rootDir, inputPath);
|
||||||
page.inputPath[0] === '/' ? page.inputPath : path.join(rootDir, page.inputPath);
|
|
||||||
const newPath = path.relative(path.dirname(fullInputPath), fullUrlPath);
|
const newPath = path.relative(path.dirname(fullInputPath), fullUrlPath);
|
||||||
node.url = newPath;
|
node.url = toPosixPath(newPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue