Added two new diagnostic rules: reportInconsistentOverload reports inconsistencies between overload signatures and/or implementation and reportNoOverloadImplementation reports an overloaded function with a missing implementation. This partially addresses #6973. (#7072)

This commit is contained in:
Eric Traut 2024-01-21 00:04:55 -08:00 committed by GitHub
parent 91960fba49
commit 7a67f4fbdb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 8 deletions

View File

@ -92,6 +92,10 @@ The following settings control pyrights diagnostic output (warnings or errors
<a name="reportAssertTypeFailure"></a> **reportAssertTypeFailure** [boolean or string, optional]: Generate or suppress diagnostics for a type mismatch detected by the `typing.assert_type` call. The default value for this setting is `"error"`.
<a name="reportInconsistentOverload"></a> **reportInconsistentOverload** [boolean or string, optional]: Generate or suppress diagnostics for an overloaded function that has overload signatures that are inconsistent with each other or with the implementation. The default value for this setting is `"error"`.
<a name="reportNoOverloadImplementation"></a> **reportNoOverloadImplementation** [boolean or string, optional]: Generate or suppress diagnostics for an overloaded function or method if the implementation is not provided. The default value for this setting is `"error"`.
<a name="reportOptionalSubscript"></a> **reportOptionalSubscript** [boolean or string, optional]: Generate or suppress diagnostics for an attempt to subscript (index) a variable with an Optional type. The default value for this setting is `"error"`.
<a name="reportOptionalMemberAccess"></a> **reportOptionalMemberAccess** [boolean or string, optional]: Generate or suppress diagnostics for an attempt to access a member of a variable with an Optional type. The default value for this setting is `"error"`.
@ -331,6 +335,8 @@ The following table lists the default severity levels for each diagnostic rule w
| reportWildcardImportFromLibrary | "none" | "warning" | "warning" | "error" |
| reportAssertTypeFailure | "none" | "error" | "error" | "error" |
| reportGeneralTypeIssues | "none" | "error" | "error" | "error" |
| reportInconsistentOverload | "none" | "error" | "error" | "error" |
| reportNoOverloadImplementation | "none" | "error" | "error" | "error" |
| reportOptionalSubscript | "none" | "error" | "error" | "error" |
| reportOptionalMemberAccess | "none" | "error" | "error" | "error" |
| reportOptionalCall | "none" | "error" | "error" | "error" |

View File

@ -2575,7 +2575,7 @@ export class Checker extends ParseTreeWalker {
if (staticMethodCount > 0 && staticMethodCount < functionType.overloads.length) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadStaticMethodInconsistent().format({
name: node.name.value,
}),
@ -2585,7 +2585,7 @@ export class Checker extends ParseTreeWalker {
if (classMethodCount > 0 && classMethodCount < functionType.overloads.length) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadClassMethodInconsistent().format({
name: node.name.value,
}),
@ -3023,7 +3023,7 @@ export class Checker extends ParseTreeWalker {
if (overloadedFunctions.length === 1) {
// There should never be a single overload.
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.singleOverload().format({ name }),
primaryDecl.node.name
);
@ -3066,7 +3066,7 @@ export class Checker extends ParseTreeWalker {
// there is an implementation.
if (!exemptMissingImplementation) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportNoOverloadImplementation,
LocMessage.overloadWithoutImplementation().format({
name: primaryDecl.node.name.value,
}),
@ -3080,7 +3080,7 @@ export class Checker extends ParseTreeWalker {
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
if (implementationFunction!.details.declaration) {
const diagnostic = this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadImplementationMismatch().format({
name,
index: index + 1,
@ -5869,7 +5869,7 @@ export class Checker extends ParseTreeWalker {
overloads.forEach((overload) => {
if (FunctionType.isFinal(overload) && overload.details.declaration?.node) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadFinalInconsistencyImpl().format({
name: overload.details.name,
}),
@ -5886,7 +5886,7 @@ export class Checker extends ParseTreeWalker {
overloads.slice(1).forEach((overload, index) => {
if (FunctionType.isFinal(overload) && overload.details.declaration?.node) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadFinalInconsistencyNoImpl().format({
name: overload.details.name,
index: index + 2,

View File

@ -573,7 +573,7 @@ export function addOverloadsToFunctionType(evaluator: TypeEvaluator, node: Funct
if (isPrevOverloadAbstract !== isCurrentOverloadAbstract) {
evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadAbstractMismatch().format({ name: node.name.value }),
node.name
);

View File

@ -162,6 +162,12 @@ export interface DiagnosticRuleSet {
// Report failure of assert_type call?
reportAssertTypeFailure: DiagnosticLevel;
// Report inconsistencies with function overload signatures?
reportInconsistentOverload: DiagnosticLevel;
// Report missing overloaded function implementation?
reportNoOverloadImplementation: DiagnosticLevel;
// Report attempts to subscript (index) an Optional type?
reportOptionalSubscript: DiagnosticLevel;
@ -385,6 +391,8 @@ export function getDiagLevelDiagnosticRules() {
DiagnosticRule.reportDuplicateImport,
DiagnosticRule.reportWildcardImportFromLibrary,
DiagnosticRule.reportAssertTypeFailure,
DiagnosticRule.reportInconsistentOverload,
DiagnosticRule.reportNoOverloadImplementation,
DiagnosticRule.reportOptionalSubscript,
DiagnosticRule.reportOptionalMemberAccess,
DiagnosticRule.reportOptionalCall,
@ -478,6 +486,8 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
reportDuplicateImport: 'none',
reportWildcardImportFromLibrary: 'none',
reportAssertTypeFailure: 'none',
reportInconsistentOverload: 'none',
reportNoOverloadImplementation: 'none',
reportOptionalSubscript: 'none',
reportOptionalMemberAccess: 'none',
reportOptionalCall: 'none',
@ -567,6 +577,8 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
reportDuplicateImport: 'none',
reportWildcardImportFromLibrary: 'warning',
reportAssertTypeFailure: 'error',
reportInconsistentOverload: 'error',
reportNoOverloadImplementation: 'error',
reportOptionalSubscript: 'error',
reportOptionalMemberAccess: 'error',
reportOptionalCall: 'error',
@ -656,6 +668,8 @@ export function getStandardDiagnosticRuleSet(): DiagnosticRuleSet {
reportDuplicateImport: 'none',
reportWildcardImportFromLibrary: 'warning',
reportAssertTypeFailure: 'error',
reportInconsistentOverload: 'error',
reportNoOverloadImplementation: 'error',
reportOptionalSubscript: 'error',
reportOptionalMemberAccess: 'error',
reportOptionalCall: 'error',
@ -745,6 +759,8 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
reportDuplicateImport: 'error',
reportWildcardImportFromLibrary: 'error',
reportAssertTypeFailure: 'error',
reportInconsistentOverload: 'error',
reportNoOverloadImplementation: 'error',
reportOptionalSubscript: 'error',
reportOptionalMemberAccess: 'error',
reportOptionalCall: 'error',

View File

@ -36,6 +36,8 @@ export enum DiagnosticRule {
reportDuplicateImport = 'reportDuplicateImport',
reportWildcardImportFromLibrary = 'reportWildcardImportFromLibrary',
reportAssertTypeFailure = 'reportAssertTypeFailure',
reportInconsistentOverload = 'reportInconsistentOverload',
reportNoOverloadImplementation = 'reportNoOverloadImplementation',
reportOptionalSubscript = 'reportOptionalSubscript',
reportOptionalMemberAccess = 'reportOptionalMemberAccess',
reportOptionalCall = 'reportOptionalCall',

View File

@ -431,6 +431,38 @@
false
]
},
"reportInconsistentOverload": {
"type": [
"string",
"boolean"
],
"description": "Diagnostics for inconsistencies between function overload signatures and implementation.",
"default": "error",
"enum": [
"none",
"information",
"warning",
"error",
true,
false
]
},
"reportNoOverloadImplementation": {
"type": [
"string",
"boolean"
],
"description": "Diagnostics for an overloaded function or method with a missing implementation.",
"default": "error",
"enum": [
"none",
"information",
"warning",
"error",
true,
false
]
},
"reportOptionalSubscript": {
"type": [
"string",

View File

@ -257,6 +257,18 @@
"title": "Controls reporting of type mismatch detected by typing.assert_type call",
"default": "error"
},
"reportInconsistentOverload": {
"$id": "#/properties/reportInconsistentOverload",
"$ref": "#/definitions/diagnostic",
"title": "Controls reporting of inconsistencies between function overload signatures",
"default": "error"
},
"reportNoOverloadImplementation": {
"$id": "#/properties/reportNoOverloadImplementation",
"$ref": "#/definitions/diagnostic",
"title": "Controls reporting of an overloaded function or method with a missing implementation",
"default": "error"
},
"reportOptionalSubscript": {
"$id": "#/properties/reportOptionalSubscript",
"$ref": "#/definitions/diagnostic",