Skip to content

Commit

Permalink
Add .js extension support with es6 example (#255)
Browse files Browse the repository at this point in the history
* Add es6 example

* Add more examples that import js

* Allow for import of x.js

* Refactor

* Add more extensions
  • Loading branch information
mrseanryan authored Dec 26, 2022
1 parent 12972a1 commit 6e506ae
Show file tree
Hide file tree
Showing 21 changed files with 129 additions and 19 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@

### Added

Allow for importing of 'x.js' files as opposed to simply 'x'. This aims towards supporting es6 and higher modules as opposed to CommonJS.

## [8.0.5] - 10 Dec 2022

### Changed
Expand Down
3 changes: 3 additions & 0 deletions example/simple-es5-js/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import inc from './math.js';

console.log('two', inc(1));
1 change: 1 addition & 0 deletions example/simple-es5-js/execute.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx tsc && node ./lib/app.js
6 changes: 6 additions & 0 deletions example/simple-es5-js/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function unused1(x: number) { return x + 1; }

// ts-unused-exports:disable-next-line
export function unusedButDisabled(x: number) { return x + 2; }

export default (x: number) => x + 1;
11 changes: 11 additions & 0 deletions example/simple-es5-js/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions":
{
"target": "ES5",
"module": "commonjs",
"noImplicitAny": true,
"strictNullChecks": true,
"outDir": "./lib",
},
"include": ["./**/*.ts"],
}
1 change: 1 addition & 0 deletions example/simple-es5-js/unused.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function unused(x: number) { return x + 2; }
3 changes: 3 additions & 0 deletions example/simple-es6/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as inc from './math.js';

console.log('two', inc.default(1));
1 change: 1 addition & 0 deletions example/simple-es6/execute.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx tsc && node ./lib/app.js
6 changes: 6 additions & 0 deletions example/simple-es6/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function unused1(x: number) { return x + 100; }

// ts-unused-exports:disable-next-line
export function unusedButDisabled(x: number) { return x + 2; }

export default (x: number) => x + 1;
11 changes: 11 additions & 0 deletions example/simple-es6/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions example/simple-es6/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"description": "Example used by integration tests (ispec)",
"repository": {
"type": "git",
"url": "https://github.com/pzavolinsky/ts-unused-exports.git"
},
"license": "MIT",
"scripts": {
"test": "npm i && ../../bin/ts-unused-exports ./tsconfig.json"
},
"type": "module",
"dependencies": {
"typescript": "^4.9.4"
}
}
10 changes: 10 additions & 0 deletions example/simple-es6/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "es6",
"module": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"outDir": "./lib",
},
"include": ["./**/*.ts"],
}
1 change: 1 addition & 0 deletions example/simple-es6/unused.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function unused(x: number) { return x + 2; }
1 change: 1 addition & 0 deletions example/simple/execute.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx tsc && node ./lib/app.js
7 changes: 4 additions & 3 deletions example/simple/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"compilerOptions": {
"compilerOptions":
{
"target": "ES5",
"module": "commonjs",
"noEmit": true,
"noImplicitAny": true,
"strictNullChecks": true
"strictNullChecks": true,
"outDir": "./lib",
},
"include": ["./**/*.ts"],
}
4 changes: 2 additions & 2 deletions features/import-alias.feature
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Scenario: Used export default - import * as x
Given file "a.ts" is export default 1;
And file "b.ts" is import * as ax from './a';
When analyzing "tsconfig.json"
Then the result at a.ts is ["default"]
# see star.feature - Import * marks 'default' as unused
Then the result is {}
# see star.feature - Import * does NOT mark 'default' as unused

Scenario: Used export default - import x
Given file "a.ts" is export default 1;
Expand Down
6 changes: 3 additions & 3 deletions features/star.feature
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Feature: import * / export *

Scenario: Import * marks 'default' as unused
Scenario: Import * does NOT mark 'default' as unused
Given file "a.ts" is
"""
export const a = 1;
export default 1;
"""
And file "b.ts" is import * as all from './a';
When analyzing "tsconfig.json"
Then the result at a.ts is ["default"]
# note: default could still be used, as all.default
Then the result is {}
# note: a or default could still be used, as all.a or all.default - so safest to mark as used

