mirror of
https://github.com/microsoft/pyright.git
synced 2024-08-17 20:00:24 +03:00
pull-pylance-with-pyright-1.1.369-9716881771
This commit is contained in:
parent
3c70b4e0d1
commit
1fde529ada
@ -109,7 +109,8 @@ export class ImportResolver {
|
||||
private _cachedFilesForPath = new Map<string, Uri[]>();
|
||||
private _cachedDirExistenceForRoot = new Map<string, boolean>();
|
||||
private _stdlibModules: Set<string> | 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -251,10 +251,10 @@ export function getBackgroundWaiter<T>(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 {
|
||||
|
@ -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<T> = (a: T, b: T) => boolean;
|
||||
@ -318,7 +318,7 @@ export function getNestedProperty(object: any, property: string) {
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getOrAdd<K, V>(map: Map<K, V>, key: K, newValueFactory: () => V): V {
|
||||
export function getOrAdd<K, V>(map: MapLike<K, V>, key: K, newValueFactory: () => V): V {
|
||||
const value = map.get(key);
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
|
@ -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<T> {
|
||||
[index: string]: T;
|
||||
export interface MapLike<K, V> {
|
||||
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<T> {
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function hasProperty(map: MapLike<any>, key: string): boolean {
|
||||
export function hasProperty(map: { [index: string]: any }, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
}
|
||||
|
||||
|
@ -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 || '');
|
||||
}
|
||||
|
@ -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(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 {
|
||||
|
@ -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 {
|
||||
|
@ -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í",
|
||||
|
@ -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.",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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}\" は共変である必要があります",
|
||||
|
@ -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}‘ 형식 변수는 공변이어야 합니다",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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}\", должна быть ковариантной",
|
||||
|
@ -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",
|
||||
|
@ -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}”应为协变",
|
||||
|
@ -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}\" 必須為共變數",
|
||||
|
@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user