Added "reportOverlappingOverload" diagnostic rule, splitting out a few checks that were previously in the "reportGeneralTypeIssue" rule. This allows for finer-grained control over these overload checks.

This commit is contained in:
Eric Traut 2021-02-20 09:28:57 -07:00
parent 9e6163bf34
commit 68fca4eab6
7 changed files with 48 additions and 5 deletions

View File

@ -100,6 +100,8 @@ The following settings control pyrights diagnostic output (warnings or errors
**reportIncompatibleVariableOverride** [boolean or string, optional]: Generate or suppress diagnostics for class variable declarations that override a symbol of the same name in a base class with a type that is incompatible with the base class symbol type. The default value for this setting is 'none'.
**reportOverlappingOverload** [boolean or string, optional]: Generate or suppress diagnostics for function overloads that overlap in signature and obscure each other or have incompatible return types.
**reportInvalidStringEscapeSequence** [boolean or string, optional]: Generate or suppress diagnostics for invalid escape sequences used within string literals. The Python specification indicates that such sequences will generate a syntax error in future versions. The default value for this setting is 'warning'.
**reportUnknownParameterType** [boolean or string, optional]: Generate or suppress diagnostics for input or return parameters for functions or methods that have an unknown type. The default value for this setting is 'none'.
@ -256,6 +258,7 @@ The following table lists the default severity levels for each diagnostic rule w
| reportConstantRedefinition | "none" | "none" | "error" |
| reportIncompatibleMethodOverride | "none" | "none" | "error" |
| reportIncompatibleVariableOverride | "none" | "none" | "error" |
| reportOverlappingOverload | "none" | "none" | "none" |
| reportInvalidStringEscapeSequence | "none" | "warning" | "error" |
| reportUnknownParameterType | "none" | "none" | "error" |
| reportUnknownArgumentType | "none" | "none" | "error" |

View File

@ -1039,8 +1039,8 @@ export class Checker extends ParseTreeWalker {
const prevOverload = prevOverloads[i];
if (this._isOverlappingOverload(functionType, prevOverload)) {
this._evaluator.addDiagnostic(
this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues,
DiagnosticRule.reportGeneralTypeIssues,
this._fileInfo.diagnosticRuleSet.reportOverlappingOverload,
DiagnosticRule.reportOverlappingOverload,
Localizer.Diagnostic.overlappingOverload().format({
name: node.name.value,
obscured: prevOverloads.length + 1,
@ -1071,8 +1071,8 @@ export class Checker extends ParseTreeWalker {
) {
const altNode = this._findNodeForOverload(node, prevOverload);
this._evaluator.addDiagnostic(
this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues,
DiagnosticRule.reportGeneralTypeIssues,
this._fileInfo.diagnosticRuleSet.reportOverlappingOverload,
DiagnosticRule.reportOverlappingOverload,
Localizer.Diagnostic.overloadReturnTypeMismatch().format({
name: node.name.value,
newIndex: prevOverloads.length + 1,

View File

@ -174,6 +174,10 @@ export interface DiagnosticRuleSet {
// the base class symbol of the same name?
reportIncompatibleVariableOverride: DiagnosticLevel;
// Report function overloads that overlap in signature but have
// incompatible return types.
reportOverlappingOverload: DiagnosticLevel;
// Report usage of invalid escape sequences in string literals?
reportInvalidStringEscapeSequence: DiagnosticLevel;
@ -289,6 +293,7 @@ export function getDiagLevelDiagnosticRules() {
DiagnosticRule.reportConstantRedefinition,
DiagnosticRule.reportIncompatibleMethodOverride,
DiagnosticRule.reportIncompatibleVariableOverride,
DiagnosticRule.reportOverlappingOverload,
DiagnosticRule.reportInvalidStringEscapeSequence,
DiagnosticRule.reportUnknownParameterType,
DiagnosticRule.reportUnknownArgumentType,
@ -355,6 +360,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
reportConstantRedefinition: 'none',
reportIncompatibleMethodOverride: 'none',
reportIncompatibleVariableOverride: 'none',
reportOverlappingOverload: 'none',
reportInvalidStringEscapeSequence: 'none',
reportUnknownParameterType: 'none',
reportUnknownArgumentType: 'none',
@ -417,6 +423,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
reportConstantRedefinition: 'none',
reportIncompatibleMethodOverride: 'none',
reportIncompatibleVariableOverride: 'none',
reportOverlappingOverload: 'none',
reportInvalidStringEscapeSequence: 'warning',
reportUnknownParameterType: 'none',
reportUnknownArgumentType: 'none',
@ -479,6 +486,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
reportConstantRedefinition: 'error',
reportIncompatibleMethodOverride: 'error',
reportIncompatibleVariableOverride: 'error',
reportOverlappingOverload: 'none',
reportInvalidStringEscapeSequence: 'error',
reportUnknownParameterType: 'error',
reportUnknownArgumentType: 'error',
@ -1022,6 +1030,13 @@ export class ConfigOptions {
defaultSettings.reportIncompatibleVariableOverride
),
// Read the "reportOverlappingOverload" entry.
reportOverlappingOverload: this._convertDiagnosticLevel(
configObj.reportOverlappingOverload,
DiagnosticRule.reportOverlappingOverload,
defaultSettings.reportOverlappingOverload
),
// Read the "reportInvalidStringEscapeSequence" entry.
reportInvalidStringEscapeSequence: this._convertDiagnosticLevel(
configObj.reportInvalidStringEscapeSequence,

View File

@ -43,6 +43,7 @@ export enum DiagnosticRule {
reportConstantRedefinition = 'reportConstantRedefinition',
reportIncompatibleMethodOverride = 'reportIncompatibleMethodOverride',
reportIncompatibleVariableOverride = 'reportIncompatibleVariableOverride',
reportOverlappingOverload = 'reportOverlappingOverload',
reportInvalidStringEscapeSequence = 'reportInvalidStringEscapeSequence',
reportUnknownParameterType = 'reportUnknownParameterType',
reportUnknownArgumentType = 'reportUnknownArgumentType',

View File

@ -868,7 +868,14 @@ test('Overload4', () => {
});
test('Overload5', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['overload5.py']);
const configOptions = new ConfigOptions('.');
// By default, reportOverlappingOverload is off.
let analysisResults = TestUtils.typeAnalyzeSampleFiles(['overload5.py'], configOptions);
TestUtils.validateResults(analysisResults, 0);
configOptions.diagnosticRuleSet.reportOverlappingOverload = 'error';
analysisResults = TestUtils.typeAnalyzeSampleFiles(['overload5.py'], configOptions);
TestUtils.validateResults(analysisResults, 5);
});

View File

@ -411,6 +411,17 @@
"error"
]
},
"reportOverlappingOverload": {
"type": "string",
"description": "Diagnostics for function overloads that overlap in signature and obscure each other or have incompatible return types.",
"default": "none",
"enum": [
"none",
"information",
"warning",
"error"
]
},
"reportInvalidStringEscapeSequence": {
"type": "string",
"description": "Diagnostics for invalid escape sequences used within string literals. The Python specification indicates that such sequences will generate a syntax error in future versions.",

View File

@ -285,6 +285,12 @@
"title": "Controls reporting of overrides in subclasses that redefine a variable in an incompatible way",
"default": "none"
},
"reportOverlappingOverload": {
"$id": "#/properties/reportOverlappingOverload",
"$ref": "#/definitions/diagnostic",
"title": "Controls reporting of function overloads that overlap in signature and obscure each other or do not agree on return type",
"default": "none"
},
"reportInvalidStringEscapeSequence": {
"$id": "#/properties/reportInvalidStringEscapeSequence",
"$ref": "#/definitions/diagnostic",