From 7039f54277b1791e99b4f625198dfba2dbf6fbe6 Mon Sep 17 00:00:00 2001 From: Kim <1191340528@qq.com> Date: Wed, 3 Aug 2022 17:53:30 +0800 Subject: [PATCH] feat(findExports): use acorn tokenizer to filter false positive exports (#56) --- package.json | 1 + pnpm-lock.yaml | 223 +------------------------------------------ src/analyze.ts | 56 +++++++++-- test/exports.test.ts | 75 +++++++++++++-- 4 files changed, 122 insertions(+), 233 deletions(-) diff --git a/package.json b/package.json index e7451db..f8291d7 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "test": "pnpm lint && vitest run" }, "dependencies": { + "acorn": "^8.8.0", "pathe": "^0.3.3", "pkg-types": "^0.3.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86b1033..47d7375 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,6 +3,7 @@ lockfileVersion: 5.4 specifiers: '@nuxtjs/eslint-config-typescript': latest '@types/node': latest + acorn: ^8.8.0 c8: latest eslint: latest jiti: latest @@ -13,6 +14,7 @@ specifiers: vitest: latest dependencies: + acorn: 8.8.0 pathe: 0.3.3 pkg-types: 0.3.3 @@ -640,7 +642,6 @@ packages: resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /add-stream/1.0.0: resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} @@ -1294,15 +1295,6 @@ packages: is-symbol: 1.0.4 dev: true - /esbuild-android-64/0.14.44: - resolution: {integrity: sha512-dFPHBXmx385zuJULAD/Cmq/LyPRXiAWbf9ylZtY0wJ8iVyWfKYaCYxeJx8OAZUuj46ZwNa7MzW2GBAQLOeiemg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - /esbuild-android-64/0.14.53: resolution: {integrity: sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==} engines: {node: '>=12'} @@ -1312,15 +1304,6 @@ packages: dev: true optional: true - /esbuild-android-arm64/0.14.44: - resolution: {integrity: sha512-qqaqqyxHXjZ/0ddKU3I3Nb7lAvVM69ELMhb8+91FyomAUmQPlHtxe+TTiWxXGHE72XEzcgTEGq4VauqLNkN22g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - /esbuild-android-arm64/0.14.53: resolution: {integrity: sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==} engines: {node: '>=12'} @@ -1330,15 +1313,6 @@ packages: dev: true optional: true - /esbuild-darwin-64/0.14.44: - resolution: {integrity: sha512-RBmtGKGY06+AW6IOJ1LE/dEeF7HH34C1/Ces9FSitU4bIbIpL4KEuQpTFoxwb4ry5s2hyw7vbPhhtyOd18FH9g==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /esbuild-darwin-64/0.14.53: resolution: {integrity: sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==} engines: {node: '>=12'} @@ -1348,15 +1322,6 @@ packages: dev: true optional: true - /esbuild-darwin-arm64/0.14.44: - resolution: {integrity: sha512-Bmhx5Cfo4Hdb7WyyyDupTB8HPmnFZ8baLfPlzLdYvF6OzsIbV+CY+m/AWf0OQvY40BlkzCLJ/7Lfwbb71Tngmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /esbuild-darwin-arm64/0.14.53: resolution: {integrity: sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==} engines: {node: '>=12'} @@ -1366,15 +1331,6 @@ packages: dev: true optional: true - /esbuild-freebsd-64/0.14.44: - resolution: {integrity: sha512-O4HpWa5ZgxbNPQTF7URicLzYa+TidGlmGT/RAC3GjbGEQQYkd0R1Slyh69Yrmb2qmcOcPAgWHbNo1UhK4WmZ4w==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /esbuild-freebsd-64/0.14.53: resolution: {integrity: sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==} engines: {node: '>=12'} @@ -1384,15 +1340,6 @@ packages: dev: true optional: true - /esbuild-freebsd-arm64/0.14.44: - resolution: {integrity: sha512-f0/jkAKccnDY7mg1F9l/AMzEm+VXWXK6c3IrOEmd13jyKfpTZKTIlt+yI04THPDCDZTzXHTRUBLozqp+m8Mg5Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /esbuild-freebsd-arm64/0.14.53: resolution: {integrity: sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==} engines: {node: '>=12'} @@ -1402,15 +1349,6 @@ packages: dev: true optional: true - /esbuild-linux-32/0.14.44: - resolution: {integrity: sha512-WSIhzLldMR7YUoEL7Ix319tC+NFmW9Pu7NgFWxUfOXeWsT0Wg484hm6bNgs7+oY2pGzg715y/Wrqi1uNOMmZJw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-32/0.14.53: resolution: {integrity: sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==} engines: {node: '>=12'} @@ -1420,15 +1358,6 @@ packages: dev: true optional: true - /esbuild-linux-64/0.14.44: - resolution: {integrity: sha512-zgscTrCMcRZRIsVugqBTP/B5lPLNchBlWjQ8sQq2Epnv+UDtYKgXEq1ctWAmibZNy2E9QRCItKMeIEqeTUT5kA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-64/0.14.53: resolution: {integrity: sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==} engines: {node: '>=12'} @@ -1438,15 +1367,6 @@ packages: dev: true optional: true - /esbuild-linux-arm/0.14.44: - resolution: {integrity: sha512-laPBPwGfsbBxGw6F6jnqic2CPXLyC1bPrmnSOeJ9oEnx1rcKkizd4HWCRUc0xv+l4z/USRfx/sEfYlWSLeqoJQ==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-arm/0.14.53: resolution: {integrity: sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==} engines: {node: '>=12'} @@ -1456,15 +1376,6 @@ packages: dev: true optional: true - /esbuild-linux-arm64/0.14.44: - resolution: {integrity: sha512-H0H/2/wgiScTwBve/JR8/o+Zhabx5KPk8T2mkYZFKQGl1hpUgC+AOmRyqy/Js3p66Wim4F4Akv3I3sJA1sKg0w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-arm64/0.14.53: resolution: {integrity: sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==} engines: {node: '>=12'} @@ -1474,15 +1385,6 @@ packages: dev: true optional: true - /esbuild-linux-mips64le/0.14.44: - resolution: {integrity: sha512-ri3Okw0aleYy7o5n9zlIq+FCtq3tcMlctN6X1H1ucILjBJuH8pan2trJPKWeb8ppntFvE28I9eEXhwkWh6wYKg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-mips64le/0.14.53: resolution: {integrity: sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==} engines: {node: '>=12'} @@ -1492,15 +1394,6 @@ packages: dev: true optional: true - /esbuild-linux-ppc64le/0.14.44: - resolution: {integrity: sha512-96TqL/MvFRuIVXz+GtCIXzRQ43ZwEk4XTn0RWUNJduXXMDQ/V1iOV28U6x6Oe3NesK4xkoKSaK2+F3VHcU8ZrA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-ppc64le/0.14.53: resolution: {integrity: sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==} engines: {node: '>=12'} @@ -1510,15 +1403,6 @@ packages: dev: true optional: true - /esbuild-linux-riscv64/0.14.44: - resolution: {integrity: sha512-rrK9qEp2M8dhilsPn4T9gxUsAumkITc1kqYbpyNMr9EWo+J5ZBj04n3GYldULrcCw4ZCHAJ+qPjqr8b6kG2inA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-riscv64/0.14.53: resolution: {integrity: sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==} engines: {node: '>=12'} @@ -1528,15 +1412,6 @@ packages: dev: true optional: true - /esbuild-linux-s390x/0.14.44: - resolution: {integrity: sha512-2YmTm9BrW5aUwBSe8wIEARd9EcnOQmkHp4+IVaO09Ez/C5T866x+ABzhG0bwx0b+QRo9q97CRMaQx2Ngb6/hfw==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - /esbuild-linux-s390x/0.14.53: resolution: {integrity: sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==} engines: {node: '>=12'} @@ -1546,15 +1421,6 @@ packages: dev: true optional: true - /esbuild-netbsd-64/0.14.44: - resolution: {integrity: sha512-zypdzPmZTCqYS30WHxbcvtC0E6e/ECvl4WueUdbdWhs2dfWJt5RtCBME664EpTznixR3lSN1MQ2NhwQF8MQryw==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - /esbuild-netbsd-64/0.14.53: resolution: {integrity: sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==} engines: {node: '>=12'} @@ -1564,15 +1430,6 @@ packages: dev: true optional: true - /esbuild-openbsd-64/0.14.44: - resolution: {integrity: sha512-8J43ab9ByYl7KteC03HGQjr2HY1ge7sN04lFnwMFWYk2NCn8IuaeeThvLeNjzOYhyT3I6K8puJP0uVXUu+D1xw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - /esbuild-openbsd-64/0.14.53: resolution: {integrity: sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==} engines: {node: '>=12'} @@ -1582,15 +1439,6 @@ packages: dev: true optional: true - /esbuild-sunos-64/0.14.44: - resolution: {integrity: sha512-OH1/09CGUJwffA+HNM6mqPkSIyHVC3ZnURU/4CCIx7IqWUBn1Sh1HRLQC8/TWNgcs0/1u7ygnc2pgf/AHZJ/Ow==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - /esbuild-sunos-64/0.14.53: resolution: {integrity: sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==} engines: {node: '>=12'} @@ -1600,15 +1448,6 @@ packages: dev: true optional: true - /esbuild-windows-32/0.14.44: - resolution: {integrity: sha512-mCAOL9/rRqwfOfxTu2sjq/eAIs7eAXGiU6sPBnowggI7QS953Iq6o3/uDu010LwfN7zr18c/lEj6/PTwwTB3AA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - /esbuild-windows-32/0.14.53: resolution: {integrity: sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==} engines: {node: '>=12'} @@ -1618,15 +1457,6 @@ packages: dev: true optional: true - /esbuild-windows-64/0.14.44: - resolution: {integrity: sha512-AG6BH3+YG0s2Q/IfB1cm68FdyFnoE1P+GFbmgFO3tA4UIP8+BKsmKGGZ5I3+ZjcnzOwvT74bQRVrfnQow2KO5Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /esbuild-windows-64/0.14.53: resolution: {integrity: sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==} engines: {node: '>=12'} @@ -1636,15 +1466,6 @@ packages: dev: true optional: true - /esbuild-windows-arm64/0.14.44: - resolution: {integrity: sha512-ygYPfYE5By4Sd6szsNr10B0RtWVNOSGmZABSaj4YQBLqh9b9i45VAjVWa8tyIy+UAbKF7WGwybi2wTbSVliO8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /esbuild-windows-arm64/0.14.53: resolution: {integrity: sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==} engines: {node: '>=12'} @@ -1654,34 +1475,6 @@ packages: dev: true optional: true - /esbuild/0.14.44: - resolution: {integrity: sha512-Rn+lRRfj60r/3svI6NgAVnetzp3vMOj17BThuhshSj/gS1LR03xrjkDYyfPmrYG/0c3D68rC6FNYMQ3yRbiXeQ==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - esbuild-android-64: 0.14.44 - esbuild-android-arm64: 0.14.44 - esbuild-darwin-64: 0.14.44 - esbuild-darwin-arm64: 0.14.44 - esbuild-freebsd-64: 0.14.44 - esbuild-freebsd-arm64: 0.14.44 - esbuild-linux-32: 0.14.44 - esbuild-linux-64: 0.14.44 - esbuild-linux-arm: 0.14.44 - esbuild-linux-arm64: 0.14.44 - esbuild-linux-mips64le: 0.14.44 - esbuild-linux-ppc64le: 0.14.44 - esbuild-linux-riscv64: 0.14.44 - esbuild-linux-s390x: 0.14.44 - esbuild-netbsd-64: 0.14.44 - esbuild-openbsd-64: 0.14.44 - esbuild-sunos-64: 0.14.44 - esbuild-windows-32: 0.14.44 - esbuild-windows-64: 0.14.44 - esbuild-windows-arm64: 0.14.44 - dev: true - /esbuild/0.14.53: resolution: {integrity: sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==} engines: {node: '>=12'} @@ -3360,14 +3153,6 @@ packages: - supports-color dev: true - /rollup/2.70.1: - resolution: {integrity: sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==} - engines: {node: '>=10.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 - dev: true - /rollup/2.77.2: resolution: {integrity: sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==} engines: {node: '>=10.0.0'} @@ -3843,10 +3628,10 @@ packages: stylus: optional: true dependencies: - esbuild: 0.14.44 + esbuild: 0.14.53 postcss: 8.4.14 resolve: 1.22.0 - rollup: 2.70.1 + rollup: 2.77.2 optionalDependencies: fsevents: 2.3.2 dev: true diff --git a/src/analyze.ts b/src/analyze.ts index b4b05e1..ce5fbf6 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -1,3 +1,4 @@ +import { tokenizer } from 'acorn' import { matchAll } from './_utils' export interface ESMImport { @@ -94,23 +95,22 @@ export function parseStaticImport (matched: StaticImport): ParsedStaticImport { export function findExports (code: string): ESMExport[] { // Find declarations like export const foo = 'bar' - const declaredExports = matchAll(EXPORT_DECAL_RE, code, { type: 'declaration' }) + const declaredExports: DeclarationExport[] = matchAll(EXPORT_DECAL_RE, code, { type: 'declaration' }) // Find named exports - const namedExports = matchAll(EXPORT_NAMED_RE, code, { type: 'named' }) + const namedExports: NamedExport[] = matchAll(EXPORT_NAMED_RE, code, { type: 'named' }) for (const namedExport of namedExports) { namedExport.names = namedExport.exports.split(/\s*,\s*/g).map(name => name.replace(/^.*?\sas\s/, '').trim()) } // Find export default - const defaultExport = matchAll(EXPORT_DEFAULT_RE, code, { type: 'default', name: 'default' }) + const defaultExport: DefaultExport[] = matchAll(EXPORT_DEFAULT_RE, code, { type: 'default', name: 'default' }) // Find export star - const starExports = matchAll(EXPORT_STAR_RE, code, { type: 'star' }) + const starExports: ESMExport[] = matchAll(EXPORT_STAR_RE, code, { type: 'star' }) // Merge and normalize exports - const exports = [].concat(declaredExports, namedExports, defaultExport, starExports) - + const exports: ESMExport[] = [].concat(declaredExports, namedExports, defaultExport, starExports) for (const exp of exports) { if (!exp.name && exp.names && exp.names.length === 1) { exp.name = exp.names[0] @@ -124,9 +124,53 @@ export function findExports (code: string): ESMExport[] { } } + // Return early when there is no export statement + if (!exports.length) { + return [] + } + const exportLocations = _getExportLocations(code) + if (!exportLocations.length) { + return [] + } + return exports.filter((exp, index, exports) => { + // Filter false positive export matches + if (!_isExportStatement(exportLocations, exp)) { + return false + } // Prevent multiple exports of same function, only keep latest iteration of signatures const nextExport = exports[index + 1] return !nextExport || exp.type !== nextExport.type || !exp.name || exp.name !== nextExport.name }) } + +// --- Internal --- + +interface TokenLocation { + start: number + end: number +} + +function _isExportStatement (exportsLocation: TokenLocation[], exp: ESMExport) { + return exportsLocation.some(location => exp.start <= location.start && exp.end >= location.end) +} + +function _getExportLocations (code: string) { + const tokens = tokenizer(code, { + ecmaVersion: 'latest', + sourceType: 'module', + allowHashBang: true, + allowAwaitOutsideFunction: true, + allowImportExportEverywhere: true + }) + const locations: TokenLocation[] = [] + for (const token of tokens) { + if (token.type.label === 'export') { + locations.push({ + start: token.start, + end: token.end + }) + } + } + return locations +} diff --git a/test/exports.test.ts b/test/exports.test.ts index 879dfa8..8e48ef9 100644 --- a/test/exports.test.ts +++ b/test/exports.test.ts @@ -39,20 +39,79 @@ describe('findExports', () => { } it('handles multiple exports', () => { const matches = findExports(` - export { useTestMe1 } from "@/test/foo1"; - export { useTestMe2 } from "@/test/foo2"; - export { useTestMe3 } from "@/test/foo3"; - `) + export { useTestMe1 } from "@/test/foo1"; + export { useTestMe2 } from "@/test/foo2"; + export { useTestMe3 } from "@/test/foo3"; + `) expect(matches.length).to.eql(3) }) it('works with multiple named exports', () => { const code = ` -export { foo } from 'foo1'; -export { bar } from 'foo2'; -export { foobar } from 'foo2'; -` + export { foo } from 'foo1'; + export { bar } from 'foo2'; + export { foobar } from 'foo2'; + ` const matches = findExports(code) expect(matches).to.have.lengthOf(3) }) + + it('the commented out export should be filtered out', () => { + const code = ` + // export { foo } from 'foo1'; + // exports default 'foo'; + // export { useB, _useC as useC }; + // export function useA () { return 'a' } + // export { default } from "./other" + // export async function foo () {} + // export { foo as default } + //export * from "./other" + //export * as foo from "./other" + + /** + * export const a = 123 + * export { foo } from 'foo1'; + * exports default 'foo' + * export function useA () { return 'a' } + * export { useB, _useC as useC }; + *export { default } from "./other" + *export async function foo () {} + * export { foo as default } + * export * from "./other" + export * as foo from "./other" + */ + export { bar } from 'foo2'; + export { foobar } from 'foo2'; + ` + const matches = findExports(code) + expect(matches).to.have.lengthOf(2) + }) + it('export in string', () => { + const tests: string[] = [ + 'export function useA () { return \'a\' }', + 'export const useD = () => { return \'d\' }', + 'export { useB, _useC as useC }', + 'export default foo', + 'export { default } from "./other"', + 'export async function foo ()', + 'export const $foo = () => {}', + 'export { foo as default }', + 'export * from "./other"', + 'export * as foo from "./other"' + ] + const code = tests.reduce((codeStr, statement, idx) => { + codeStr = ` + ${codeStr} + const test${idx}0 = "${statement}" + const test${idx}1 = \` + test1 + ${statement} + test2 + \` + ` + return codeStr + }, 'export { bar } from \'foo2\'; \n export { foobar } from \'foo2\';') + const matches = findExports(code) + expect(matches).to.have.lengthOf(2) + }) })