Added config options strictListInference and strictDictionaryInference.

This commit is contained in:
Eric Traut 2019-05-15 22:59:32 -07:00
parent 768cb3f2c2
commit 7d5ff66df2
4 changed files with 57 additions and 9 deletions

View File

@ -61,6 +61,18 @@
],
"pattern": "^(.*)$"
},
"strictListInference": {
"$id": "#/properties/strictListInference",
"type": "boolean",
"title": "Infer strict types for list expressions",
"default": "false"
},
"strictDictionaryInference": {
"$id": "#/properties/strictDictionaryInference",
"type": "boolean",
"title": "Infer strict types for dictionary expressions",
"default": "false"
},
"reportTypeshedErrors": {
"$id": "#/properties/reportTypeshedErrors",
"$ref": "#/definitions/diagnostic",

View File

@ -28,6 +28,10 @@ Pyright offers flexible configuration options specified in a JSON-formatted text
## Type Check Diagnostics Settings
The following settings control pyright's diagnostic output (warnings or errors). Unless otherwise specified, each diagnostic setting can specify a boolean value (`false` indicating that no error is generated and `true` indicating that an error is generated). Alternatively, a string value of `"none"`, `"warning"`, or `"error"` can be used to specify the diagnostic level.
**strictListInference** [boolean]: When inferring the type of a list, use strict type assumptions. For example, the expression `[1, 'a', 3.4]` could be inferred to be of type `List[Any]` or `List[Union[int, str, float]]`. If this setting is true, it will use the latter (stricter) type. The default value for this setting is 'false'.
**strictDictionaryInference** [boolean]: When inferring the type of a dictionarys keys and values, use strict type assumptions. For example, the expression `{'a': 1, 'b': 'a'}` could be inferred to be of type `Dict[str, Any]` or `Dict[str, Union[int, str]]`. If this setting is true, it will use the latter (stricter) type. The default value for this setting is 'false'.
**reportTypeshedErrors** [boolean or string, optional]: Generate or suppress diagnostics for typeshed type stub files. In general, these type stub files should be “clean” and generate no errors. The default value for this setting is 'none'.
**reportMissingImports** [boolean or string, optional]: Generate or suppress diagnostics for imports that have no corresponding imported python file or type stub file. The default value for this setting is 'none', although pyright can do a much better job of static type checking if type stub files are provided for all imports.

View File

@ -2403,12 +2403,17 @@ export class ExpressionEvaluator {
keyType = keyTypes.length > 0 ? TypeUtils.combineTypes(keyTypes) : AnyType.create();
// If the value type differs, we need to back off because we can't
// properly represent the mappings between different keys and associated
// value types. If all the values are the same type, we'll assume that
// all values in this dictionary should be the same.
// If the value type differs and we're not using "strict inference mode",
// we need to back off because we can't properly represent the mappings
// between different keys and associated value types. If all the values
// are the same type, we'll assume that all values in this dictionary should
// be the same.
if (valueTypes.length > 0) {
valueType = TypeUtils.areTypesSame(valueTypes) ? valueTypes[0] : UnknownType.create();
if (this._fileInfo.configOptions.strictDictionaryInference || this._fileInfo.useStrictMode) {
valueType = TypeUtils.combineTypes(valueTypes);
} else {
valueType = TypeUtils.areTypesSame(valueTypes) ? valueTypes[0] : UnknownType.create();
}
} else {
valueType = AnyType.create();
}
@ -2428,11 +2433,13 @@ export class ExpressionEvaluator {
const entryTypes = node.entries.map(
entry => TypeUtils.stripLiteralValue(this.getType(entry)));
// If the list contains only one type, we'll assume the list is
// homogeneous. Otherwise, we'll avoid making assumptions about
// the list entry type.
if (entryTypes.length > 0) {
listEntryType = TypeUtils.areTypesSame(entryTypes) ? entryTypes[0] : UnknownType.create();
if (this._fileInfo.configOptions.strictListInference || this._fileInfo.useStrictMode) {
listEntryType = TypeUtils.combineTypes(entryTypes);
} else {
// Is the list homogeneous? If so, use stricter rules. Otherwise relax the rules.
listEntryType = TypeUtils.areTypesSame(entryTypes) ? entryTypes[0] : UnknownType.create();
}
}
}

View File

@ -79,6 +79,12 @@ export class ConfigOptions {
//---------------------------------------------------------------
// Diagnostics Settings
// Use strict inference rules for list expressions?
strictListInference = false;
// Use strict inference rules for dictionary expressions?
strictDictionaryInference = false;
// Report diagnostics in typeshed files?
reportTypeshedErrors: DiagnosticLevel = 'none';
@ -244,6 +250,14 @@ export class ConfigOptions {
}
}
// Use strict inference rules for list expressions?
this.strictListInference = this._convertBoolean(
configObj.strictListInference, 'strictListInference', false);
// Use strict inference rules for dictionary expressions?
this.strictDictionaryInference = this._convertBoolean(
configObj.strictDictionaryInference, 'strictDictionaryInference', false);
// Read the "reportTypeshedErrors" entry.
this.reportTypeshedErrors = this._convertDiagnosticLevel(
configObj.reportTypeshedErrors, 'reportTypeshedErrors', 'none');
@ -419,6 +433,17 @@ export class ConfigOptions {
return absolutePath;
}
private _convertBoolean(value: any, fieldName: string, defaultValue: boolean): boolean {
if (value === undefined) {
return defaultValue;
} else if (typeof value === 'boolean') {
return value ? true : false;
}
console.log(`Config "${ fieldName }" entry must be true or false.`);
return defaultValue;
}
private _convertDiagnosticLevel(value: any, fieldName: string,
defaultValue: DiagnosticLevel): DiagnosticLevel {