mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-26 10:55:06 +03:00
Changed the behavior of the package type verifier so it does not flag unannotated class or instance variables if a parent class provides a type annotation for a variable of the same name. The type is inherited in this case. Also updated the library guidance to reflect this change.
This commit is contained in:
parent
2090c5f09b
commit
92b4028cd5
@ -74,6 +74,7 @@ Variables:
|
||||
|
||||
Type annotations can be omitted in a few specific cases where the type is obvious from the context:
|
||||
|
||||
* A class or instance variable does not require an annotation if the class inherits from another class that has provided an annotation for the variable of the same name. The type is inherited from the parent class in this case.
|
||||
* Constants that are assigned simple literal values (e.g. `RED = '#F00'` or `MAX_TIMEOUT = 50` or `room_temperature: Final = 20`). A constant is a symbol that is assigned only once and is either annotated with `Final` or is named in all-caps. A constant that is not assigned a simple literal value requires explicit annotations, preferably with a `Final` annotation (e.g. `WOODWINDS: Final[List[str]] = ['Oboe', 'Bassoon']`).
|
||||
* Enum values within an Enum class do not require annotations because they take on the type of the Enum class.
|
||||
* Type aliases do not require annotations. A type alias is a symbol that is defined at a module level with a single assignment where the assigned value is an instantiable type, as opposed to a class instance (e.g. `Foo = Callable[[Literal["a", "b"]], Union[int, str]]` or `Bar = Optional[MyGenericClass[int]]`).
|
||||
|
@ -35,6 +35,7 @@ import { isDunderName, isPrivateOrProtectedName } from './symbolNameUtils';
|
||||
import {
|
||||
ClassType,
|
||||
FunctionType,
|
||||
isClass,
|
||||
isInstantiableClass,
|
||||
isModule,
|
||||
isUnknown,
|
||||
@ -440,7 +441,8 @@ export class PackageTypeVerifier {
|
||||
scopeName: string,
|
||||
symbolTable: SymbolTable,
|
||||
scopeType: ScopeType,
|
||||
publicSymbolMap: PublicSymbolMap
|
||||
publicSymbolMap: PublicSymbolMap,
|
||||
overrideSymbolCallback?: (name: string, symbol: Symbol) => Symbol
|
||||
): boolean {
|
||||
if (this._shouldIgnoreType(report, scopeName)) {
|
||||
return true;
|
||||
@ -467,6 +469,9 @@ export class PackageTypeVerifier {
|
||||
return;
|
||||
}
|
||||
|
||||
if (overrideSymbolCallback) {
|
||||
symbol = overrideSymbolCallback(name, symbol);
|
||||
}
|
||||
const symbolType = this._program.getTypeForSymbol(symbol);
|
||||
|
||||
const typedDecls = symbol.getTypedDeclarations();
|
||||
@ -949,7 +954,24 @@ export class PackageTypeVerifier {
|
||||
type.details.fullName,
|
||||
type.details.fields,
|
||||
ScopeType.Class,
|
||||
publicSymbolMap
|
||||
publicSymbolMap,
|
||||
(name: string, symbol: Symbol) => {
|
||||
// If the symbol within this class is lacking a type declaration,
|
||||
// see if we can find a same-named symbol in a parent class with
|
||||
// a type declaration.
|
||||
if (!symbol.hasTypedDeclarations()) {
|
||||
for (const mroClass of type.details.mro.slice(1)) {
|
||||
if (isClass(mroClass)) {
|
||||
const overrideSymbol = mroClass.details.fields.get(name);
|
||||
if (overrideSymbol && overrideSymbol.hasTypedDeclarations()) {
|
||||
return overrideSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
)
|
||||
) {
|
||||
symbolInfo.typeKnownStatus = TypeKnownStatus.PartiallyUnknown;
|
||||
|
Loading…
Reference in New Issue
Block a user