mirror of
https://github.com/microsoft/pyright.git
synced 2024-08-17 03:40:44 +03:00
Added new diagnostic rule "reportInvalidTypeVarUse" that controls reporting of TypeVars that appear only once in a function signature. By default it is off in basic type checking mode but on in strict mode.
This commit is contained in:
parent
1c91ad026a
commit
bb04ffa6be
@ -112,6 +112,8 @@ The following settings control pyright’s diagnostic output (warnings or errors
|
||||
|
||||
**reportMissingTypeArgument** [boolean or string, optional]: Generate or suppress diagnostics when a generic class is used without providing explicit or implicit type arguments. The default value for this setting is 'none'.
|
||||
|
||||
**reportInvalidTypeVarUse** [boolean or string, optional]: Generate or suppress diagnostics when a TypeVar is used inappropriately (e.g. if a TypeVar appears only once) within a generic function signature. The default value for this setting is 'none'.
|
||||
|
||||
**reportCallInDefaultInitializer** [boolean or string, optional]: Generate or suppress diagnostics for function calls within a default value initialization expression. Such calls can mask expensive operations that are performed at module initialization time. The default value for this setting is 'none'.
|
||||
|
||||
**reportUnnecessaryIsInstance** [boolean or string, optional]: Generate or suppress diagnostics for 'isinstance' or 'issubclass' calls where the result is statically determined to be always true or always false. Such calls are often indicative of a programming error. The default value for this setting is 'none'.
|
||||
|
@ -796,6 +796,11 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
// Verifies that each local type variable is used more than once.
|
||||
private _validateFunctionTypeVarUsage(node: FunctionNode) {
|
||||
// Skip this check entirely if it's disabled.
|
||||
if (this._fileInfo.diagnosticRuleSet.reportInvalidTypeVarUse === 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
const localTypeVarUsage = new Map<string, NameNode[]>();
|
||||
|
||||
const nameWalker = new ParseTreeUtils.NameNodeWalker((nameNode) => {
|
||||
@ -827,8 +832,8 @@ export class Checker extends ParseTreeWalker {
|
||||
localTypeVarUsage.forEach((nameNodes) => {
|
||||
if (nameNodes.length === 1) {
|
||||
this._evaluator.addDiagnostic(
|
||||
this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues,
|
||||
DiagnosticRule.reportGeneralTypeIssues,
|
||||
this._fileInfo.diagnosticRuleSet.reportInvalidTypeVarUse,
|
||||
DiagnosticRule.reportInvalidTypeVarUse,
|
||||
Localizer.Diagnostic.typeVarUsedOnlyOnce().format({
|
||||
name: nameNodes[0].value,
|
||||
}),
|
||||
|
@ -192,6 +192,9 @@ export interface DiagnosticRuleSet {
|
||||
// Report usage of generic class without explicit type arguments?
|
||||
reportMissingTypeArgument: DiagnosticLevel;
|
||||
|
||||
// Report improper usage of type variables within function signatures?
|
||||
reportInvalidTypeVarUse: DiagnosticLevel;
|
||||
|
||||
// Report usage of function call within default value
|
||||
// initialization expression?
|
||||
reportCallInDefaultInitializer: DiagnosticLevel;
|
||||
@ -277,6 +280,7 @@ export function getDiagLevelDiagnosticRules() {
|
||||
DiagnosticRule.reportUnknownVariableType,
|
||||
DiagnosticRule.reportUnknownMemberType,
|
||||
DiagnosticRule.reportMissingTypeArgument,
|
||||
DiagnosticRule.reportInvalidTypeVarUse,
|
||||
DiagnosticRule.reportCallInDefaultInitializer,
|
||||
DiagnosticRule.reportUnnecessaryIsInstance,
|
||||
DiagnosticRule.reportUnnecessaryCast,
|
||||
@ -338,6 +342,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'none',
|
||||
reportUnknownMemberType: 'none',
|
||||
reportMissingTypeArgument: 'none',
|
||||
reportInvalidTypeVarUse: 'none',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'none',
|
||||
reportUnnecessaryCast: 'none',
|
||||
@ -395,6 +400,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'none',
|
||||
reportUnknownMemberType: 'none',
|
||||
reportMissingTypeArgument: 'none',
|
||||
reportInvalidTypeVarUse: 'none',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'none',
|
||||
reportUnnecessaryCast: 'none',
|
||||
@ -452,6 +458,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'error',
|
||||
reportUnknownMemberType: 'error',
|
||||
reportMissingTypeArgument: 'error',
|
||||
reportInvalidTypeVarUse: 'error',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'error',
|
||||
reportUnnecessaryCast: 'error',
|
||||
@ -1020,6 +1027,13 @@ export class ConfigOptions {
|
||||
defaultSettings.reportMissingTypeArgument
|
||||
),
|
||||
|
||||
// Read the "reportInvalidTypeVarUse" entry.
|
||||
reportInvalidTypeVarUse: this._convertDiagnosticLevel(
|
||||
configObj.reportInvalidTypeVarUse,
|
||||
DiagnosticRule.reportInvalidTypeVarUse,
|
||||
defaultSettings.reportInvalidTypeVarUse
|
||||
),
|
||||
|
||||
// Read the "reportCallInDefaultInitializer" entry.
|
||||
reportCallInDefaultInitializer: this._convertDiagnosticLevel(
|
||||
configObj.reportCallInDefaultInitializer,
|
||||
|
@ -49,6 +49,7 @@ export enum DiagnosticRule {
|
||||
reportUnknownVariableType = 'reportUnknownVariableType',
|
||||
reportUnknownMemberType = 'reportUnknownMemberType',
|
||||
reportMissingTypeArgument = 'reportMissingTypeArgument',
|
||||
reportInvalidTypeVarUse = 'reportInvalidTypeVarUse',
|
||||
reportCallInDefaultInitializer = 'reportCallInDefaultInitializer',
|
||||
reportUnnecessaryIsInstance = 'reportUnnecessaryIsInstance',
|
||||
reportUnnecessaryCast = 'reportUnnecessaryCast',
|
||||
|
@ -2,6 +2,8 @@
|
||||
# a generic function. A TypeVar must appear at least twice to be
|
||||
# considered legitimate.
|
||||
|
||||
# pyright: reportInvalidTypeVarUse=true
|
||||
|
||||
from typing import Dict, Generic, List, TypeVar
|
||||
|
||||
|
||||
|
@ -878,7 +878,7 @@ test('ParamSpec1', () => {
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const results = TestUtils.typeAnalyzeSampleFiles(['paramSpec1.py'], configOptions);
|
||||
TestUtils.validateResults(results, 8);
|
||||
TestUtils.validateResults(results, 7);
|
||||
});
|
||||
|
||||
test('ParamSpec2', () => {
|
||||
@ -906,7 +906,7 @@ test('ParamSpec4', () => {
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const results = TestUtils.typeAnalyzeSampleFiles(['paramSpec4.py'], configOptions);
|
||||
TestUtils.validateResults(results, 7);
|
||||
TestUtils.validateResults(results, 5);
|
||||
});
|
||||
|
||||
test('ClassVar1', () => {
|
||||
|
@ -477,6 +477,17 @@
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"reportInvalidTypeVarUse": {
|
||||
"type": "string",
|
||||
"description": "Diagnostics for improper use of type variables in a function signature.",
|
||||
"default": "none",
|
||||
"enum": [
|
||||
"none",
|
||||
"information",
|
||||
"warning",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"reportCallInDefaultInitializer": {
|
||||
"type": "string",
|
||||
"description": "Diagnostics for function calls within a default value initialization expression. Such calls can mask expensive operations that are performed at module initialization time.",
|
||||
|
@ -321,6 +321,12 @@
|
||||
"title": "Controls reporting generic class reference with missing type arguments",
|
||||
"default": "none"
|
||||
},
|
||||
"reportInvalidTypeVarUse": {
|
||||
"$id": "#/properties/reportInvalidTypeVarUse",
|
||||
"$ref": "#/definitions/diagnostic",
|
||||
"title": "Controls reporting improper use of type variables within function signatures",
|
||||
"default": "none"
|
||||
},
|
||||
"reportCallInDefaultInitializer": {
|
||||
"$id": "#/properties/reportCallInDefaultInitializer",
|
||||
"$ref": "#/definitions/diagnostic",
|
||||
|
Loading…
Reference in New Issue
Block a user