ts-unused-exports
Advanced tools
Comparing version 2.1.0 to 2.2.0
## [Unreleased] - ReleaseDate | ||
### Added | ||
- If the option --showLineNumber is given, then output 1 line per unused export, with the location in the file (line number, column) | ||
### Changed | ||
- Fix the --ignorePaths option (it was incorrectly filtering the parsed files, instead of filtering the output) | ||
## [2.1.0] - 20 Oct 2019 | ||
### Added | ||
- Add comment flag to ignore some exports | ||
@@ -4,0 +11,0 @@ - Add tsconfig paths aliases support |
@@ -1,4 +0,4 @@ | ||
import { File, Analysis } from './types'; | ||
import { Analysis, ExtraCommandLineOptions, File } from './types'; | ||
export { Analysis } from './types'; | ||
declare const _default: (files: File[]) => Analysis; | ||
declare const _default: (files: File[], extraOptions?: ExtraCommandLineOptions | undefined) => Analysis; | ||
export default _default; |
@@ -5,3 +5,8 @@ "use strict"; | ||
var exports = {}; | ||
file.exports.forEach(function (e) { return exports[e] = 0; }); | ||
file.exports.forEach(function (e, index) { | ||
exports[e] = { | ||
usageCount: 0, | ||
location: file.exportLocations[index] | ||
}; | ||
}); | ||
return { exports: exports, path: file.fullPath }; | ||
@@ -23,4 +28,4 @@ }; | ||
return imp == '*' | ||
? Object.keys(ex).filter(function (e) { return e != 'default'; }).forEach(function (e) { return ++ex[e]; }) | ||
: ++ex[imp]; | ||
? Object.keys(ex).filter(function (e) { return e != 'default'; }).forEach(function (e) { return ex[e].usageCount++; }) | ||
: ex[imp].usageCount++; | ||
}); | ||
@@ -39,7 +44,23 @@ }); | ||
.filter(function (e) { return e != 'default'; }) | ||
.forEach(function (key) { return fileExports.exports[key] = 0; }); | ||
.forEach(function (key) { | ||
if (!fileExports.exports[key]) { | ||
var export1 = exportMap[ex.slice(2)].exports[key]; | ||
fileExports.exports[key] = { | ||
usageCount: 0, | ||
location: export1.location | ||
}; | ||
} | ||
fileExports.exports[key].usageCount = 0; | ||
}); | ||
}); | ||
}); | ||
}; | ||
exports.default = (function (files) { | ||
// Allow disabling of results, by path from command line (useful for large projects) | ||
var shouldPathBeIgnored = function (path, extraOptions) { | ||
if (!extraOptions || !extraOptions.pathsToIgnore) { | ||
return false; | ||
} | ||
return extraOptions.pathsToIgnore.some(function (ignore) { return path.indexOf(ignore) >= 0; }); | ||
}; | ||
exports.default = (function (files, extraOptions) { | ||
var exportMap = getExportMap(files); | ||
@@ -52,7 +73,17 @@ expandExportFromStar(files, exportMap); | ||
var exports = expItem.exports, path = expItem.path; | ||
var unused = Object.keys(exports).filter(function (k) { return exports[k] === 0; }); | ||
if (unused.length) | ||
analysis[path] = unused; | ||
if (shouldPathBeIgnored(path, extraOptions)) | ||
return; | ||
var unusedExports = Object.keys(exports).filter(function (k) { return exports[k].usageCount === 0; }); | ||
if (unusedExports.length === 0) { | ||
return; | ||
} | ||
analysis[path] = []; | ||
unusedExports.forEach(function (e) { | ||
analysis[path].push({ | ||
exportName: e, | ||
location: exports[e].location | ||
}); | ||
}); | ||
}); | ||
return analysis; | ||
}); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var fs_1 = require("fs"); | ||
var ts = require("typescript"); | ||
var analyzer_1 = require("./analyzer"); | ||
var path_1 = require("path"); | ||
var argsParser_1 = require("./argsParser"); | ||
var parser_1 = require("./parser"); | ||
var analyzer_1 = require("./analyzer"); | ||
var argsParser_1 = require("./argsParser"); | ||
var fs_1 = require("fs"); | ||
var parseTsConfig = function (tsconfigPath) { | ||
@@ -39,3 +39,3 @@ var basePath = path_1.resolve(path_1.dirname(tsconfigPath)); | ||
var tsConfig = exports.loadTsConfig(tsconfigPath, args.tsFiles); | ||
return analyzer_1.default(parser_1.default(path_1.dirname(tsconfigPath), tsConfig, args.options)); | ||
return analyzer_1.default(parser_1.default(path_1.dirname(tsconfigPath), tsConfig), args.options); | ||
}); |
import { ExtraCommandLineOptions } from "./types"; | ||
declare type TsFilesAndOptions = { | ||
tsFiles?: string[]; | ||
options: ExtraCommandLineOptions; | ||
options?: ExtraCommandLineOptions; | ||
}; | ||
@@ -6,0 +6,0 @@ export declare function extractOptionsFromFiles(files?: string[]): TsFilesAndOptions; |
@@ -53,2 +53,5 @@ "use strict"; | ||
break; | ||
case "--showLineNumber": | ||
newFilesAndOptions.options.showLineNumber = true; | ||
break; | ||
default: | ||
@@ -55,0 +58,0 @@ throw new Error("Not a recognised option '" + optionName + "'"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var argsParser_1 = require("./argsParser"); | ||
var app_1 = require("./app"); | ||
var chalk_1 = require("chalk"); | ||
var app_1 = require("./app"); | ||
var usage_1 = require("./usage"); | ||
var argsParser_1 = require("./argsParser"); | ||
var _a = process.argv.slice(2), tsconfig = _a[0], tsFiles = _a.slice(1); | ||
@@ -18,4 +18,20 @@ if (!argsParser_1.hasValidArgs()) { | ||
console.log(chalk_1.default.red(chalk_1.default.bold(files.length.toString()) + " module" + (files.length == 1 ? '' : 's') + " with unused exports")); | ||
files.forEach(function (path) { return console.log(path + ": " + chalk_1.default.bold.yellow(analysis_1[path].join(", "))); }); | ||
if (argsParser_1.extractOptionsFromFiles(tsFiles).options.exitWithCount) { | ||
var getLocationInFile_1 = function (location) { | ||
if (!location) { | ||
return ""; | ||
} | ||
return "[" + location.line + "," + location.character + "]"; | ||
}; | ||
var options = argsParser_1.extractOptionsFromFiles(tsFiles).options; | ||
if (options && options.showLineNumber) { | ||
files.forEach(function (path) { | ||
analysis_1[path].forEach(function (unusedExport) { | ||
console.log("" + path + getLocationInFile_1(unusedExport.location) + ": " + chalk_1.default.bold.yellow(unusedExport.exportName)); | ||
}); | ||
}); | ||
} | ||
else { | ||
files.forEach(function (path) { return console.log(path + ": " + chalk_1.default.bold.yellow(analysis_1[path].map(function (r) { return r.exportName; }).join(", "))); }); | ||
} | ||
if (options && options.exitWithCount) { | ||
process.exit(files.length); | ||
@@ -22,0 +38,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var argsParser_1 = require("./argsParser"); | ||
var path_1 = require("path"); | ||
var app_1 = require("./app"); | ||
var argsParser_1 = require("./argsParser"); | ||
var parser_1 = require("./parser"); | ||
@@ -35,5 +35,5 @@ var usage_1 = require("./usage"); | ||
; | ||
var analyzeDeps = function (tsconfigPath, extraOptions) { | ||
var analyzeDeps = function (tsconfigPath) { | ||
var tsConfig = app_1.loadTsConfig(tsconfigPath); | ||
var files = parser_1.default(path_1.dirname(tsconfigPath), tsConfig, extraOptions); | ||
var files = parser_1.default(path_1.dirname(tsconfigPath), tsConfig); | ||
var fileMap = getFileMap(files); | ||
@@ -44,3 +44,4 @@ var analysis = {}; | ||
}; | ||
var _a = process.argv.slice(2), tsconfig = _a[0], filter = _a[1], options = _a.slice(2); | ||
// Not using options here | ||
var _a = process.argv.slice(2), tsconfig = _a[0], filter = _a[1]; | ||
if (!argsParser_1.hasValidArgs()) { | ||
@@ -53,4 +54,3 @@ usage_1.showUsage(); | ||
}; | ||
var parsedOptions = argsParser_1.extractOptionsFromFiles(options).options; | ||
var analysis = analyzeDeps(tsconfig, parsedOptions); | ||
var analysis = analyzeDeps(tsconfig); | ||
var deps = getValues(analysis); | ||
@@ -57,0 +57,0 @@ deps.sort(function (a, b) { return a.depth - b.depth; }); |
@@ -1,3 +0,3 @@ | ||
import { File, TsConfig, ExtraCommandLineOptions } from './types'; | ||
declare const _default: (rootDir: string, TsConfig: TsConfig, extraOptions?: ExtraCommandLineOptions | undefined) => File[]; | ||
import { File, TsConfig } from './types'; | ||
declare const _default: (rootDir: string, TsConfig: TsConfig) => File[]; | ||
export default _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var fs_1 = require("fs"); | ||
var path_1 = require("path"); | ||
var ts = require("typescript"); | ||
var tsconfigPaths = require("tsconfig-paths"); | ||
var path_1 = require("path"); | ||
var fs_1 = require("fs"); | ||
var TRIM_QUOTES = /^['"](.*)['"]$/; | ||
@@ -103,5 +103,14 @@ var EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx']; | ||
var exports = []; | ||
var exportLocations = []; | ||
var name = path_1.relative(rootDir, path).replace(/([\\/]index)?\.[^.]*$/, ''); | ||
var baseDir = baseUrl && path_1.resolve(rootDir, baseUrl); | ||
var tsconfigPathsMatcher = baseDir && paths && tsconfigPaths.createMatchPath(baseDir, paths); | ||
var addExport = function (exportName, file, node) { | ||
exports.push(exportName); | ||
var location = file.getLineAndCharacterOfPosition(node.getStart()); | ||
exportLocations.push({ | ||
line: location.line + 1, | ||
character: location.character | ||
}); | ||
}; | ||
var addImport = function (fw) { | ||
@@ -148,3 +157,3 @@ var from = fw.from, what = fw.what; | ||
if (kind === ts.SyntaxKind.ExportAssignment) { | ||
exports.push('default'); | ||
addExport('default', file, node); | ||
return; | ||
@@ -154,3 +163,3 @@ } | ||
if (node.moduleSpecifier === undefined) { | ||
exports.push.apply(exports, extractExportStatement(node)); | ||
extractExportStatement(node).forEach(function (e) { return addExport(e, file, node); }); | ||
return; | ||
@@ -164,3 +173,3 @@ } | ||
if (what == star) { | ||
exports.push("*:" + key); | ||
addExport("*:" + key, file, node); | ||
} | ||
@@ -176,3 +185,3 @@ else { | ||
if (hasModifier(node, ts.SyntaxKind.DefaultKeyword)) { | ||
exports.push('default'); | ||
addExport('default', file, node); | ||
return; | ||
@@ -185,3 +194,3 @@ } | ||
if (name_2) | ||
exports.push(name_2); | ||
addExport(name_2, file, node); | ||
} | ||
@@ -193,3 +202,4 @@ }); | ||
imports: imports, | ||
exports: exports | ||
exports: exports, | ||
exportLocations: exportLocations | ||
}; | ||
@@ -201,19 +211,11 @@ }; | ||
}; | ||
var parsePaths = function (rootDir, _a, extraOptions) { | ||
var parsePaths = function (rootDir, _a) { | ||
var baseUrl = _a.baseUrl, filePaths = _a.files, paths = _a.paths; | ||
var files = filePaths | ||
.filter(function (p) { return p.indexOf('.d.') == -1 && !shouldPathBeIgnored(p, extraOptions.pathsToIgnore); }) | ||
.filter(function (p) { return p.indexOf('.d.') == -1; }) | ||
.map(function (path) { return parseFile(rootDir, path_1.resolve(rootDir, path), baseUrl, paths); }); | ||
return files; | ||
}; | ||
// Allow disabling of results, by path from command line (useful for large projects) | ||
var shouldPathBeIgnored = function (path, pathsToIgnore) { | ||
if (!pathsToIgnore) { | ||
return false; | ||
} | ||
return pathsToIgnore.some(function (ignore) { return path.indexOf(ignore) >= 0; }); | ||
}; | ||
exports.default = (function (rootDir, TsConfig, extraOptions) { | ||
var activeExtraOptions = extraOptions || {}; | ||
return parsePaths(rootDir, TsConfig, activeExtraOptions); | ||
exports.default = (function (rootDir, TsConfig) { | ||
return parsePaths(rootDir, TsConfig); | ||
}); |
@@ -9,5 +9,15 @@ export interface Imports { | ||
exports: string[]; | ||
exportLocations: LocationInFile[]; | ||
} | ||
export interface LocationInFile { | ||
/** 1-based. */ | ||
line: number; | ||
character: number; | ||
} | ||
export interface ExportNameAndLocation { | ||
exportName: string; | ||
location: LocationInFile; | ||
} | ||
export interface Analysis { | ||
[index: string]: string[]; | ||
[index: string]: ExportNameAndLocation[]; | ||
} | ||
@@ -25,2 +35,3 @@ export interface TsConfigPaths { | ||
pathsToIgnore?: string[]; | ||
showLineNumber?: boolean; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function showUsage() { | ||
console.error("\n usage: ts-unused-exports path/to/tsconfig.json [file1.ts file2.ts] [--exitWithCount][--ignorePaths=path1;path2]\n \n Note: if no file is specified after tsconfig, the files will be read from the\n tsconfig's \"files\" key which must be present.\n \n If the files are specified, their path must be relative to the tsconfig file.\n For example, given:\n /\n |-- config\n | -- tsconfig.json\n -- src\n -- file.ts\n \n Then the usage would be:\n ts-unused-exports config/tsconfig.json ../src/file.ts\n "); | ||
console.error("\n usage: ts-unused-exports path/to/tsconfig.json [file1.ts file2.ts] [--exitWithCount][--ignorePaths=path1;path2][--showLineNumber]\n \n Note: if no file is specified after tsconfig, the files will be read from the\n tsconfig's \"files\" key which must be present.\n \n If the files are specified, their path must be relative to the tsconfig file.\n For example, given:\n /\n |-- config\n | -- tsconfig.json\n -- src\n -- file.ts\n \n Then the usage would be:\n ts-unused-exports config/tsconfig.json ../src/file.ts\n "); | ||
} | ||
exports.showUsage = showUsage; |
{ | ||
"name": "ts-unused-exports", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "ts-unused-exports finds unused exported symbols in your Typescript project", | ||
@@ -27,3 +27,3 @@ "main": "lib/app.js", | ||
"test:unit": "jasmine", | ||
"test:itest": "./bin/ts-unused-exports ./example/tsconfig.json", | ||
"test:itest": "cd ispec && bash ./run.sh", | ||
"exec": "bin/ts-unused-exports" | ||
@@ -30,0 +30,0 @@ }, |
@@ -47,4 +47,5 @@ ts-unused-exports | ||
|---|---|---| | ||
| `exitWithCount` | Set the process exit code to be the count of files that have unused exports. | `--exitWithCount` | | ||
| `ignorePaths` | Exclude files that match the given path segments. | `--ignorePaths=math;utils` | | ||
| `exitWithCount` | Set the process exit code to be the count of files that have unused exports. | `--exitWithCount` | | ||
| `showLineNumber` | Show the line number and column of the unused export. | `--showLineNumber` | | ||
@@ -80,3 +81,3 @@ Note that if `ts-unused-exports` is called without files, the files will be read from the tsconfig's `files` or `include` key which must be present. If called with files, then those file paths should be relative to the `tsconfig.json`, just like you would specifie them in your tsconfig's `files` key. | ||
There is a (very silly) example in the [example/](https://github.com/pzavolinsky/ts-unused-exports/blob/master/example) directory. | ||
There is a (very silly) example in the [example/](https://github.com/pzavolinsky/ts-unused-exports/blob/master/example/simple) directory. | ||
@@ -89,4 +90,4 @@ If you want to run it you can: | ||
./bin/ts-unused-exports example/tsconfig.json | ||
# or: node ./bin/ts-unused-exports example/tsconfig.json | ||
# or: node bin\ts-unused-exports example\tsconfig.json | ||
# or: node ./bin/ts-unused-exports example/simple/tsconfig.json | ||
# or: node bin\ts-unused-exports example\simple\tsconfig.json | ||
``` | ||
@@ -111,3 +112,3 @@ | ||
```shell | ||
./bin/ts-unused-exports example/tsconfig.json app.ts math.ts | ||
./bin/ts-unused-exports example/simple/tsconfig.json app.ts math.ts | ||
``` | ||
@@ -118,3 +119,3 @@ | ||
```shell | ||
./bin/ts-unused-exports example/tsconfig.json $(cd example; find -name '*.ts') | ||
./bin/ts-unused-exports example/simple/tsconfig.json $(cd example/simple; find -name '*.ts') | ||
``` | ||
@@ -121,0 +122,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
29587
608
124
0