Scenario: Import * and default
Given file "a.ts" is
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-unused-exports",
"version": "8.0.5",
"version": "9.0.0",
"description": "ts-unused-exports finds unused exported symbols in your Typescript project",
"main": "lib/app.js",
"repository": {
Expand Down
18 changes: 9 additions & 9 deletions src/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import {
File,
LocationInFile,
} from './types';
import { indexCandidates, removeExportStarPrefix } from './parser/util';
import {
indexCandidates,
removeExportStarPrefix,
removeFileExtensionToAllowForJs,
} from './parser/util';

export { Analysis } from './types';

Expand Down Expand Up @@ -69,7 +73,7 @@ const getExportMap = (files: File[]): ExportMap => {

const processImports = (file: File, exportMap: ExportMap): void => {
Object.keys(file.imports).forEach((key) => {
let ex = exportMap[key]?.exports;
let ex = exportMap[removeFileExtensionToAllowForJs(key)]?.exports;

// Handle imports from an index file
if (!ex && key === '.') {
Expand Down Expand Up @@ -101,13 +105,9 @@ const processImports = (file: File, exportMap: ExportMap): void => {
ex[imp].usageCount++;
};

file.imports[key].forEach((imp) =>
imp === '*'
? Object.keys(ex)
.filter((e) => e != 'default')
.forEach(addUsage)
: addUsage(imp),
);
file.imports[key].forEach((imp) => {
imp === '*' ? Object.keys(ex).forEach(addUsage) : addUsage(imp);
});
});
};

Expand Down
20 changes: 19 additions & 1 deletion src/parser/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,33 @@ import path = require('path');

// Parse Imports

const EXTENSIONS = ['.d.ts', '.ts', '.tsx', '.js', '.jsx'];
const EXTENSIONS = [
'.d.ts',
'.ts',
'.cts',
'.mts',
'.tsx',
'.js',
'.cjs',
'.mjs',
'.jsx',
];

const isRelativeToBaseDir = (baseDir: string, from: string): boolean =>
existsSync(resolve(baseDir, `${from}.js`)) ||
existsSync(resolve(baseDir, `${from}.cjs`)) ||
existsSync(resolve(baseDir, `${from}.mjs`)) ||
existsSync(resolve(baseDir, `${from}.ts`)) ||
existsSync(resolve(baseDir, `${from}.cts`)) ||
existsSync(resolve(baseDir, `${from}.mts`)) ||
existsSync(resolve(baseDir, `${from}.d.ts`)) ||
existsSync(resolve(baseDir, `${from}.tsx`)) ||
existsSync(resolve(baseDir, from, 'index.js')) ||
existsSync(resolve(baseDir, from, 'index.cjs')) ||
existsSync(resolve(baseDir, from, 'index.mjs')) ||
existsSync(resolve(baseDir, from, 'index.ts')) ||
existsSync(resolve(baseDir, from, 'index.cts')) ||
existsSync(resolve(baseDir, from, 'index.mts')) ||
existsSync(resolve(baseDir, from, 'index.tsx'));

const joinWithBaseUrl = (baseUrl: string, from: string) => {
Expand Down
16 changes: 16 additions & 0 deletions src/parser/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,26 @@ export function isUnique<T>(value: T, index: number, self: T[]): boolean {
export const indexCandidates = [
'/index',
'/index.ts',
'/index.cts',
'/index.mts',
'/index.tsx',
'/index.js',
'/index.cjs',
'/index.mjs',
];

export function removeFileExtensionToAllowForJs(path: string): string {
// ref: https://www.typescriptlang.org/docs/handbook/esm-node.html
const extensionsToStrip = ['.js', '.cjs', '.mjs'];

for (let i = 0; i < extensionsToStrip.length; i++) {
const ext = extensionsToStrip[i];
if (path.endsWith(ext)) return path.substring(0, path.length - ext.length);
}

return path;
}

export function removeExportStarPrefix(path: string): string {
if (path.startsWith('*:')) return path.slice(2);
else if (path.startsWith('*as:')) return path.slice(4);
Expand Down

0 comments on commit 6e506ae

Please sign in to comment.