From 1fde529ada5863289e235def186f62b778d32e24 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:13:36 +0000 Subject: [PATCH] pull-pylance-with-pyright-1.1.369-9716881771 --- .../src/analyzer/importResolver.ts | 222 +++++++++--------- .../src/backgroundAnalysis.ts | 4 +- .../src/backgroundAnalysisBase.ts | 9 +- .../src/backgroundThreadBase.ts | 4 +- .../src/common/collectionUtils.ts | 4 +- packages/pyright-internal/src/common/core.ts | 9 +- .../src/common/envVarUtils.ts | 1 + .../src/languageService/completionProvider.ts | 46 ++-- .../src/localization/localize.ts | 6 +- .../src/localization/package.nls.cs.json | 6 +- .../src/localization/package.nls.de.json | 4 +- .../src/localization/package.nls.es.json | 2 +- .../src/localization/package.nls.fr.json | 2 +- .../src/localization/package.nls.it.json | 2 +- .../src/localization/package.nls.ja.json | 2 +- .../src/localization/package.nls.ko.json | 4 +- .../src/localization/package.nls.pl.json | 2 +- .../src/localization/package.nls.pt-br.json | 6 +- .../src/localization/package.nls.ru.json | 2 +- .../src/localization/package.nls.tr.json | 4 +- .../src/localization/package.nls.zh-cn.json | 2 +- .../src/localization/package.nls.zh-tw.json | 2 +- .../src/tests/completions.test.ts | 87 +++++++ 23 files changed, 270 insertions(+), 162 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/importResolver.ts b/packages/pyright-internal/src/analyzer/importResolver.ts index fba6ea175..3e362bc98 100644 --- a/packages/pyright-internal/src/analyzer/importResolver.ts +++ b/packages/pyright-internal/src/analyzer/importResolver.ts @@ -109,7 +109,8 @@ export class ImportResolver { private _cachedFilesForPath = new Map(); private _cachedDirExistenceForRoot = new Map(); private _stdlibModules: Set | undefined; - protected cachedParentImportResults: ParentDirectoryCache; + + protected readonly cachedParentImportResults: ParentDirectoryCache; constructor(readonly serviceProvider: ServiceProvider, private _configOptions: ConfigOptions, readonly host: Host) { this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([])); @@ -172,7 +173,7 @@ export class ImportResolver { return suggestions; } - const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root); + const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root); const origin = sourceFileUri.getDirectory(); let current: Uri | undefined = origin; @@ -533,7 +534,7 @@ export class ImportResolver { execEnv: ExecutionEnvironment, moduleDescriptor: ImportedModuleDescriptor ): ImportResult { - const importName = this.formatImportName(moduleDescriptor); + const importName = formatImportName(moduleDescriptor); const importFailureInfo: string[] = []; const importResult = this._resolveImportStrict( importName, @@ -559,7 +560,7 @@ export class ImportResolver { } // Check whether the given file is in the parent directory import resolution cache. - const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root); + const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root); if (!this.cachedParentImportResults.checkValidPath(this.fileSystem, sourceFileUri, root)) { return importResult; } @@ -776,74 +777,12 @@ export class ImportResolver { protected getNativeModuleName(uri: Uri): string | undefined { const fileExtension = uri.lastExtension.toLowerCase(); - if (this._isNativeModuleFileExtension(fileExtension)) { + if (_isNativeModuleFileExtension(fileExtension)) { return stripFileExtension(uri.fileName, /* multiDotExtension */ true); } return undefined; } - protected getModuleNameFromPath( - containerPath: Uri, - fileUri: Uri, - stripTopContainerDir = false - ): string | undefined { - const moduleNameInfo = this.getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir); - if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) { - return undefined; - } - - return moduleNameInfo.moduleName; - } - - protected getModuleNameInfoFromPath( - containerPath: Uri, - fileUri: Uri, - stripTopContainerDir = false - ): ModuleNameInfoFromPath | undefined { - let fileUriWithoutExtension = fileUri.stripExtension(); - - // If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'. - if (this._isNativeModuleFileExtension(fileUri.lastExtension)) { - fileUriWithoutExtension = fileUriWithoutExtension.stripExtension(); - } - - if (!fileUriWithoutExtension.startsWith(containerPath)) { - return undefined; - } - - // Strip off the '/__init__' if it's present. - if (fileUriWithoutExtension.pathEndsWith('__init__')) { - fileUriWithoutExtension = fileUriWithoutExtension.getDirectory(); - } - - const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension)); - if (stripTopContainerDir) { - if (parts.length === 0) { - return undefined; - } - parts.shift(); - } - - if (parts.length === 0) { - return undefined; - } - - // Handle the case where the symbol was resolved to a stubs package - // rather than the real package. We'll strip off the "-stubs" suffix - // in this case. - if (parts[0].endsWith(stubsSuffix)) { - parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length); - } - - // Check whether parts contains invalid characters. - const containsInvalidCharacters = parts.some((p) => !this._isIdentifier(p)); - - return { - moduleName: parts.join('.'), - containsInvalidCharacters, - }; - } - // Potentially modifies the ImportResult by removing some or all of the // implicit import entries. Only the imported symbols should be included. protected filterImplicitImports( @@ -880,22 +819,6 @@ export class ImportResolver { return newImportResult; } - protected formatImportName(moduleDescriptor: ImportedModuleDescriptor) { - return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.'); - } - - protected getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri { - if (!this._isDefaultWorkspace(executionRoot)) { - return executionRoot!; - } - - return sourceFileUri.getDirectory(); - } - - private _isDefaultWorkspace(uri: Uri | undefined) { - return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri); - } - private _resolveImportStrict( importName: string, sourceFileUri: Uri, @@ -1119,7 +1042,7 @@ export class ImportResolver { ); if (stdLibTypeshedPath) { - moduleName = this.getModuleNameFromPath(stdLibTypeshedPath, fileUri); + moduleName = getModuleNameFromPath(stdLibTypeshedPath, fileUri); if (moduleName) { const moduleDescriptor: ImportedModuleDescriptor = { leadingDots: 0, @@ -1149,7 +1072,7 @@ export class ImportResolver { // Look for it in the root directory of the execution environment. if (execEnv.root) { - const candidateModuleNameInfo = this.getModuleNameInfoFromPath(execEnv.root, fileUri); + const candidateModuleNameInfo = _getModuleNameInfoFromPath(execEnv.root, fileUri); if (candidateModuleNameInfo) { if (candidateModuleNameInfo.containsInvalidCharacters) { @@ -1163,7 +1086,7 @@ export class ImportResolver { } for (const extraPath of execEnv.extraPaths) { - const candidateModuleNameInfo = this.getModuleNameInfoFromPath(extraPath, fileUri); + const candidateModuleNameInfo = _getModuleNameInfoFromPath(extraPath, fileUri); if (candidateModuleNameInfo) { if (candidateModuleNameInfo.containsInvalidCharacters) { @@ -1182,7 +1105,7 @@ export class ImportResolver { // Check for a typings file. if (this._configOptions.stubPath) { - const candidateModuleNameInfo = this.getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri); + const candidateModuleNameInfo = _getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri); if (candidateModuleNameInfo) { if (candidateModuleNameInfo.containsInvalidCharacters) { @@ -1209,7 +1132,7 @@ export class ImportResolver { ); if (thirdPartyTypeshedPath) { - const candidateModuleName = this.getModuleNameFromPath( + const candidateModuleName = getModuleNameFromPath( thirdPartyTypeshedPath, fileUri, /* stripTopContainerDir */ true @@ -1226,7 +1149,7 @@ export class ImportResolver { const thirdPartyTypeshedPathEx = this.getTypeshedPathEx(execEnv, importFailureInfo); if (thirdPartyTypeshedPathEx) { - const candidateModuleName = this.getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri); + const candidateModuleName = getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri); // Does this candidate look better than the previous best module name? // We'll always try to use the shortest version. @@ -1241,7 +1164,7 @@ export class ImportResolver { const pythonSearchPaths = this.getPythonSearchPaths(importFailureInfo); for (const searchPath of pythonSearchPaths) { - const candidateModuleNameInfo = this.getModuleNameInfoFromPath(searchPath, fileUri); + const candidateModuleNameInfo = _getModuleNameInfoFromPath(searchPath, fileUri); if (candidateModuleNameInfo) { if (candidateModuleNameInfo.containsInvalidCharacters) { @@ -1260,7 +1183,7 @@ export class ImportResolver { } if (detectPyTyped && importType === ImportType.ThirdParty) { - const root = this.getParentImportResolutionRoot(fileUri, execEnv.root); + const root = getParentImportResolutionRoot(fileUri, execEnv.root); // Go up directories one by one looking for a py.typed file. let current: Uri | undefined = fileUri.getDirectory(); @@ -1552,7 +1475,7 @@ export class ImportResolver { moduleDescriptor: ImportedModuleDescriptor, allowPyi: boolean ): ImportResult | undefined { - const importName = this.formatImportName(moduleDescriptor); + const importName = formatImportName(moduleDescriptor); const importFailureInfo: string[] = []; // Check for a local stub file using stubPath. @@ -1828,16 +1751,6 @@ export class ImportResolver { return bestImportSoFar; } - private _isIdentifier(value: string) { - for (let i = 0; i < value.length; i++) { - if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) { - return false; - } - } - - return true; - } - private _findTypeshedPath( execEnv: ExecutionEnvironment, moduleDescriptor: ImportedModuleDescriptor, @@ -2588,7 +2501,7 @@ export class ImportResolver { // Make sure we don't use parent folder resolution when checking whether the given name is resolvable. let importResult: ImportResult | undefined; if (strictOnly) { - const importName = this.formatImportName(moduleDescriptor); + const importName = formatImportName(moduleDescriptor); const importFailureInfo: string[] = []; importResult = this._resolveImportStrict( @@ -2653,7 +2566,7 @@ export class ImportResolver { if (fileExt === '.py' || fileExt === '.pyi') { strippedFileName = stripFileExtension(filePath.fileName); } else if ( - this._isNativeModuleFileExtension(fileExt) && + _isNativeModuleFileExtension(fileExt) && !this.fileExistsCached(filePath.packageUri) && !this.fileExistsCached(filePath.packageStubUri) ) { @@ -2770,15 +2683,10 @@ export class ImportResolver { const fileExtension = fileUri.lastExtension.toLowerCase(); const withoutExtension = stripFileExtension(fileUri.fileName, /* multiDotExtension */ true); return ( - this._isNativeModuleFileExtension(fileExtension) && - equateStringsCaseInsensitive(moduleName, withoutExtension) + _isNativeModuleFileExtension(fileExtension) && equateStringsCaseInsensitive(moduleName, withoutExtension) ); } - private _isNativeModuleFileExtension(fileExtension: string): boolean { - return supportedNativeLibExtensions.some((ext) => ext === fileExtension); - } - private _tryWalkUp(current: Uri | undefined): Uri | undefined { if (!current || current.isEmpty() || current.isRoot()) { return undefined; @@ -2796,7 +2704,7 @@ export class ImportResolver { return ( current && !current.isEmpty() && - (current.isChild(root) || (current.equals(root) && this._isDefaultWorkspace(execEnv.root))) + (current.isChild(root) || (current.equals(root) && _isDefaultWorkspace(execEnv.root))) ); } } @@ -2806,3 +2714,95 @@ export type ImportResolverFactory = ( options: ConfigOptions, host: Host ) => ImportResolver; + +export function formatImportName(moduleDescriptor: ImportedModuleDescriptor) { + return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.'); +} + +export function getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri { + if (!_isDefaultWorkspace(executionRoot)) { + return executionRoot!; + } + + return sourceFileUri.getDirectory(); +} + +export function getModuleNameFromPath( + containerPath: Uri, + fileUri: Uri, + stripTopContainerDir = false +): string | undefined { + const moduleNameInfo = _getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir); + if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) { + return undefined; + } + + return moduleNameInfo.moduleName; +} + +function _getModuleNameInfoFromPath( + containerPath: Uri, + fileUri: Uri, + stripTopContainerDir = false +): ModuleNameInfoFromPath | undefined { + let fileUriWithoutExtension = fileUri.stripExtension(); + + // If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'. + if (_isNativeModuleFileExtension(fileUri.lastExtension)) { + fileUriWithoutExtension = fileUriWithoutExtension.stripExtension(); + } + + if (!fileUriWithoutExtension.startsWith(containerPath)) { + return undefined; + } + + // Strip off the '/__init__' if it's present. + if (fileUriWithoutExtension.pathEndsWith('__init__')) { + fileUriWithoutExtension = fileUriWithoutExtension.getDirectory(); + } + + const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension)); + if (stripTopContainerDir) { + if (parts.length === 0) { + return undefined; + } + parts.shift(); + } + + if (parts.length === 0) { + return undefined; + } + + // Handle the case where the symbol was resolved to a stubs package + // rather than the real package. We'll strip off the "-stubs" suffix + // in this case. + if (parts[0].endsWith(stubsSuffix)) { + parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length); + } + + // Check whether parts contains invalid characters. + const containsInvalidCharacters = parts.some((p) => !_isIdentifier(p)); + + return { + moduleName: parts.join('.'), + containsInvalidCharacters, + }; +} + +function _isNativeModuleFileExtension(fileExtension: string): boolean { + return supportedNativeLibExtensions.some((ext) => ext === fileExtension); +} + +function _isDefaultWorkspace(uri: Uri | undefined) { + return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri); +} + +function _isIdentifier(value: string) { + for (let i = 0; i < value.length; i++) { + if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) { + return false; + } + } + + return true; +} diff --git a/packages/pyright-internal/src/backgroundAnalysis.ts b/packages/pyright-internal/src/backgroundAnalysis.ts index 579047123..852bed50a 100644 --- a/packages/pyright-internal/src/backgroundAnalysis.ts +++ b/packages/pyright-internal/src/backgroundAnalysis.ts @@ -24,11 +24,13 @@ export class BackgroundAnalysis extends BackgroundAnalysisBase { constructor(serviceProvider: ServiceProvider) { super(serviceProvider.console()); + const index = ++BackgroundAnalysis._workerIndex; const initialData: InitializationData = { rootUri: getRootUri(serviceProvider)?.toString() ?? '', + serviceId: index.toString(), cancellationFolderName: getCancellationFolderName(), runner: undefined, - workerIndex: ++BackgroundAnalysis._workerIndex, + workerIndex: index, }; // this will load this same file in BG thread and start listener diff --git a/packages/pyright-internal/src/backgroundAnalysisBase.ts b/packages/pyright-internal/src/backgroundAnalysisBase.ts index c0368ebac..9bd3d49fb 100644 --- a/packages/pyright-internal/src/backgroundAnalysisBase.ts +++ b/packages/pyright-internal/src/backgroundAnalysisBase.ts @@ -310,7 +310,14 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase const console = this.getConsole(); this.logTracker = new LogTracker(console, `BG(${threadId})`); - this._program = new Program(this.importResolver, this._configOptions, serviceProvider, this.logTracker); + this._program = new Program( + this.importResolver, + this._configOptions, + serviceProvider, + this.logTracker, + undefined, + data.serviceId + ); } get program(): Program { diff --git a/packages/pyright-internal/src/backgroundThreadBase.ts b/packages/pyright-internal/src/backgroundThreadBase.ts index 8775b2615..5f39836f6 100644 --- a/packages/pyright-internal/src/backgroundThreadBase.ts +++ b/packages/pyright-internal/src/backgroundThreadBase.ts @@ -251,10 +251,10 @@ export function getBackgroundWaiter(port: MessagePort, deserializer: (v: any) export interface InitializationData { rootUri: string; + serviceId: string; + workerIndex: number; cancellationFolderName: string | undefined; runner: string | undefined; - title?: string; - workerIndex: number; } export interface RequestResponse { diff --git a/packages/pyright-internal/src/common/collectionUtils.ts b/packages/pyright-internal/src/common/collectionUtils.ts index 6456f881b..3311a09fa 100644 --- a/packages/pyright-internal/src/common/collectionUtils.ts +++ b/packages/pyright-internal/src/common/collectionUtils.ts @@ -6,7 +6,7 @@ * Helper functions relating to collections and arrays. */ -import { compareValues, Comparison, equateValues, isArray } from './core'; +import { compareValues, Comparison, equateValues, isArray, MapLike } from './core'; export const emptyArray: never[] = [] as never[]; export type EqualityComparer = (a: T, b: T) => boolean; @@ -318,7 +318,7 @@ export function getNestedProperty(object: any, property: string) { return value; } -export function getOrAdd(map: Map, key: K, newValueFactory: () => V): V { +export function getOrAdd(map: MapLike, key: K, newValueFactory: () => V): V { const value = map.get(key); if (value !== undefined) { return value; diff --git a/packages/pyright-internal/src/common/core.ts b/packages/pyright-internal/src/common/core.ts index c82d31cc4..269043952 100644 --- a/packages/pyright-internal/src/common/core.ts +++ b/packages/pyright-internal/src/common/core.ts @@ -102,8 +102,11 @@ const hasOwnProperty = Object.prototype.hasOwnProperty; * The `in` and `for-in` operators can *not* be safely used, * since `Object.prototype` may be modified by outside code. */ -export interface MapLike { - [index: string]: T; +export interface MapLike { + readonly [Symbol.toStringTag]: string; + get(key: K): V | undefined; + has(key: K): boolean; + set(key: K, value: V): this; } /** @@ -112,7 +115,7 @@ export interface MapLike { * @param map A map-like. * @param key A property key. */ -export function hasProperty(map: MapLike, key: string): boolean { +export function hasProperty(map: { [index: string]: any }, key: string): boolean { return hasOwnProperty.call(map, key); } diff --git a/packages/pyright-internal/src/common/envVarUtils.ts b/packages/pyright-internal/src/common/envVarUtils.ts index 17911db80..5a5b4457a 100644 --- a/packages/pyright-internal/src/common/envVarUtils.ts +++ b/packages/pyright-internal/src/common/envVarUtils.ts @@ -70,6 +70,7 @@ export function expandPathVariables(path: string, rootPath: Uri, workspaces: Wor const ws_regexp = RegExp(`\\$\\{workspaceFolder:${escapedWorkspaceName}\\}`, 'g'); path = path.replace(ws_regexp, workspace.rootUri.getPath()); } + if (process.env.HOME !== undefined) { replace(/\$\{env:HOME\}/g, process.env.HOME || ''); } diff --git a/packages/pyright-internal/src/languageService/completionProvider.ts b/packages/pyright-internal/src/languageService/completionProvider.ts index 8c5fcc7f6..23fe7e396 100644 --- a/packages/pyright-internal/src/languageService/completionProvider.ts +++ b/packages/pyright-internal/src/languageService/completionProvider.ts @@ -46,6 +46,7 @@ import { printLiteralValue } from '../analyzer/typePrinter'; import { ClassType, combineTypes, + EnumLiteral, FunctionType, isClass, isClassInstance, @@ -127,6 +128,7 @@ import { import { DocumentSymbolCollector } from './documentSymbolCollector'; import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils'; import '../common/serviceProviderExtensions'; +import { transformTypeForEnumMember } from '../analyzer/enums'; namespace Keywords { const base: string[] = [ @@ -705,13 +707,7 @@ export class CompletionProvider { // Handle enum members specially. Enum members normally look like // variables, but the are declared using assignment expressions // within an enum class. - if ( - primaryDecl.type === DeclarationType.Variable && - detail.boundObjectOrClass && - isInstantiableClass(detail.boundObjectOrClass) && - ClassType.isEnumClass(detail.boundObjectOrClass) && - primaryDecl.node.parent?.nodeType === ParseNodeType.Assignment - ) { + if (this._isEnumMember(detail.boundObjectOrClass, name)) { itemKind = CompletionItemKind.EnumMember; } @@ -757,19 +753,16 @@ export class CompletionProvider { if (isClass(subtype)) { const instance = TypeBase.isInstance(subtype); - if (ClassType.isEnumClass(subtype) && instance) { - // We don't add members for instances of enum members, but do add members of `enum.Enum` itself. - // ex) 'MyEnum.member.' <= here - const enumType = subtype.details.baseClasses.find( - (t) => isClass(t) && ClassType.isBuiltIn(t, 'Enum') - ) as ClassType | undefined; - if (!enumType) { - return; - } + getMembersForClass(subtype, symbolTable, instance); - getMembersForClass(enumType, symbolTable, /* instance */ true); - } else { - getMembersForClass(subtype, symbolTable, instance); + if (ClassType.isEnumClass(subtype) && instance) { + // Don't show enum member out of another enum member + // ex) Enum.Member. <= shouldn't show `Member` again. + for (const name of symbolTable.keys()) { + if (this._isEnumMember(subtype, name)) { + symbolTable.delete(name); + } + } } } else if (isModule(subtype)) { getMembersForModule(subtype, symbolTable); @@ -3143,6 +3136,21 @@ export class CompletionProvider { // before doing more expensive type evaluation. return decl.isMethod && decl.node.decorators.length > 0; } + + private _isEnumMember(containingType: ClassType | undefined, name: string) { + if (!containingType || !ClassType.isEnumClass(containingType)) { + return false; + } + + const symbolType = transformTypeForEnumMember(this.evaluator, containingType, name); + + return ( + symbolType && + isClassInstance(symbolType) && + ClassType.isSameGenericClass(symbolType, containingType) && + symbolType.literalValue instanceof EnumLiteral + ); + } } export class CompletionMap { diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index 06c94d41f..8c47b714f 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -118,7 +118,7 @@ export function setLocaleOverride(locale: string) { localeOverride = locale.toLowerCase(); } -export function getLocaleFromEnv() { +export function getLocaleFromEnv(): string { if (localeOverride) { return localeOverride; } @@ -130,7 +130,7 @@ export function getLocaleFromEnv() { const vscodeConfigString = env?.VSCODE_NLS_CONFIG; if (vscodeConfigString) { try { - return JSON.parse(vscodeConfigString).locale; + return JSON.parse(vscodeConfigString).locale || defaultLocale; } catch { // Fall through } @@ -142,7 +142,7 @@ export function getLocaleFromEnv() { // This string may contain a local followed by an encoding (e.g. "en-us.UTF-8"). const localeStringSplit = localeString.split('.'); if (localeStringSplit.length > 0 && localeStringSplit[0]) { - return localeStringSplit[0]; + return localeStringSplit[0] || defaultLocale; } } } catch { diff --git a/packages/pyright-internal/src/localization/package.nls.cs.json b/packages/pyright-internal/src/localization/package.nls.cs.json index b4df26b34..91e443960 100644 --- a/packages/pyright-internal/src/localization/package.nls.cs.json +++ b/packages/pyright-internal/src/localization/package.nls.cs.json @@ -158,8 +158,8 @@ "enumMemberDelete": "Člen výčtu {name} se nedá odstranit.", "enumMemberSet": "Člen výčtu {name} se nedá přiřadit.", "enumMemberTypeAnnotation": "Poznámky typu nejsou pro členy výčtu povolené", - "exceptionGroupIncompatible": "Syntaxe skupiny výjimek (except*) vyžaduje Python 3.11 nebo novější", - "exceptionGroupTypeIncorrect": "Typ výjimky v kromě* se nedá odvodit z BaseGroupException.", + "exceptionGroupIncompatible": "Syntaxe skupiny výjimek (\"except*\") vyžaduje Python 3.11 nebo novější", + "exceptionGroupTypeIncorrect": "Typ výjimky v except* se nedá odvodit z BaseGroupException.", "exceptionTypeIncorrect": "„{type}“ se neodvozuje od BaseException", "exceptionTypeNotClass": "{type} není platná třída výjimky", "exceptionTypeNotInstantiable": "Konstruktor pro výjimku typu {type} vyžaduje jeden nebo více argumentů", @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Argumenty typu nejsou u třídy Protocol povoleny při použití syntaxe parametru typu", "protocolIllegal": "Použití protokolu vyžaduje Python 3.7 nebo novější", "protocolNotAllowed": "„Protocol“ nejde v tomto kontextu použít.", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "Argument typu pro „protokol“ musí být parametr typu", "protocolUnsafeOverlap": "Třída se nebezpečně překrývá s názvem „{name}“ a může vytvořit shodu při spuštění.", "protocolVarianceContravariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kontravariantní", "protocolVarianceCovariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kovariantní", diff --git a/packages/pyright-internal/src/localization/package.nls.de.json b/packages/pyright-internal/src/localization/package.nls.de.json index 666913cbb..a45fa71b4 100644 --- a/packages/pyright-internal/src/localization/package.nls.de.json +++ b/packages/pyright-internal/src/localization/package.nls.de.json @@ -159,7 +159,7 @@ "enumMemberSet": "Das Enumerationselement \"{name}\" kann nicht zugewiesen werden.", "enumMemberTypeAnnotation": "Typanmerkungen sind für Enumerationsmember nicht zulässig", "exceptionGroupIncompatible": "Die Ausnahmegruppensyntax (\"except*\") erfordert Python 3.11 oder höher.", - "exceptionGroupTypeIncorrect": "Der Ausnahmetyp in „except*“ kann nicht von BaseGroupException abgeleitet werden.", + "exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.", "exceptionTypeIncorrect": "\"{type}\" ist nicht von BaseException abgeleitet.", "exceptionTypeNotClass": "\"{type}\" ist keine gültige Ausnahmeklasse.", "exceptionTypeNotInstantiable": "Der Konstruktor für den Ausnahmetyp \"{type}\" erfordert mindestens ein Argument.", @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Typargumente sind mit der Protokollklasse nicht zulässig, wenn die Typparametersyntax verwendet wird.", "protocolIllegal": "Die Verwendung von \"Protocol\" erfordert Python 3.7 oder höher.", "protocolNotAllowed": "\"Protocol\" kann in diesem Kontext nicht verwendet werden.", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "Das Typargument für „Protocol“ muss ein Typparameter sein.", "protocolUnsafeOverlap": "Die Klasse überlappt unsicher mit „{name}“ und könnte zur Laufzeit eine Übereinstimmung erzeugen.", "protocolVarianceContravariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"contravariant\" sein.", "protocolVarianceCovariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"covariant\" sein.", diff --git a/packages/pyright-internal/src/localization/package.nls.es.json b/packages/pyright-internal/src/localization/package.nls.es.json index 0bbf5cd93..73daf4ced 100644 --- a/packages/pyright-internal/src/localization/package.nls.es.json +++ b/packages/pyright-internal/src/localization/package.nls.es.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "No se permiten argumentos de tipo con la clase Protocol cuando se usa la sintaxis de parámetro de tipo", "protocolIllegal": "El uso de \"Protocolo\" requiere Python 3.7 o posterior.", "protocolNotAllowed": "\"Protocolo\" no puede utilizarse en este contexto", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "El argumento de tipo para \"Protocol\" debe ser un parámetro de tipo", "protocolUnsafeOverlap": "La clase se superpone \"{name}\" de forma no segura y podría producir una coincidencia en tiempo de ejecución", "protocolVarianceContravariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser contravariante.", "protocolVarianceCovariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser covariante", diff --git a/packages/pyright-internal/src/localization/package.nls.fr.json b/packages/pyright-internal/src/localization/package.nls.fr.json index f7a882115..c9c4b6900 100644 --- a/packages/pyright-internal/src/localization/package.nls.fr.json +++ b/packages/pyright-internal/src/localization/package.nls.fr.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Les arguments de type ne sont pas autorisés avec la classe Protocol lors de l'utilisation de la syntaxe des paramètres de type", "protocolIllegal": "L’utilisation de « Protocole » nécessite Python 3.7 ou une version plus récente", "protocolNotAllowed": "\"Protocole\" ne peut pas être utilisé dans ce contexte", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "L’argument de type pour « Protocol » doit être un paramètre de type", "protocolUnsafeOverlap": "La classe chevauche « {name} » de manière non sécurisée et peut produire une correspondance au moment de l’exécution", "protocolVarianceContravariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être contravariante", "protocolVarianceCovariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être covariante", diff --git a/packages/pyright-internal/src/localization/package.nls.it.json b/packages/pyright-internal/src/localization/package.nls.it.json index 599bc9fb1..771dd88fe 100644 --- a/packages/pyright-internal/src/localization/package.nls.it.json +++ b/packages/pyright-internal/src/localization/package.nls.it.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Gli argomenti tipo non sono consentiti con la classe Protocollo quando si usa la sintassi dei parametri tipo", "protocolIllegal": "L'uso del \"protocollo\" richiede Python 3.7 o versione successiva", "protocolNotAllowed": "\"Protocol\" non può essere usato in questo contesto", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "L'argomento di tipo per \"Protocol\" deve essere un parametro di tipo", "protocolUnsafeOverlap": "La classe si sovrappone a \"{name}\" in modo non sicuro e può produrre una corrispondenza in fase di esecuzione", "protocolVarianceContravariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere controvariante", "protocolVarianceCovariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere covariante", diff --git a/packages/pyright-internal/src/localization/package.nls.ja.json b/packages/pyright-internal/src/localization/package.nls.ja.json index 3afee55c0..b8037b565 100644 --- a/packages/pyright-internal/src/localization/package.nls.ja.json +++ b/packages/pyright-internal/src/localization/package.nls.ja.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "型パラメーター構文を使用する場合、Protocol クラスでは型引数を使用できません", "protocolIllegal": "\"Protocol\" を使用するには Python 3.7 以降が必要です", "protocolNotAllowed": "\"Protocol\" はこのコンテキストでは使用できません", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "\"Protocol\" の型引数は型パラメーターである必要があります", "protocolUnsafeOverlap": "クラスが安全でない方法で \"{name}\" と重複しており、実行時に一致する可能性があります", "protocolVarianceContravariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は反変である必要があります", "protocolVarianceCovariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は共変である必要があります", diff --git a/packages/pyright-internal/src/localization/package.nls.ko.json b/packages/pyright-internal/src/localization/package.nls.ko.json index 3b3075e20..1a6ce84a7 100644 --- a/packages/pyright-internal/src/localization/package.nls.ko.json +++ b/packages/pyright-internal/src/localization/package.nls.ko.json @@ -159,7 +159,7 @@ "enumMemberSet": "열거형 멤버 \"{name}\"을(를) 할당할 수 없음", "enumMemberTypeAnnotation": "열거형 멤버에는 형식 주석을 사용할 수 없습니다.", "exceptionGroupIncompatible": "예외 그룹 구문(\"except*\")에는 Python 3.11 이상이 필요합니다.", - "exceptionGroupTypeIncorrect": "exception*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.", + "exceptionGroupTypeIncorrect": "except*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.", "exceptionTypeIncorrect": "‘{type}’은 BaseException에서 파생되지 않습니다.", "exceptionTypeNotClass": "\"{type}\"은(는) 올바른 예외 클래스가 아닙니다.", "exceptionTypeNotInstantiable": "예외 형식 \"{type}\"에 대한 생성자에는 하나 이상의 인수가 필요합니다.", @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "형식 매개 변수 구문을 사용할 때는 Protocol 클래스에 형식 인수가 허용되지 않습니다.", "protocolIllegal": "\"프로토콜\"을 사용하려면 Python 3.7 이상이 필요합니다.", "protocolNotAllowed": "이 컨텍스트에서는 \"Protocol\"을 사용할 수 없습니다.", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "\"Protocol\"의 형식 인수는 형식 매개 변수여야 합니다.", "protocolUnsafeOverlap": "클래스가 \"{name}\"과(와) 안전하지 않게 겹치며 런타임에 일치 항목을 생성할 수 있습니다.", "protocolVarianceContravariant": "‘{class}‘ 제네릭 프로토콜에서 사용되는 ’{variable}‘ 형식 변수는 반공변이어야 합니다.", "protocolVarianceCovariant": "‘{class}‘ 제네릭 프로토콜에서 사용되는 ’{variable}‘ 형식 변수는 공변이어야 합니다", diff --git a/packages/pyright-internal/src/localization/package.nls.pl.json b/packages/pyright-internal/src/localization/package.nls.pl.json index 736a5d4dd..440a5bf5e 100644 --- a/packages/pyright-internal/src/localization/package.nls.pl.json +++ b/packages/pyright-internal/src/localization/package.nls.pl.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Argumenty typu są niedozwolone w przypadku klasy protokołu, gdy jest używana składnia parametru typu", "protocolIllegal": "Użycie elementu „Protocol” wymaga języka Python w wersji 3.7 lub nowszej", "protocolNotAllowed": "„Protokół” nie może być używany w tym kontekście", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "Argument typu dla elementy „Protocol” musi być parametrem typu", "protocolUnsafeOverlap": "Klasa nakłada się niebezpiecznie na element „{name}” i może utworzyć dopasowanie w czasie wykonywania", "protocolVarianceContravariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kontrawariantna", "protocolVarianceCovariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kowariantna", diff --git a/packages/pyright-internal/src/localization/package.nls.pt-br.json b/packages/pyright-internal/src/localization/package.nls.pt-br.json index 5934ec1dd..fc71b2676 100644 --- a/packages/pyright-internal/src/localization/package.nls.pt-br.json +++ b/packages/pyright-internal/src/localization/package.nls.pt-br.json @@ -158,8 +158,8 @@ "enumMemberDelete": "O membro enumerado \"{name}\" não pode ser excluído", "enumMemberSet": "O membro enumerado \"{name}\" não pode ser atribuído", "enumMemberTypeAnnotation": "Anotações de tipo não são permitidas para membros de enumeração", - "exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"exceto*\") requer o Python 3.11 ou mais recente", - "exceptionGroupTypeIncorrect": "O tipo de exceção em exceto* não pode derivar de BaseGroupException", + "exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"except*\") requer o Python 3.11 ou mais recente", + "exceptionGroupTypeIncorrect": "O tipo de exceção em except* não pode derivar de BaseGroupException", "exceptionTypeIncorrect": "\"{type}\" não deriva de BaseException", "exceptionTypeNotClass": "\"{type}\" não é uma classe de exceção válida", "exceptionTypeNotInstantiable": "O construtor para o tipo de exceção \"{type}\" requer um ou mais argumentos", @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Argumentos de tipo não são permitidos com a classe Protocol ao usar a sintaxe de parâmetro de tipo", "protocolIllegal": "O uso de \"Protocol\" requer o Python 3.7 ou mais recente", "protocolNotAllowed": "\"Protocol\" não pode ser usado nesse contexto", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "O argumento de tipo para o \"Protocolo\" deve ser um parâmetro de tipo", "protocolUnsafeOverlap": "A classe se sobrepõe a \"{name}\" de forma não segura e pode produzir uma correspondência em runtime", "protocolVarianceContravariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser contravariante", "protocolVarianceCovariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser covariante", diff --git a/packages/pyright-internal/src/localization/package.nls.ru.json b/packages/pyright-internal/src/localization/package.nls.ru.json index 18e5477f3..e29f99b4b 100644 --- a/packages/pyright-internal/src/localization/package.nls.ru.json +++ b/packages/pyright-internal/src/localization/package.nls.ru.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Аргументы типа не допускаются с классом протокола при использовании синтаксиса параметра типа", "protocolIllegal": "Ключевое слово \"Protocol\" можно использовать в Python версии не ниже 3.7", "protocolNotAllowed": "Невозможно использовать \"Protocol\" в этом контексте", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "Аргумент типа для параметра \"Protocol\" должен быть параметром типа", "protocolUnsafeOverlap": "Класс небезопасно перекрывает \"{name}\" и может вызвать совпадение во время выполнения", "protocolVarianceContravariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть контравариантной.", "protocolVarianceCovariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть ковариантной", diff --git a/packages/pyright-internal/src/localization/package.nls.tr.json b/packages/pyright-internal/src/localization/package.nls.tr.json index db0e01230..2802b3ba9 100644 --- a/packages/pyright-internal/src/localization/package.nls.tr.json +++ b/packages/pyright-internal/src/localization/package.nls.tr.json @@ -159,7 +159,7 @@ "enumMemberSet": "Sabit liste üyesi \"{name}\" atanamıyor", "enumMemberTypeAnnotation": "Sabit listesi üyeleri için tür ek açıklamalarına izin verilmiyor", "exceptionGroupIncompatible": "Özel durum grubu söz dizimi (\"except*\") için Python 3.11 veya daha yeni bir sürümü gerekiyor", - "exceptionGroupTypeIncorrect": "Except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor", + "exceptionGroupTypeIncorrect": "except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor", "exceptionTypeIncorrect": "\"{type}\", BaseException türevi değil", "exceptionTypeNotClass": "\"{type}\" geçerli bir özel durum sınıfı değil", "exceptionTypeNotInstantiable": "\"{type}\" özel durum türü oluşturucusu bir veya daha fazla bağımsız değişken gerektiriyor", @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "Tür parametresi söz dizimi kullanılırken, tür bağımsız değişkenlerinin Protokol sınıfıyla kullanılmasına izin verilmez", "protocolIllegal": "\"Protocol\" kullanımı için Python 3.7 veya daha yeni bir sürümü gerekiyor", "protocolNotAllowed": "\"Protokol\" bu bağlamda kullanılamaz", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "“Protokol” için tür bağımsız değişkeni bir tür parametresi olmalıdır", "protocolUnsafeOverlap": "Sınıf, \"{name}\" ile güvenli olmayan bir şekilde çakışıyor ve çalışma zamanında bir eşleşme üretebilir", "protocolVarianceContravariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni, değişken karşıtı olmalıdır", "protocolVarianceCovariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni birlikte değişen olmalıdır", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-cn.json b/packages/pyright-internal/src/localization/package.nls.zh-cn.json index e0a3b416f..3306e6c71 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-cn.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-cn.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "使用类型参数语法时,协议类不允许使用类型参数", "protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更高版本", "protocolNotAllowed": "\"Protocol\" 不能用于此上下文", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "“协议”的类型参数必须是类型参数", "protocolUnsafeOverlap": "类与“{name}”不安全地重叠,并且可能在运行时生成匹配项", "protocolVarianceContravariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为逆变", "protocolVarianceCovariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为协变", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-tw.json b/packages/pyright-internal/src/localization/package.nls.zh-tw.json index 0907de171..92d5e3e16 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-tw.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-tw.json @@ -403,7 +403,7 @@ "protocolBaseClassWithTypeArgs": "使用型別參數語法時,通訊協定類別不允許使用型別引數", "protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更新版本", "protocolNotAllowed": "\"Protocol\" 不能用在此內容中", - "protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", + "protocolTypeArgMustBeTypeParam": "“Protocol” 的型別引數必須是型別參數", "protocolUnsafeOverlap": "類別以不安全方式重疊 \"{name}\",且可能會在運行時間產生相符專案", "protocolVarianceContravariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為逆變數", "protocolVarianceCovariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為共變數", diff --git a/packages/pyright-internal/src/tests/completions.test.ts b/packages/pyright-internal/src/tests/completions.test.ts index 10c21096e..6bd5321e5 100644 --- a/packages/pyright-internal/src/tests/completions.test.ts +++ b/packages/pyright-internal/src/tests/completions.test.ts @@ -1302,3 +1302,90 @@ test('import from completion for namespace package', async () => { }, }); }); + +test('members off enum member', async () => { + const code = ` +// @filename: test.py +//// from enum import Enum +//// class Planet(Enum): +//// MERCURY = (3.303e+23, 2.4397e6) +//// EARTH = (5.976e+24, 6.37814e6) +//// +//// def __init__(self, mass, radius): +//// self.mass = mass # in kilograms +//// self.radius = radius # in meters +//// +//// @property +//// def surface_gravity(self): +//// # universal gravitational constant (m3 kg-1 s-2) +//// G = 6.67300E-11 +//// return G * self.mass / (self.radius * self.radius) +//// +//// Planet.EARTH.[|/*marker*/|] + `; + + const state = parseAndGetTestState(code).state; + + await state.verifyCompletion('excluded', 'markdown', { + ['marker']: { + completions: [ + { + label: 'MERCURY', + kind: CompletionItemKind.EnumMember, + }, + { + label: 'EARTH', + kind: CompletionItemKind.EnumMember, + }, + ], + }, + }); + + await state.verifyCompletion('included', 'markdown', { + ['marker']: { + completions: [ + { + label: 'mass', + kind: CompletionItemKind.Variable, + }, + { + label: 'radius', + kind: CompletionItemKind.Variable, + }, + { + label: 'surface_gravity', + kind: CompletionItemKind.Property, + }, + ], + }, + }); +}); + +test('enum with regular base type', async () => { + const code = ` +// @filename: test.py +//// from enum import Enum +//// from datetime import timedelta +//// class Period(timedelta, Enum): +//// Today = -1 +//// +//// Period.Today.[|/*marker*/|] + `; + + const state = parseAndGetTestState(code).state; + + await state.verifyCompletion('included', 'markdown', { + ['marker']: { + completions: [ + { + label: 'days', + kind: CompletionItemKind.Property, + }, + { + label: 'seconds', + kind: CompletionItemKind.Property, + }, + ], + }, + }); +});