From 2abd802fe632fa350ab93d2c4cafdc5637c22115 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 18 Apr 2019 07:45:50 -0700 Subject: [PATCH] Added new config feature: reportUntypedBaseClass. --- client/schemas/pyrightconfig.schema.json | 6 ++++++ docs/configuration.md | 2 ++ server/src/analyzer/semanticAnalyzer.ts | 6 ------ server/src/analyzer/typeAnalyzer.ts | 11 +++++++++++ server/src/common/configOptions.ts | 7 +++++++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/client/schemas/pyrightconfig.schema.json b/client/schemas/pyrightconfig.schema.json index 65b9de218..6d42ce1fd 100644 --- a/client/schemas/pyrightconfig.schema.json +++ b/client/schemas/pyrightconfig.schema.json @@ -121,6 +121,12 @@ "title": "Controls reporting of class decorators without type annotations, which obscure class types", "default": "none" }, + "reportUntypedBaseClass": { + "$id": "#/properties/reportUntypedBaseClass", + "$ref": "#/definitions/diagnostic", + "title": "Controls reporting of a base class of an unknown type, which obscures most type checking for the class", + "default": "none" + }, "reportPrivateUsage": { "$id": "#/properties/reportPrivateUsage", "$ref": "#/definitions/diagnostic", diff --git a/docs/configuration.md b/docs/configuration.md index a368a9c26..ade1617cf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -48,6 +48,8 @@ The following settings control pyright's diagnostic output (warnings or errors). **reportUntypedClassDecorator** [boolean or string, optional]: Generate or suppress diagnostics for class decorators that have no type annotations. These obscure the class type, defeating many type analysis features. +**reportUntypedBaseClass** [boolean or string, optional]: Generate or suppress diagnostics for base classes whose type cannot be determined statically. These obscure the class type, defeating many type analysis features. + **reportPrivateUsage** [boolean or string, optional]: Generate or suppress diagnostics for uses of private variables or functions outside of the class or module that declares them. Private variables and functions, by convention, are named starting with a single underscoe (“_”) character. diff --git a/server/src/analyzer/semanticAnalyzer.ts b/server/src/analyzer/semanticAnalyzer.ts index 81f79f6dd..ceca47ad5 100644 --- a/server/src/analyzer/semanticAnalyzer.ts +++ b/server/src/analyzer/semanticAnalyzer.ts @@ -203,12 +203,6 @@ export abstract class SemanticAnalyzer extends ParseTreeWalker { } } - if (!argType.isAny()) { - if (argType.category !== TypeCategory.Class) { - this._addError(`Argument to class must be a base class`, arg); - } - } - classType.addBaseClass(argType, isMetaclass); if (!isMetaclass) { diff --git a/server/src/analyzer/typeAnalyzer.ts b/server/src/analyzer/typeAnalyzer.ts index bd5254a40..6e7f143a0 100644 --- a/server/src/analyzer/typeAnalyzer.ts +++ b/server/src/analyzer/typeAnalyzer.ts @@ -163,6 +163,17 @@ export class TypeAnalyzer extends ParseTreeWalker { } } + if (this._fileInfo.configOptions.reportUntypedBaseClass !== 'none') { + if (argType instanceof UnknownType || + argType instanceof UnionType && argType.getTypes().some(t => t instanceof UnknownType)) { + + this._addDiagnostic( + this._fileInfo.configOptions.reportUntypedBaseClass, + `Base class type is unknown, obscuring type of derived class`, + arg); + } + } + if (classType.updateBaseClassType(index, argType)) { this._setAnalysisChanged(); } diff --git a/server/src/common/configOptions.ts b/server/src/common/configOptions.ts index 6a90d31e3..ebb4236bb 100644 --- a/server/src/common/configOptions.ts +++ b/server/src/common/configOptions.ts @@ -106,6 +106,9 @@ export class ConfigOptions { // Report untyped class decorators that obscure the class type? reportUntypedClassDecorator: DiagnosticLevel = 'none'; + // Report untyped base class that obscure the class type? + reportUntypedBaseClass: DiagnosticLevel = 'none'; + // Report usage of private variables and functions outside of // the owning class or module? reportPrivateUsage: DiagnosticLevel = 'none'; @@ -250,6 +253,10 @@ export class ConfigOptions { this.reportUntypedClassDecorator = this._convertDiagnosticLevel( configObj.reportUntypedClassDecorator, 'reportUntypedClassDecorator', 'none'); + // Read the "reportUntypedBaseClass" entry. + this.reportUntypedBaseClass = this._convertDiagnosticLevel( + configObj.reportUntypedBaseClass, 'reportUntypedBaseClass', 'none'); + // Read the "reportPrivateUsage" entry. this.reportPrivateUsage = this._convertDiagnosticLevel( configObj.reportPrivateUsage, 'reportPrivateUsage', 'none');