mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-26 19:01:08 +03:00
Removed recently-added "reportInvalidTypeVarUse" diagnostic rule and associated checks. After further discussion, we decided that there are legitimate cases where a TypeVar can appear only once in a function signature.
This commit is contained in:
parent
4067961207
commit
9046794205
@ -112,8 +112,6 @@ 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'.
|
||||
|
@ -344,8 +344,6 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
this._scopedNodes.push(node);
|
||||
|
||||
this._validateFunctionTypeVarUsage(node);
|
||||
|
||||
if (functionTypeResult && functionTypeResult.decoratedType.category === TypeCategory.OverloadedFunction) {
|
||||
const overloads = functionTypeResult.decoratedType.overloads;
|
||||
if (overloads.length > 1) {
|
||||
@ -794,55 +792,6 @@ export class Checker extends ParseTreeWalker {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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) => {
|
||||
const nameType = this._evaluator.getType(nameNode);
|
||||
if (nameType && isTypeVar(nameType)) {
|
||||
if (nameType.scopeId === node.id) {
|
||||
if (!localTypeVarUsage.has(nameType.details.name)) {
|
||||
localTypeVarUsage.set(nameType.details.name, [nameNode]);
|
||||
} else {
|
||||
localTypeVarUsage.get(nameType.details.name)!.push(nameNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Find all of the local type variables in signature.
|
||||
node.parameters.forEach((param) => {
|
||||
const annotation = param.typeAnnotation || param.typeAnnotationComment;
|
||||
if (annotation) {
|
||||
nameWalker.walk(annotation);
|
||||
}
|
||||
});
|
||||
|
||||
if (node.returnTypeAnnotation) {
|
||||
nameWalker.walk(node.returnTypeAnnotation);
|
||||
}
|
||||
|
||||
// Report errors for all local type variables that appear only once.
|
||||
localTypeVarUsage.forEach((nameNodes) => {
|
||||
if (nameNodes.length === 1) {
|
||||
this._evaluator.addDiagnostic(
|
||||
this._fileInfo.diagnosticRuleSet.reportInvalidTypeVarUse,
|
||||
DiagnosticRule.reportInvalidTypeVarUse,
|
||||
Localizer.Diagnostic.typeVarUsedOnlyOnce().format({
|
||||
name: nameNodes[0].value,
|
||||
}),
|
||||
nameNodes[0]
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _validateOverloadConsistency(
|
||||
node: FunctionNode,
|
||||
functionType: FunctionType,
|
||||
|
@ -1034,16 +1034,3 @@ export function isAssignmentToDefaultsFollowingNamedTuple(callNode: ParseNode):
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This simple parse tree walker calls a callback function
|
||||
// for each NameNode it encounters.
|
||||
export class NameNodeWalker extends ParseTreeWalker {
|
||||
constructor(private _callback: (node: NameNode) => void) {
|
||||
super();
|
||||
}
|
||||
|
||||
visitName(node: NameNode) {
|
||||
this._callback(node);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -192,9 +192,6 @@ 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;
|
||||
@ -280,7 +277,6 @@ export function getDiagLevelDiagnosticRules() {
|
||||
DiagnosticRule.reportUnknownVariableType,
|
||||
DiagnosticRule.reportUnknownMemberType,
|
||||
DiagnosticRule.reportMissingTypeArgument,
|
||||
DiagnosticRule.reportInvalidTypeVarUse,
|
||||
DiagnosticRule.reportCallInDefaultInitializer,
|
||||
DiagnosticRule.reportUnnecessaryIsInstance,
|
||||
DiagnosticRule.reportUnnecessaryCast,
|
||||
@ -342,7 +338,6 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'none',
|
||||
reportUnknownMemberType: 'none',
|
||||
reportMissingTypeArgument: 'none',
|
||||
reportInvalidTypeVarUse: 'none',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'none',
|
||||
reportUnnecessaryCast: 'none',
|
||||
@ -400,7 +395,6 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'none',
|
||||
reportUnknownMemberType: 'none',
|
||||
reportMissingTypeArgument: 'none',
|
||||
reportInvalidTypeVarUse: 'none',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'none',
|
||||
reportUnnecessaryCast: 'none',
|
||||
@ -458,7 +452,6 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
reportUnknownVariableType: 'error',
|
||||
reportUnknownMemberType: 'error',
|
||||
reportMissingTypeArgument: 'error',
|
||||
reportInvalidTypeVarUse: 'error',
|
||||
reportCallInDefaultInitializer: 'none',
|
||||
reportUnnecessaryIsInstance: 'error',
|
||||
reportUnnecessaryCast: 'error',
|
||||
@ -1027,13 +1020,6 @@ 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,7 +49,6 @@ export enum DiagnosticRule {
|
||||
reportUnknownVariableType = 'reportUnknownVariableType',
|
||||
reportUnknownMemberType = 'reportUnknownMemberType',
|
||||
reportMissingTypeArgument = 'reportMissingTypeArgument',
|
||||
reportInvalidTypeVarUse = 'reportInvalidTypeVarUse',
|
||||
reportCallInDefaultInitializer = 'reportCallInDefaultInitializer',
|
||||
reportUnnecessaryIsInstance = 'reportUnnecessaryIsInstance',
|
||||
reportUnnecessaryCast = 'reportUnnecessaryCast',
|
||||
|
@ -1,50 +0,0 @@
|
||||
# This sample tests the reporting of incorrect TypeVar usage within
|
||||
# a generic function. A TypeVar must appear at least twice to be
|
||||
# considered legitimate.
|
||||
|
||||
# pyright: reportInvalidTypeVarUse=true
|
||||
|
||||
from typing import Dict, Generic, List, TypeVar
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_S = TypeVar("_S")
|
||||
|
||||
|
||||
class Foo(Generic[_T]):
|
||||
def m1(self, v1: _T) -> None:
|
||||
...
|
||||
|
||||
# This should generate an error because _S
|
||||
# is a local typeVar and appears only once.
|
||||
def m2(self, v1: _S) -> None:
|
||||
...
|
||||
|
||||
# This should generate an error because _S
|
||||
# is a local typeVar and appears only once.
|
||||
def m3(self, v1: _T) -> _S:
|
||||
...
|
||||
|
||||
|
||||
# This should generate an error because _T
|
||||
# is a local typeVar and appears only once.
|
||||
def f1(self, v1: _T) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f2(self, v1: _T, v2: List[_T]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f3(self, v1: _T) -> _T:
|
||||
...
|
||||
|
||||
|
||||
def f4(self) -> Dict[_T, _T]:
|
||||
...
|
||||
|
||||
|
||||
# This should generate an error because _T
|
||||
# is a local typeVar and appears only once.
|
||||
def f5(self) -> List[_T]:
|
||||
...
|
@ -945,12 +945,6 @@ test('TypeVar4', () => {
|
||||
TestUtils.validateResults(analysisResults, 4);
|
||||
});
|
||||
|
||||
test('TypeVar5', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeVar5.py']);
|
||||
|
||||
TestUtils.validateResults(analysisResults, 4);
|
||||
});
|
||||
|
||||
test('Annotated1', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
||||
|
@ -477,17 +477,6 @@
|
||||
"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,12 +321,6 @@
|
||||
"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