mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
Added "--skipunannotated" option for command-line version of pyright. If specified, pyright skips type analysis of functions and methods that have no parameter or return type annotations. Return types of functions are also never inferred from the function implementation. This matches the default behavior of mypy and allows for more efficient analysis of complex code bases that are only partially annotated.
This commit is contained in:
parent
94a700b562
commit
ef773d2407
@ -15,6 +15,7 @@ Pyright can be run as either a VS Code extension or as a node-based command-line
|
||||
| -p, --project `<FILE OR DIRECTORY>` | Use the configuration file at this location |
|
||||
| --pythonplatform `<PLATFORM>` | Analyze for platform (Darwin, Linux, Windows) |
|
||||
| --pythonversion `<VERSION>` | Analyze for version (3.3, 3.4, etc.) |
|
||||
| --skipunannotated | Skip type analysis of unannotated functions? |
|
||||
| --stats | Print detailed performance stats |
|
||||
| -t, --typeshed-path `<DIRECTORY>` | Use typeshed type stubs at this location (2) |
|
||||
| -v, --venv-path `<DIRECTORY>` | Directory that contains virtual environments (3) |
|
||||
|
@ -1887,6 +1887,15 @@ export function getFullStatementRange(statementNode: ParseNode, tokenizerOutput:
|
||||
return { start: range.start, end: { line: range.end.line + 1, character: 0 } };
|
||||
}
|
||||
|
||||
export function isUnannotatedFunction(node: FunctionNode) {
|
||||
return (
|
||||
node.returnTypeAnnotation === undefined &&
|
||||
node.parameters.every(
|
||||
(param) => param.typeAnnotation === undefined && param.typeAnnotationComment === undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function _getEndPositionIfMultipleStatementsAreOnSameLine(
|
||||
range: Range,
|
||||
tokenPosition: number,
|
||||
|
@ -742,6 +742,7 @@ export class Program {
|
||||
printTypeFlags: Program._getPrintTypeFlags(this._configOptions),
|
||||
logCalls: this._configOptions.logTypeEvaluationTime,
|
||||
minimumLoggingThreshold: this._configOptions.typeEvaluationTimeThreshold,
|
||||
analyzeUnannotatedFunctions: this._configOptions.analyzeUnannotatedFunctions,
|
||||
},
|
||||
this._logTracker,
|
||||
this._configOptions.logTypeEvaluationTime
|
||||
|
@ -622,6 +622,8 @@ export class AnalyzerService {
|
||||
configOptions.applyDiagnosticOverrides(commandLineOptions.diagnosticSeverityOverrides);
|
||||
}
|
||||
|
||||
configOptions.analyzeUnannotatedFunctions = commandLineOptions.analyzeUnannotatedFunctions ?? true;
|
||||
|
||||
const reportDuplicateSetting = (settingName: string, configValue: number | string | boolean) => {
|
||||
const settingSource = commandLineOptions.fromVsCodeExtension
|
||||
? 'the client settings'
|
||||
|
@ -506,6 +506,7 @@ export interface EvaluatorOptions {
|
||||
printTypeFlags: TypePrinter.PrintTypeFlags;
|
||||
logCalls: boolean;
|
||||
minimumLoggingThreshold: number;
|
||||
analyzeUnannotatedFunctions: boolean;
|
||||
}
|
||||
|
||||
export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions: EvaluatorOptions): TypeEvaluator {
|
||||
@ -3193,6 +3194,17 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
let isIncomplete = false;
|
||||
const allowForwardReferences = (flags & EvaluatorFlags.AllowForwardReferences) !== 0 || fileInfo.isStubFile;
|
||||
|
||||
if (!evaluatorOptions.analyzeUnannotatedFunctions) {
|
||||
const containingFunction = ParseTreeUtils.getEnclosingFunction(node);
|
||||
if (containingFunction && ParseTreeUtils.isUnannotatedFunction(containingFunction)) {
|
||||
return {
|
||||
node,
|
||||
type: AnyType.create(),
|
||||
isIncomplete: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Look for the scope that contains the value definition and
|
||||
// see if it has a declared type.
|
||||
const symbolWithScope = lookUpSymbolRecursive(node, name, !allowForwardReferences);
|
||||
@ -17270,6 +17282,8 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
} else if (type.details.declaration) {
|
||||
const functionNode = type.details.declaration.node;
|
||||
|
||||
// Skip return type inference if we are in "skip unannotated function" mode.
|
||||
if (evaluatorOptions.analyzeUnannotatedFunctions) {
|
||||
const codeFlowComplexity = AnalyzerNodeInfo.getCodeFlowComplexity(functionNode);
|
||||
|
||||
// For very complex functions that have no annotated parameter types,
|
||||
@ -17296,6 +17310,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!returnType) {
|
||||
returnType = UnknownType.create();
|
||||
@ -17309,6 +17324,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
// params, try to analyze the function with the provided argument types and
|
||||
// attempt to do a better job at inference.
|
||||
if (
|
||||
evaluatorOptions.analyzeUnannotatedFunctions &&
|
||||
isPartlyUnknown(returnType) &&
|
||||
FunctionType.hasUnannotatedParams(type) &&
|
||||
!FunctionType.isStubDefinition(type) &&
|
||||
|
@ -118,12 +118,15 @@ export class CommandLineOptions {
|
||||
// Use indexing.
|
||||
indexing?: boolean | undefined;
|
||||
|
||||
// Use type evaluator call tracking
|
||||
// Use type evaluator call tracking.
|
||||
logTypeEvaluationTime = false;
|
||||
|
||||
// Minimum threshold for type eval logging
|
||||
// Minimum threshold for type eval logging.
|
||||
typeEvaluationTimeThreshold = 50;
|
||||
|
||||
// Run ambient analysis
|
||||
// Run ambient analysis.
|
||||
enableAmbientAnalysis = true;
|
||||
|
||||
// Analyze functions and methods that have no type annotations?
|
||||
analyzeUnannotatedFunctions = true;
|
||||
}
|
||||
|
@ -657,6 +657,10 @@ export class ConfigOptions {
|
||||
// Was this config initialized from JSON (pyrightconfig/pyproject)?
|
||||
initializedFromJson = false;
|
||||
|
||||
// Should we skip analysis of all functions and methods that have
|
||||
// no parameter ore return type annotations?
|
||||
analyzeUnannotatedFunctions = true;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Diagnostics Rule Set
|
||||
|
||||
|
@ -131,6 +131,7 @@ async function processArgs(): Promise<ExitStatus> {
|
||||
{ name: 'project', alias: 'p', type: String },
|
||||
{ name: 'pythonplatform', type: String },
|
||||
{ name: 'pythonversion', type: String },
|
||||
{ name: 'skipunannotated', type: Boolean },
|
||||
{ name: 'stats' },
|
||||
{ name: 'typeshed-path', alias: 't', type: String },
|
||||
{ name: 'venv-path', alias: 'v', type: String },
|
||||
@ -177,7 +178,7 @@ async function processArgs(): Promise<ExitStatus> {
|
||||
}
|
||||
|
||||
if (args['verifytypes'] !== undefined) {
|
||||
const incompatibleArgs = ['watch', 'stats', 'createstub', 'dependencies'];
|
||||
const incompatibleArgs = ['watch', 'stats', 'createstub', 'dependencies', 'skipunannotated'];
|
||||
for (const arg of incompatibleArgs) {
|
||||
if (args[arg] !== undefined) {
|
||||
console.error(`'verifytypes' option cannot be used with '${arg}' option`);
|
||||
@ -187,7 +188,7 @@ async function processArgs(): Promise<ExitStatus> {
|
||||
}
|
||||
|
||||
if (args.createstub) {
|
||||
const incompatibleArgs = ['watch', 'stats', 'verifytypes', 'dependencies'];
|
||||
const incompatibleArgs = ['watch', 'stats', 'verifytypes', 'dependencies', 'skipunannotated'];
|
||||
for (const arg of incompatibleArgs) {
|
||||
if (args[arg] !== undefined) {
|
||||
console.error(`'createstub' option cannot be used with '${arg}' option`);
|
||||
@ -243,12 +244,16 @@ async function processArgs(): Promise<ExitStatus> {
|
||||
options.typeStubTargetImportName = args.createstub;
|
||||
}
|
||||
|
||||
options.analyzeUnannotatedFunctions = !args.skipAnalysisForUnannotatedFunctions;
|
||||
|
||||
if (args.verbose) {
|
||||
options.verboseOutput = true;
|
||||
}
|
||||
|
||||
if (args.lib) {
|
||||
options.useLibraryCodeForTypes = true;
|
||||
}
|
||||
|
||||
options.checkOnlyOpenFiles = false;
|
||||
|
||||
const treatWarningsAsErrors = !!args.warnings;
|
||||
@ -603,6 +608,7 @@ function printUsage() {
|
||||
' -p,--project <FILE OR DIRECTORY> Use the configuration file at this location\n' +
|
||||
' --pythonplatform <PLATFORM> Analyze for a specific platform (Darwin, Linux, Windows)\n' +
|
||||
' --pythonversion <VERSION> Analyze for a specific version (3.3, 3.4, etc.)\n' +
|
||||
' --skipunannotated Do not analyze functions and methods with no type annotations\n' +
|
||||
' --stats Print detailed performance stats\n' +
|
||||
' -t,--typeshed-path <DIRECTORY> Use typeshed type stubs at this location\n' +
|
||||
' -v,--venv-path <DIRECTORY> Directory that contains virtual environments\n' +
|
||||
|
Loading…
Reference in New Issue
Block a user