From 3c9954eb307f76a858ec1f7255524d0ff5e2a07c Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 27 Jul 2019 12:58:14 -0700 Subject: [PATCH] Added "--dependencies" command-line switch that reports import dependency information for all source files that were analyzed. --- docs/command-line.md | 1 + server/src/analyzer/program.ts | 37 ++++++++++++++++++++++++++++++++++ server/src/analyzer/service.ts | 4 ++++ server/src/pyright.ts | 8 +++++++- 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/command-line.md b/docs/command-line.md index d9e5a70a1..1d65dd80d 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -4,6 +4,7 @@ Pyright can be run as either a VS Code extension or as a node-based command-line | Flag | Description | | :--------------------------------- | :--------------------------------------------------- | +| --dependencies | Emit import dependecy information | | -h, --help | Show help message | | -p, --project FILE OR DIRECTORY | Use the configuration file at this location | | --stats | Print detailed performance stats | diff --git a/server/src/analyzer/program.ts b/server/src/analyzer/program.ts index bfb8a6dc4..821561c01 100644 --- a/server/src/analyzer/program.ts +++ b/server/src/analyzer/program.ts @@ -302,6 +302,43 @@ export class Program { return false; } + // Prints import dependency information for each of the files in the program. + printDependencies() { + const sortedFiles = this._sourceFileList.sort((a, b) => { + return (a.sourceFile.getFilePath() < b.sourceFile.getFilePath()) ? 1 : -1; + }); + + const zeroImportFiles: SourceFile[] = []; + + sortedFiles.forEach(sfInfo => { + this._console.log(`${ sfInfo.sourceFile.getFilePath() }`) + + this._console.log(` Imports ${ sfInfo.imports.length } ` + + `file${ sfInfo.imports.length === 1 ? '' : 's' }`) + sfInfo.imports.forEach(importInfo => { + this._console.log(` ${ importInfo.sourceFile.getFilePath() }`) + }); + + this._console.log(` Imported by ${ sfInfo.importedBy.length } ` + + `file${ sfInfo.importedBy.length === 1 ? '' : 's' }`) + sfInfo.importedBy.forEach(importInfo => { + this._console.log(` ${ importInfo.sourceFile.getFilePath() }`) + }); + if (sfInfo.importedBy.length === 0) { + zeroImportFiles.push(sfInfo.sourceFile); + } + }); + + if (zeroImportFiles.length > 0) { + this._console.log(''); + this._console.log(`${ zeroImportFiles.length } file${ zeroImportFiles.length === 1 ? '' : 's' }` + + ` not explicitly imported`); + zeroImportFiles.forEach(importFile => { + this._console.log(` ${ importFile.getFilePath() }`) + }); + } + } + // This method is similar to analyze() except that it analyzes // a single file (and its dependencies if necessary). private _analyzeFile(sourceFileInfo: SourceFileInfo, options: ConfigOptions, diff --git a/server/src/analyzer/service.ts b/server/src/analyzer/service.ts index e64738d5f..4b92b89a3 100644 --- a/server/src/analyzer/service.ts +++ b/server/src/analyzer/service.ts @@ -152,6 +152,10 @@ export class AnalyzerService { this._console.log('Maximum pass count: ' + maxPassCount.toString() + path); } + printDependencies() { + this._program.printDependencies(); + } + test_getConfigOptions(commandLineOptions: CommandLineOptions): ConfigOptions { return this._getConfigOptions(commandLineOptions); } diff --git a/server/src/pyright.ts b/server/src/pyright.ts index c8d1c94ef..6cafe8c97 100644 --- a/server/src/pyright.ts +++ b/server/src/pyright.ts @@ -38,6 +38,7 @@ interface DiagnosticResult { function processArgs() { const optionDefinitions: OptionDefinition[] = [ + { name: 'dependencies', type: Boolean }, { name: 'files', type: String, multiple: true, defaultOption: true }, { name: 'help', alias: 'h', type: Boolean }, { name: 'project', alias: 'p', type: String }, @@ -95,7 +96,7 @@ function processArgs() { options.typeshedPath = combinePaths(process.cwd(), normalizePath(args['typeshed-path'])); } - options.verboseOutput = args.verbose !== undefined; + options.verboseOutput = !!args.verbose; let watch = args.watch !== undefined; options.watch = watch; @@ -124,6 +125,10 @@ function processArgs() { timingStats.printDetails(console); } + if (args.dependencies) { + service.printDependencies(); + } + if (!watch) { process.exit( errorCount > 0 ? @@ -146,6 +151,7 @@ function printUsage() { console.log( 'Usage: ' + toolName + ' [options] files...\n' + ' Options:\n' + + ' --dependencies Emit import dependecy information\n' + ' -h,--help Show this help message\n' + ' -p,--project FILE OR DIRECTORY Use the configuration file at this location\n' + ' --stats Print detailed performance stats\n' +