pylance-22-5-2024 -> pyright (#7980)

* pullpylance-22-5-2024

  Co-authored-by: Bill Schnurr <bschnurr@microsoft.com>
  Co-authored-by: HeeJae Chang <hechang@microsoft.com>
  Co-authored-by: Erik De Bonte <erikd@microsoft.com>
  Co-authored-by: Rich Chiodo <rchiodo@microsoft.com>
  Co-authored-by: Stella Huang <stellahuang@microsoft.com>
  Co-authored-by: Kacie Kang <jikang@microsoft.com>
This commit is contained in:
Bill Schnurr 2024-05-22 15:34:30 -07:00 committed by GitHub
parent 766a012627
commit 0618acc535
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 333 additions and 197 deletions

View File

@ -24,13 +24,18 @@ export interface AnalysisResults {
diagnostics: FileDiagnostics[]; diagnostics: FileDiagnostics[];
filesInProgram: number; filesInProgram: number;
checkingOnlyOpenFiles: boolean; checkingOnlyOpenFiles: boolean;
filesRequiringAnalysis: number; requiringAnalysisCount: RequiringAnalysisCount;
fatalErrorOccurred: boolean; fatalErrorOccurred: boolean;
configParseErrorOccurred: boolean; configParseErrorOccurred: boolean;
elapsedTime: number; elapsedTime: number;
error?: Error | undefined; error?: Error | undefined;
} }
export interface RequiringAnalysisCount {
files: number;
cells: number;
}
export type AnalysisCompleteCallback = (results: AnalysisResults) => void; export type AnalysisCompleteCallback = (results: AnalysisResults) => void;
export function analyzeProgram( export function analyzeProgram(
@ -51,7 +56,7 @@ export function analyzeProgram(
const duration = new Duration(); const duration = new Duration();
moreToAnalyze = program.analyze(maxTime, token); moreToAnalyze = program.analyze(maxTime, token);
const filesLeftToAnalyze = program.getFilesToAnalyzeCount(); const requiringAnalysisCount = program.getFilesToAnalyzeCount();
// If we're using command-line mode, the maxTime will be undefined, and we'll // If we're using command-line mode, the maxTime will be undefined, and we'll
// want to report all diagnostics rather than just the ones that have changed. // want to report all diagnostics rather than just the ones that have changed.
@ -66,7 +71,7 @@ export function analyzeProgram(
callback({ callback({
diagnostics, diagnostics,
filesInProgram: program.getFileCount(), filesInProgram: program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze, requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: program.isCheckingOnlyOpenFiles(), checkingOnlyOpenFiles: program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false, fatalErrorOccurred: false,
configParseErrorOccurred: false, configParseErrorOccurred: false,
@ -84,7 +89,7 @@ export function analyzeProgram(
callback({ callback({
diagnostics: [], diagnostics: [],
filesInProgram: 0, filesInProgram: 0,
filesRequiringAnalysis: 0, requiringAnalysisCount: { files: 0, cells: 0 },
checkingOnlyOpenFiles: true, checkingOnlyOpenFiles: true,
fatalErrorOccurred: true, fatalErrorOccurred: true,
configParseErrorOccurred: false, configParseErrorOccurred: false,

View File

@ -262,7 +262,7 @@ export class BackgroundAnalysisProgram {
this._onAnalysisCompletion({ this._onAnalysisCompletion({
diagnostics: fileDiags, diagnostics: fileDiags,
filesInProgram: this._program.getFileCount(), filesInProgram: this._program.getFileCount(),
filesRequiringAnalysis: this._program.getFilesToAnalyzeCount(), requiringAnalysisCount: this._program.getFilesToAnalyzeCount(),
checkingOnlyOpenFiles: this._program.isCheckingOnlyOpenFiles(), checkingOnlyOpenFiles: this._program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false, fatalErrorOccurred: false,
configParseErrorOccurred: false, configParseErrorOccurred: false,

View File

@ -564,6 +564,7 @@ export class ImportResolver {
return importResult; return importResult;
} }
const localImportFailureInfo: string[] = [`Attempting to resolve using local imports: ${importName}`];
const importPath: ImportPath = { importPath: undefined }; const importPath: ImportPath = { importPath: undefined };
// Going up the given folder one by one until we can resolve the import. // Going up the given folder one by one until we can resolve the import.
@ -575,7 +576,7 @@ export class ImportResolver {
execEnv, execEnv,
moduleDescriptor, moduleDescriptor,
importName, importName,
[], localImportFailureInfo,
/* allowPartial */ undefined, /* allowPartial */ undefined,
/* allowNativeLib */ undefined, /* allowNativeLib */ undefined,
/* useStubPackage */ false, /* useStubPackage */ false,
@ -603,6 +604,12 @@ export class ImportResolver {
if (current) { if (current) {
this.cachedParentImportResults.checked(current, importName, importPath); this.cachedParentImportResults.checked(current, importName, importPath);
} }
if (this._configOptions.verboseOutput) {
const console = this.serviceProvider.console();
localImportFailureInfo.forEach((diag) => console.log(diag));
}
return importResult; return importResult;
} }

View File

@ -30,8 +30,7 @@ export class ParentDirectoryCache {
const result = this._cachedResults.get(importName)?.get(path.key); const result = this._cachedResults.get(importName)?.get(path.key);
if (result) { if (result) {
// We already checked for the importName at the path. // We already checked for the importName at the path.
// Return the result if succeeded otherwise, return regular import result given. return result;
return result ?? importResult;
} }
const checked = this._importChecked.get(importName)?.get(path.key); const checked = this._importChecked.get(importName)?.get(path.key);

View File

@ -50,6 +50,7 @@ import { createTypeEvaluatorWithTracker } from './typeEvaluatorWithTracker';
import { PrintTypeFlags } from './typePrinter'; import { PrintTypeFlags } from './typePrinter';
import { TypeStubWriter } from './typeStubWriter'; import { TypeStubWriter } from './typeStubWriter';
import { Type } from './types'; import { Type } from './types';
import { RequiringAnalysisCount } from './analysis';
const _maxImportDepth = 256; const _maxImportDepth = 256;
@ -521,22 +522,29 @@ export class Program {
return this._sourceFileList.filter((s) => s.isOpenByClient); return this._sourceFileList.filter((s) => s.isOpenByClient);
} }
getFilesToAnalyzeCount() { getFilesToAnalyzeCount(): RequiringAnalysisCount {
let sourceFileCount = 0; let filesToAnalyzeCount = 0;
let cellsToAnalyzeCount = 0;
if (this._disableChecker) { if (this._disableChecker) {
return sourceFileCount; return { files: 0, cells: 0 };
} }
this._sourceFileList.forEach((fileInfo) => { this._sourceFileList.forEach((fileInfo) => {
if (fileInfo.sourceFile.isCheckingRequired()) { const sourceFile = fileInfo.sourceFile;
if (sourceFile.isCheckingRequired()) {
if (this._shouldCheckFile(fileInfo)) { if (this._shouldCheckFile(fileInfo)) {
sourceFileCount++; sourceFile.getIPythonMode() === IPythonMode.CellDocs
? cellsToAnalyzeCount++
: filesToAnalyzeCount++;
} }
} }
}); });
return sourceFileCount; return {
files: filesToAnalyzeCount,
cells: cellsToAnalyzeCount,
};
} }
isCheckingOnlyOpenFiles() { isCheckingOnlyOpenFiles() {
@ -1505,7 +1513,7 @@ export class Program {
assert(!this._sourceFileMap.has(fileUri.key)); assert(!this._sourceFileMap.has(fileUri.key));
// We should never have an empty URI for a source file. // We should never have an empty URI for a source file.
assert(!fileInfo.sourceFile.getUri().isEmpty()); assert(!fileUri.isEmpty());
this._sourceFileList.push(fileInfo); this._sourceFileList.push(fileInfo);
this._sourceFileMap.set(fileUri.key, fileInfo); this._sourceFileMap.set(fileUri.key, fileInfo);

View File

@ -1086,7 +1086,7 @@ export class AnalyzerService {
this._typeStubTargetUri = rootPackagePath.getDirectory(); this._typeStubTargetUri = rootPackagePath.getDirectory();
} }
if (!finalResolvedPath) { if (finalResolvedPath.isEmpty()) {
this._typeStubTargetIsSingleFile = false; this._typeStubTargetIsSingleFile = false;
} else { } else {
filesToImport.push(finalResolvedPath); filesToImport.push(finalResolvedPath);
@ -1730,7 +1730,7 @@ export class AnalyzerService {
this._onCompletionCallback({ this._onCompletionCallback({
diagnostics: [], diagnostics: [],
filesInProgram: 0, filesInProgram: 0,
filesRequiringAnalysis: 0, requiringAnalysisCount: { files: 0, cells: 0 },
checkingOnlyOpenFiles: true, checkingOnlyOpenFiles: true,
fatalErrorOccurred: false, fatalErrorOccurred: false,
configParseErrorOccurred: true, configParseErrorOccurred: true,

View File

@ -12,7 +12,7 @@ import { isMainThread } from 'worker_threads';
import { OperationCanceledException } from '../common/cancellationUtils'; import { OperationCanceledException } from '../common/cancellationUtils';
import { appendArray } from '../common/collectionUtils'; import { appendArray } from '../common/collectionUtils';
import { ConfigOptions, ExecutionEnvironment, getBasicDiagnosticRuleSet } from '../common/configOptions'; import { ConfigOptions, ExecutionEnvironment, getBasicDiagnosticRuleSet } from '../common/configOptions';
import { ConsoleInterface, StandardConsole } from '../common/console'; import { ConsoleInterface, LogLevel, StandardConsole } from '../common/console';
import { assert } from '../common/debug'; import { assert } from '../common/debug';
import { Diagnostic, DiagnosticCategory, TaskListToken, convertLevelToCategory } from '../common/diagnostic'; import { Diagnostic, DiagnosticCategory, TaskListToken, convertLevelToCategory } from '../common/diagnostic';
import { DiagnosticRule } from '../common/diagnosticRules'; import { DiagnosticRule } from '../common/diagnosticRules';
@ -95,7 +95,6 @@ class WriteableData {
// the binder information hanging from it? // the binder information hanging from it?
parseTreeNeedsCleaning = false; parseTreeNeedsCleaning = false;
parserOutput: ParserOutput | undefined;
parsedFileContents: string | undefined; parsedFileContents: string | undefined;
tokenizerLines: TextRangeCollection<TextRange> | undefined; tokenizerLines: TextRangeCollection<TextRange> | undefined;
tokenizerOutput: TokenizerOutput | undefined; tokenizerOutput: TokenizerOutput | undefined;
@ -142,6 +141,30 @@ class WriteableData {
// True if the file appears to have been deleted. // True if the file appears to have been deleted.
isFileDeleted = false; isFileDeleted = false;
private _lastCallstack: string | undefined;
private _parserOutput: ParserOutput | undefined;
private readonly _consoleWithLevel?: ConsoleInterface & { level: LogLevel };
constructor(console: ConsoleInterface) {
if (ConsoleInterface.hasLevel(console)) {
this._consoleWithLevel = console;
}
}
get parserOutput() {
return this._parserOutput;
}
set parserOutput(value: ParserOutput | undefined) {
this._lastCallstack =
this._consoleWithLevel?.level === LogLevel.Log && value === undefined && this._parserOutput !== undefined
? new Error().stack
: undefined;
this._parserOutput = value;
}
debugPrint() { debugPrint() {
return `WritableData: return `WritableData:
diagnosticVersion=${this.diagnosticVersion}, diagnosticVersion=${this.diagnosticVersion},
@ -171,7 +194,8 @@ class WriteableData {
pyrightIgnoreLines=${this.pyrightIgnoreLines?.size}, pyrightIgnoreLines=${this.pyrightIgnoreLines?.size},
checkTime=${this.checkTime}, checkTime=${this.checkTime},
clientDocumentContents=${this.clientDocumentContents?.length}, clientDocumentContents=${this.clientDocumentContents?.length},
parseResults=${this.parserOutput?.parseTree.length}`; parseResults=${this.parserOutput?.parseTree.length},
parseResultsDropCallstack=${this._lastCallstack}`;
} }
} }
@ -180,9 +204,6 @@ export interface SourceFileEditMode {
} }
export class SourceFile { export class SourceFile {
// Data that changes when the source file changes.
private _writableData = new WriteableData();
// Console interface to use for debugging. // Console interface to use for debugging.
private _console: ConsoleInterface; private _console: ConsoleInterface;
@ -232,6 +253,10 @@ export class SourceFile {
private _ipythonMode = IPythonMode.None; private _ipythonMode = IPythonMode.None;
private _logTracker: LogTracker; private _logTracker: LogTracker;
private _preEditData: WriteableData | undefined; private _preEditData: WriteableData | undefined;
// Data that changes when the source file changes.
private _writableData: WriteableData;
readonly fileSystem: FileSystem; readonly fileSystem: FileSystem;
constructor( constructor(
@ -247,6 +272,8 @@ export class SourceFile {
) { ) {
this.fileSystem = serviceProvider.get(ServiceKeys.fs); this.fileSystem = serviceProvider.get(ServiceKeys.fs);
this._console = console || new StandardConsole(); this._console = console || new StandardConsole();
this._writableData = new WriteableData(this._console);
this._editMode = editMode; this._editMode = editMode;
this._uri = uri; this._uri = uri;
this._moduleName = moduleName; this._moduleName = moduleName;
@ -864,7 +891,7 @@ export class SourceFile {
sourceMapper: SourceMapper, sourceMapper: SourceMapper,
dependentFiles?: ParserOutput[] dependentFiles?: ParserOutput[]
) { ) {
assert(!this.isParseRequired(), 'Check called before parsing'); assert(!this.isParseRequired(), `Check called before parsing: state=${this._writableData.debugPrint()}`);
assert(!this.isBindingRequired(), `Check called before binding: state=${this._writableData.debugPrint()}`); assert(!this.isBindingRequired(), `Check called before binding: state=${this._writableData.debugPrint()}`);
assert(!this._writableData.isBindingInProgress, 'Check called while binding in progress'); assert(!this._writableData.isBindingInProgress, 'Check called while binding in progress');
assert(this.isCheckingRequired(), 'Check called unnecessarily'); assert(this.isCheckingRequired(), 'Check called unnecessarily');
@ -1209,7 +1236,7 @@ export class SourceFile {
this._preEditData = this._writableData; this._preEditData = this._writableData;
// Recreate all the writable data from scratch. // Recreate all the writable data from scratch.
this._writableData = new WriteableData(); this._writableData = new WriteableData(this._console);
} }
// Get all task list diagnostics for the current file and add them // Get all task list diagnostics for the current file and add them

View File

@ -12,11 +12,12 @@ import {
ClassDeclaration, ClassDeclaration,
Declaration, Declaration,
DeclarationBase, DeclarationBase,
DeclarationType,
FunctionDeclaration, FunctionDeclaration,
isClassDeclaration, isClassDeclaration,
isFunctionDeclaration, isFunctionDeclaration,
isSpecialBuiltInClassDeclaration,
isVariableDeclaration, isVariableDeclaration,
SpecialBuiltInClassDeclaration,
VariableDeclaration, VariableDeclaration,
} from '../analyzer/declaration'; } from '../analyzer/declaration';
import * as ParseTreeUtils from '../analyzer/parseTreeUtils'; import * as ParseTreeUtils from '../analyzer/parseTreeUtils';
@ -227,9 +228,9 @@ export function getClassDocString(
sourceMapper: SourceMapper sourceMapper: SourceMapper
) { ) {
let docString = classType.details.docString; let docString = classType.details.docString;
if (!docString && resolvedDecl && isClassDeclaration(resolvedDecl)) { if (!docString && resolvedDecl && _isAnyClassDeclaration(resolvedDecl)) {
docString = _getFunctionOrClassDeclsDocString([resolvedDecl]); docString = isClassDeclaration(resolvedDecl) ? _getFunctionOrClassDeclsDocString([resolvedDecl]) : undefined;
if (!docString && resolvedDecl && isStubFile(resolvedDecl.uri) && resolvedDecl.type === DeclarationType.Class) { if (!docString && resolvedDecl && isStubFile(resolvedDecl.uri)) {
for (const implDecl of sourceMapper.findDeclarations(resolvedDecl)) { for (const implDecl of sourceMapper.findDeclarations(resolvedDecl)) {
if (isVariableDeclaration(implDecl) && !!implDecl.docString) { if (isVariableDeclaration(implDecl) && !!implDecl.docString) {
docString = implDecl.docString; docString = implDecl.docString;
@ -386,3 +387,7 @@ function _getFunctionOrClassDeclsDocString(decls: FunctionDeclaration[] | ClassD
return undefined; return undefined;
} }
function _isAnyClassDeclaration(decl: Declaration): decl is ClassDeclaration | SpecialBuiltInClassDeclaration {
return isClassDeclaration(decl) || isSpecialBuiltInClassDeclaration(decl);
}

View File

@ -9,7 +9,13 @@
import { CancellationToken } from 'vscode-languageserver'; import { CancellationToken } from 'vscode-languageserver';
import { MessageChannel, MessagePort, Worker, parentPort, threadId, workerData } from 'worker_threads'; import { MessageChannel, MessagePort, Worker, parentPort, threadId, workerData } from 'worker_threads';
import { AnalysisCompleteCallback, AnalysisResults, analyzeProgram, nullCallback } from './analyzer/analysis'; import {
AnalysisCompleteCallback,
AnalysisResults,
RequiringAnalysisCount,
analyzeProgram,
nullCallback,
} from './analyzer/analysis';
import { BackgroundAnalysisProgram, InvalidatedReason } from './analyzer/backgroundAnalysisProgram'; import { BackgroundAnalysisProgram, InvalidatedReason } from './analyzer/backgroundAnalysisProgram';
import { ImportResolver } from './analyzer/importResolver'; import { ImportResolver } from './analyzer/importResolver';
import { OpenFileOptions, Program } from './analyzer/program'; import { OpenFileOptions, Program } from './analyzer/program';
@ -473,12 +479,12 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
protected handleAnalyze(port: MessagePort, cancellationId: string, token: CancellationToken) { protected handleAnalyze(port: MessagePort, cancellationId: string, token: CancellationToken) {
// Report files to analyze first. // Report files to analyze first.
const filesLeftToAnalyze = this.program.getFilesToAnalyzeCount(); const requiringAnalysisCount = this.program.getFilesToAnalyzeCount();
this.onAnalysisCompletion(port, { this.onAnalysisCompletion(port, {
diagnostics: [], diagnostics: [],
filesInProgram: this.program.getFileCount(), filesInProgram: this.program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze, requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(), checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false, fatalErrorOccurred: false,
configParseErrorOccurred: false, configParseErrorOccurred: false,
@ -671,12 +677,16 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
} }
} }
private _reportDiagnostics(diagnostics: FileDiagnostics[], filesLeftToAnalyze: number, elapsedTime: number) { private _reportDiagnostics(
diagnostics: FileDiagnostics[],
requiringAnalysisCount: RequiringAnalysisCount,
elapsedTime: number
) {
if (parentPort) { if (parentPort) {
this.onAnalysisCompletion(parentPort, { this.onAnalysisCompletion(parentPort, {
diagnostics, diagnostics,
filesInProgram: this.program.getFileCount(), filesInProgram: this.program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze, requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(), checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false, fatalErrorOccurred: false,
configParseErrorOccurred: false, configParseErrorOccurred: false,

View File

@ -22,24 +22,32 @@ import './common/serviceProviderExtensions';
import { Uri } from './common/uri/uri'; import { Uri } from './common/uri/uri';
export class BackgroundConsole implements ConsoleInterface { export class BackgroundConsole implements ConsoleInterface {
// We always generate logs in the background. For the foreground, private _level = LogLevel.Log;
// we'll decide based on user setting whether.
get level() { get level() {
return LogLevel.Log; return this._level;
}
set level(value: LogLevel) {
this._level = value;
} }
log(msg: string) { log(msg: string) {
this.post(LogLevel.Log, msg); this.post(LogLevel.Log, msg);
} }
info(msg: string) { info(msg: string) {
this.post(LogLevel.Info, msg); this.post(LogLevel.Info, msg);
} }
warn(msg: string) { warn(msg: string) {
this.post(LogLevel.Warn, msg); this.post(LogLevel.Warn, msg);
} }
error(msg: string) { error(msg: string) {
this.post(LogLevel.Error, msg); this.post(LogLevel.Error, msg);
} }
protected post(level: LogLevel, msg: string) { protected post(level: LogLevel, msg: string) {
parentPort?.postMessage({ requestType: 'log', data: serialize({ level: level, message: msg }) }); parentPort?.postMessage({ requestType: 'log', data: serialize({ level: level, message: msg }) });
} }

View File

@ -9,53 +9,64 @@
import { CancellationToken, ExecuteCommandParams } from 'vscode-languageserver'; import { CancellationToken, ExecuteCommandParams } from 'vscode-languageserver';
import { OperationCanceledException } from '../common/cancellationUtils'; import { OperationCanceledException } from '../common/cancellationUtils';
import { LanguageServerInterface } from '../common/languageServerInterface'; import { LanguageServerBaseInterface, LanguageServerInterface } from '../common/languageServerInterface';
import { AnalyzerServiceExecutor } from '../languageService/analyzerServiceExecutor'; import { AnalyzerServiceExecutor } from '../languageService/analyzerServiceExecutor';
import { ServerCommand } from './commandController'; import { ServerCommand } from './commandController';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { Workspace } from '../workspaceFactory';
export class CreateTypeStubCommand implements ServerCommand { export class CreateTypeStubCommand implements ServerCommand {
constructor(private _ls: LanguageServerInterface) {} constructor(private _ls: LanguageServerInterface) {
// Empty
}
async execute(cmdParams: ExecuteCommandParams, token: CancellationToken): Promise<any> { async execute(cmdParams: ExecuteCommandParams, token: CancellationToken): Promise<any> {
if (cmdParams.arguments && cmdParams.arguments.length >= 2) { if (!cmdParams.arguments || cmdParams.arguments.length < 2) {
const workspaceRoot = Uri.parse(cmdParams.arguments[0] as string, this._ls.serviceProvider); return undefined;
const importName = cmdParams.arguments[1] as string; }
const callingFile = Uri.parse(cmdParams.arguments[2] as string, this._ls.serviceProvider);
const service = await AnalyzerServiceExecutor.cloneService( const workspaceRoot = Uri.parse(cmdParams.arguments[0] as string, this._ls.serviceProvider);
this._ls, const importName = cmdParams.arguments[1] as string;
await this._ls.getWorkspaceForFile(callingFile ?? workspaceRoot), const callingFile = Uri.parse(cmdParams.arguments[2] as string, this._ls.serviceProvider);
{
typeStubTargetImportName: importName, const workspace = await this._ls.getWorkspaceForFile(callingFile ?? workspaceRoot);
} return await new TypeStubCreator(this._ls).create(workspace, importName, token);
); }
}
try {
await service.writeTypeStubInBackground(token); export class TypeStubCreator {
service.dispose(); constructor(private _ls: LanguageServerBaseInterface) {}
const infoMessage = `Type stub was successfully created for '${importName}'.`; async create(workspace: Workspace, importName: string, token: CancellationToken): Promise<any> {
this._ls.window.showInformationMessage(infoMessage); const service = await AnalyzerServiceExecutor.cloneService(this._ls, workspace, {
typeStubTargetImportName: importName,
// This is called after a new type stub has been created. It allows useBackgroundAnalysis: true,
// us to invalidate caches and force reanalysis of files that potentially });
// are affected by the appearance of a new type stub.
this._ls.reanalyze(); try {
} catch (err) { await service.writeTypeStubInBackground(token);
const isCancellation = OperationCanceledException.is(err); service.dispose();
if (isCancellation) {
const errMessage = `Type stub creation for '${importName}' was canceled`; const infoMessage = `Type stub was successfully created for '${importName}'.`;
this._ls.console.error(errMessage); this._ls.window.showInformationMessage(infoMessage);
} else {
let errMessage = ''; // This is called after a new type stub has been created. It allows
if (err instanceof Error) { // us to invalidate caches and force reanalysis of files that potentially
errMessage = ': ' + err.message; // are affected by the appearance of a new type stub.
} this._ls.reanalyze();
errMessage = `An error occurred when creating type stub for '${importName}'` + errMessage; } catch (err) {
this._ls.console.error(errMessage); const isCancellation = OperationCanceledException.is(err);
this._ls.window.showErrorMessage(errMessage); if (isCancellation) {
const errMessage = `Type stub creation for '${importName}' was canceled`;
this._ls.console.error(errMessage);
} else {
let errMessage = '';
if (err instanceof Error) {
errMessage = ': ' + err.message;
} }
errMessage = `An error occurred when creating type stub for '${importName}'` + errMessage;
this._ls.console.error(errMessage);
this._ls.window.showErrorMessage(errMessage);
} }
} }
} }

View File

@ -29,6 +29,10 @@ export namespace ConsoleInterface {
export function is(obj: any): obj is ConsoleInterface { export function is(obj: any): obj is ConsoleInterface {
return obj.error !== undefined && obj.warn !== undefined && obj.info !== undefined && obj.log !== undefined; return obj.error !== undefined && obj.warn !== undefined && obj.info !== undefined && obj.log !== undefined;
} }
export function hasLevel(console: any): console is ConsoleInterface & { level: LogLevel } {
return is(console) && 'level' in console;
}
} }
const levelMap = new Map([ const levelMap = new Map([

View File

@ -6,13 +6,19 @@
* Interface for language server * Interface for language server
*/ */
import { MarkupKind } from 'vscode-languageserver';
import { MaxAnalysisTime } from '../analyzer/program';
import { BackgroundAnalysisBase } from '../backgroundAnalysisBase'; import { BackgroundAnalysisBase } from '../backgroundAnalysisBase';
import { Workspace } from '../workspaceFactory'; import { Workspace } from '../workspaceFactory';
import { CancellationProvider } from './cancellationUtils';
import { DiagnosticSeverityOverridesMap } from './commandLineOptions'; import { DiagnosticSeverityOverridesMap } from './commandLineOptions';
import { SignatureDisplayType } from './configOptions'; import { SignatureDisplayType } from './configOptions';
import { ConsoleInterface, LogLevel } from './console'; import { ConsoleInterface, LogLevel } from './console';
import { TaskListToken } from './diagnostic'; import { TaskListToken } from './diagnostic';
import * as ext from './extensibility'; import * as ext from './extensibility';
import { FileSystem } from './fileSystem';
import { FileWatcherHandler } from './fileWatcher';
import { ServiceProvider } from './serviceProvider';
import { Uri } from './uri/uri'; import { Uri } from './uri/uri';
export interface ServerSettings { export interface ServerSettings {
@ -71,6 +77,49 @@ export namespace WindowInterface {
} }
} }
export interface WorkspaceServices {
fs: FileSystem | undefined;
backgroundAnalysis: BackgroundAnalysisBase | undefined;
}
export interface ServerOptions {
productName: string;
rootDirectory: Uri;
version: string;
cancellationProvider: CancellationProvider;
serviceProvider: ServiceProvider;
fileWatcherHandler: FileWatcherHandler;
maxAnalysisTimeInForeground?: MaxAnalysisTime;
disableChecker?: boolean;
supportedCommands?: string[];
supportedCodeActions?: string[];
supportsTelemetry?: boolean;
}
export interface ClientCapabilities {
hasConfigurationCapability: boolean;
hasVisualStudioExtensionsCapability: boolean;
hasWorkspaceFoldersCapability: boolean;
hasWatchFileCapability: boolean;
hasWatchFileRelativePathCapability: boolean;
hasActiveParameterCapability: boolean;
hasSignatureLabelOffsetCapability: boolean;
hasHierarchicalDocumentSymbolCapability: boolean;
hasWindowProgressCapability: boolean;
hasGoToDeclarationCapability: boolean;
hasDocumentChangeCapability: boolean;
hasDocumentAnnotationCapability: boolean;
hasCompletionCommitCharCapability: boolean;
hoverContentFormat: MarkupKind;
completionDocFormat: MarkupKind;
completionSupportsSnippet: boolean;
signatureDocFormat: MarkupKind;
supportsDeprecatedDiagnosticTag: boolean;
supportsUnnecessaryDiagnosticTag: boolean;
supportsTaskItemDiagnosticTag: boolean;
completionItemResolveSupportsAdditionalTextEdits: boolean;
}
export interface LanguageServerBaseInterface { export interface LanguageServerBaseInterface {
readonly console: ConsoleInterface; readonly console: ConsoleInterface;
readonly window: WindowInterface; readonly window: WindowInterface;

View File

@ -234,6 +234,8 @@ export namespace Uri {
return EmptyUri.instance; return EmptyUri.instance;
} }
// Excel's copy of tests\harness\vfs\pathValidation.ts knows about this constant.
// If the value is changed, the Excel team should be told.
export const DefaultWorkspaceRootComponent = '<default workspace root>'; export const DefaultWorkspaceRootComponent = '<default workspace root>';
export const DefaultWorkspaceRootPath = `/${DefaultWorkspaceRootComponent}`; export const DefaultWorkspaceRootPath = `/${DefaultWorkspaceRootComponent}`;

View File

@ -380,7 +380,7 @@ export function getRootUri(csdOrSp: CaseSensitivityDetector | ServiceProvider):
return undefined; return undefined;
} }
export function encodeUri(fs: ReadOnlyFileSystem, uri: Uri): string { export function convertUriToLspUriString(fs: ReadOnlyFileSystem, uri: Uri): string {
// Convert to a URI string that the LSP client understands (mapped files are only local to the server). // Convert to a URI string that the LSP client understands (mapped files are only local to the server).
return fs.getOriginalUri(uri).toString(); return fs.getOriginalUri(uri).toString();
} }

View File

@ -28,7 +28,7 @@ import { convertRangeToTextRange, convertTextRangeToRange } from './positionUtil
import { TextRange } from './textRange'; import { TextRange } from './textRange';
import { TextRangeCollection } from './textRangeCollection'; import { TextRangeCollection } from './textRangeCollection';
import { Uri } from './uri/uri'; import { Uri } from './uri/uri';
import { encodeUri } from './uri/uriUtils'; import { convertUriToLspUriString } from './uri/uriUtils';
export function convertToTextEdits(editActions: TextEditAction[]): TextEdit[] { export function convertToTextEdits(editActions: TextEditAction[]): TextEdit[] {
return editActions.map((editAction) => ({ return editActions.map((editAction) => ({
@ -68,7 +68,7 @@ export function convertToWorkspaceEdit(
export function appendToWorkspaceEdit(fs: ReadOnlyFileSystem, edits: FileEditAction[], workspaceEdit: WorkspaceEdit) { export function appendToWorkspaceEdit(fs: ReadOnlyFileSystem, edits: FileEditAction[], workspaceEdit: WorkspaceEdit) {
edits.forEach((edit) => { edits.forEach((edit) => {
const uri = encodeUri(fs, edit.fileUri); const uri = convertUriToLspUriString(fs, edit.fileUri);
workspaceEdit.changes![uri] = workspaceEdit.changes![uri] || []; workspaceEdit.changes![uri] = workspaceEdit.changes![uri] || [];
workspaceEdit.changes![uri].push({ range: edit.range, newText: edit.replacementText }); workspaceEdit.changes![uri].push({ range: edit.range, newText: edit.replacementText });
}); });
@ -185,7 +185,7 @@ export function generateWorkspaceEdit(
continue; continue;
} }
edits.changes![encodeUri(fs, uri)] = [ edits.changes![convertUriToLspUriString(fs, uri)] = [
{ {
range: convertTextRangeToRange(parseResults.parserOutput.parseTree, parseResults.tokenizerOutput.lines), range: convertTextRangeToRange(parseResults.parserOutput.parseTree, parseResults.tokenizerOutput.lines),
newText: final.getFileContent() ?? '', newText: final.getFileContent() ?? '',
@ -224,7 +224,11 @@ function _convertToWorkspaceEditWithDocumentChanges(
switch (operation.kind) { switch (operation.kind) {
case 'create': case 'create':
workspaceEdit.documentChanges!.push( workspaceEdit.documentChanges!.push(
CreateFile.create(encodeUri(fs, operation.fileUri), /* options */ undefined, defaultAnnotationId) CreateFile.create(
convertUriToLspUriString(fs, operation.fileUri),
/* options */ undefined,
defaultAnnotationId
)
); );
break; break;
case 'rename': case 'rename':
@ -236,7 +240,7 @@ function _convertToWorkspaceEditWithDocumentChanges(
} }
// Text edit's file path must refer to original file paths unless it is a new file just created. // Text edit's file path must refer to original file paths unless it is a new file just created.
const mapPerFile = createMapFromItems(editActions.edits, (e) => encodeUri(fs, e.fileUri)); const mapPerFile = createMapFromItems(editActions.edits, (e) => convertUriToLspUriString(fs, e.fileUri));
for (const [uri, value] of mapPerFile) { for (const [uri, value] of mapPerFile) {
workspaceEdit.documentChanges!.push( workspaceEdit.documentChanges!.push(
TextDocumentEdit.create( TextDocumentEdit.create(
@ -259,8 +263,8 @@ function _convertToWorkspaceEditWithDocumentChanges(
case 'rename': case 'rename':
workspaceEdit.documentChanges!.push( workspaceEdit.documentChanges!.push(
RenameFile.create( RenameFile.create(
encodeUri(fs, operation.oldFileUri), convertUriToLspUriString(fs, operation.oldFileUri),
encodeUri(fs, operation.newFileUri), convertUriToLspUriString(fs, operation.newFileUri),
/* options */ undefined, /* options */ undefined,
defaultAnnotationId defaultAnnotationId
) )
@ -268,7 +272,11 @@ function _convertToWorkspaceEditWithDocumentChanges(
break; break;
case 'delete': case 'delete':
workspaceEdit.documentChanges!.push( workspaceEdit.documentChanges!.push(
DeleteFile.create(encodeUri(fs, operation.fileUri), /* options */ undefined, defaultAnnotationId) DeleteFile.create(
convertUriToLspUriString(fs, operation.fileUri),
/* options */ undefined,
defaultAnnotationId
)
); );
break; break;
default: default:

View File

@ -78,7 +78,7 @@ import { AnalyzerService, LibraryReanalysisTimeProvider, getNextServiceId } from
import { IPythonMode } from './analyzer/sourceFile'; import { IPythonMode } from './analyzer/sourceFile';
import type { BackgroundAnalysisBase } from './backgroundAnalysisBase'; import type { BackgroundAnalysisBase } from './backgroundAnalysisBase';
import { CommandResult } from './commands/commandResult'; import { CommandResult } from './commands/commandResult';
import { CancelAfter, CancellationProvider } from './common/cancellationUtils'; import { CancelAfter } from './common/cancellationUtils';
import { CaseSensitivityDetector } from './common/caseSensitivityDetector'; import { CaseSensitivityDetector } from './common/caseSensitivityDetector';
import { getNestedProperty } from './common/collectionUtils'; import { getNestedProperty } from './common/collectionUtils';
import { DiagnosticSeverityOverrides, getDiagnosticSeverityOverrides } from './common/commandLineOptions'; import { DiagnosticSeverityOverrides, getDiagnosticSeverityOverrides } from './common/commandLineOptions';
@ -88,16 +88,22 @@ import { Diagnostic as AnalyzerDiagnostic, DiagnosticCategory, TaskListPriority
import { DiagnosticRule } from './common/diagnosticRules'; import { DiagnosticRule } from './common/diagnosticRules';
import { FileDiagnostics } from './common/diagnosticSink'; import { FileDiagnostics } from './common/diagnosticSink';
import { FileSystem, ReadOnlyFileSystem } from './common/fileSystem'; import { FileSystem, ReadOnlyFileSystem } from './common/fileSystem';
import { FileWatcherEventType, FileWatcherHandler } from './common/fileWatcher'; import { FileWatcherEventType } from './common/fileWatcher';
import { Host } from './common/host'; import { Host } from './common/host';
import { LanguageServerInterface, ServerSettings } from './common/languageServerInterface'; import {
ClientCapabilities,
LanguageServerInterface,
ServerOptions,
ServerSettings,
WorkspaceServices,
} from './common/languageServerInterface';
import { fromLSPAny } from './common/lspUtils'; import { fromLSPAny } from './common/lspUtils';
import { ProgressReportTracker, ProgressReporter } from './common/progressReporter'; import { ProgressReportTracker, ProgressReporter } from './common/progressReporter';
import { ServiceKeys } from './common/serviceKeys'; import { ServiceKeys } from './common/serviceKeys';
import { ServiceProvider } from './common/serviceProvider'; import { ServiceProvider } from './common/serviceProvider';
import { DocumentRange, Position, Range } from './common/textRange'; import { DocumentRange, Position, Range } from './common/textRange';
import { Uri } from './common/uri/uri'; import { Uri } from './common/uri/uri';
import { encodeUri } from './common/uri/uriUtils'; import { convertUriToLspUriString } from './common/uri/uriUtils';
import { AnalyzerServiceExecutor } from './languageService/analyzerServiceExecutor'; import { AnalyzerServiceExecutor } from './languageService/analyzerServiceExecutor';
import { CallHierarchyProvider } from './languageService/callHierarchyProvider'; import { CallHierarchyProvider } from './languageService/callHierarchyProvider';
import { CompletionItemData, CompletionProvider } from './languageService/completionProvider'; import { CompletionItemData, CompletionProvider } from './languageService/completionProvider';
@ -117,49 +123,6 @@ import { InitStatus, WellKnownWorkspaceKinds, Workspace, WorkspaceFactory } from
import { DynamicFeature, DynamicFeatures } from './languageService/dynamicFeature'; import { DynamicFeature, DynamicFeatures } from './languageService/dynamicFeature';
import { FileWatcherDynamicFeature } from './languageService/fileWatcherDynamicFeature'; import { FileWatcherDynamicFeature } from './languageService/fileWatcherDynamicFeature';
export interface ServerOptions {
productName: string;
rootDirectory: Uri;
version: string;
cancellationProvider: CancellationProvider;
serviceProvider: ServiceProvider;
fileWatcherHandler: FileWatcherHandler;
maxAnalysisTimeInForeground?: MaxAnalysisTime;
disableChecker?: boolean;
supportedCommands?: string[];
supportedCodeActions?: string[];
supportsTelemetry?: boolean;
}
export interface WorkspaceServices {
fs: FileSystem | undefined;
backgroundAnalysis: BackgroundAnalysisBase | undefined;
}
export interface ClientCapabilities {
hasConfigurationCapability: boolean;
hasVisualStudioExtensionsCapability: boolean;
hasWorkspaceFoldersCapability: boolean;
hasWatchFileCapability: boolean;
hasWatchFileRelativePathCapability: boolean;
hasActiveParameterCapability: boolean;
hasSignatureLabelOffsetCapability: boolean;
hasHierarchicalDocumentSymbolCapability: boolean;
hasWindowProgressCapability: boolean;
hasGoToDeclarationCapability: boolean;
hasDocumentChangeCapability: boolean;
hasDocumentAnnotationCapability: boolean;
hasCompletionCommitCharCapability: boolean;
hoverContentFormat: MarkupKind;
completionDocFormat: MarkupKind;
completionSupportsSnippet: boolean;
signatureDocFormat: MarkupKind;
supportsDeprecatedDiagnosticTag: boolean;
supportsUnnecessaryDiagnosticTag: boolean;
supportsTaskItemDiagnosticTag: boolean;
completionItemResolveSupportsAdditionalTextEdits: boolean;
}
const nullProgressReporter = attachWorkDone(undefined as any, /* params */ undefined); const nullProgressReporter = attachWorkDone(undefined as any, /* params */ undefined);
/* /*
@ -799,7 +762,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
) { ) {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -812,7 +775,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
return locations return locations
.filter((loc) => this.canNavigateToFile(loc.uri, workspace.service.fs)) .filter((loc) => this.canNavigateToFile(loc.uri, workspace.service.fs))
.map((loc) => Location.create(encodeUri(workspace.service.fs, loc.uri), loc.range)); .map((loc) => Location.create(convertUriToLspUriString(workspace.service.fs, loc.uri), loc.range));
} }
protected async onReferences( protected async onReferences(
@ -841,7 +804,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
this._pendingFindAllRefsCancellationSource = source; this._pendingFindAllRefsCancellationSource = source;
try { try {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -868,7 +831,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
): Promise<DocumentSymbol[] | SymbolInformation[] | null | undefined> { ): Promise<DocumentSymbol[] | SymbolInformation[] | null | undefined> {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
return undefined; return undefined;
@ -901,7 +864,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
protected async onHover(params: HoverParams, token: CancellationToken) { protected async onHover(params: HoverParams, token: CancellationToken) {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
return workspace.service.run((program) => { return workspace.service.run((program) => {
@ -913,7 +876,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: DocumentHighlightParams, params: DocumentHighlightParams,
token: CancellationToken token: CancellationToken
): Promise<DocumentHighlight[] | null | undefined> { ): Promise<DocumentHighlight[] | null | undefined> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
return workspace.service.run((program) => { return workspace.service.run((program) => {
@ -925,7 +888,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: SignatureHelpParams, params: SignatureHelpParams,
token: CancellationToken token: CancellationToken
): Promise<SignatureHelp | undefined | null> { ): Promise<SignatureHelp | undefined | null> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -967,7 +930,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
protected async onCompletion(params: CompletionParams, token: CancellationToken): Promise<CompletionList | null> { protected async onCompletion(params: CompletionParams, token: CancellationToken): Promise<CompletionList | null> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
return null; return null;
@ -1001,7 +964,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected async onCompletionResolve(params: CompletionItem, token: CancellationToken): Promise<CompletionItem> { protected async onCompletionResolve(params: CompletionItem, token: CancellationToken): Promise<CompletionItem> {
const completionItemData = fromLSPAny<CompletionItemData>(params.data); const completionItemData = fromLSPAny<CompletionItemData>(params.data);
if (completionItemData && completionItemData.uri) { if (completionItemData && completionItemData.uri) {
const uri = this.decodeUri(completionItemData.uri); const uri = Uri.parse(completionItemData.uri, this.caseSensitiveDetector);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
workspace.service.run((program) => { workspace.service.run((program) => {
return new CompletionProvider( return new CompletionProvider(
@ -1024,7 +987,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: PrepareRenameParams, params: PrepareRenameParams,
token: CancellationToken token: CancellationToken
): Promise<Range | { range: Range; placeholder: string } | null> { ): Promise<Range | { range: Range; placeholder: string } | null> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const isUntitled = uri.isUntitled(); const isUntitled = uri.isUntitled();
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
@ -1044,7 +1007,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: RenameParams, params: RenameParams,
token: CancellationToken token: CancellationToken
): Promise<WorkspaceEdit | null | undefined> { ): Promise<WorkspaceEdit | null | undefined> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const isUntitled = uri.isUntitled(); const isUntitled = uri.isUntitled();
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
@ -1065,7 +1028,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: CallHierarchyPrepareParams, params: CallHierarchyPrepareParams,
token: CancellationToken token: CancellationToken
): Promise<CallHierarchyItem[] | null> { ): Promise<CallHierarchyItem[] | null> {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1078,7 +1041,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
protected async onCallHierarchyIncomingCalls(params: CallHierarchyIncomingCallsParams, token: CancellationToken) { protected async onCallHierarchyIncomingCalls(params: CallHierarchyIncomingCallsParams, token: CancellationToken) {
const uri = this.decodeUri(params.item.uri); const uri = this.convertLspUriStringToUri(params.item.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1094,7 +1057,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: CallHierarchyOutgoingCallsParams, params: CallHierarchyOutgoingCallsParams,
token: CancellationToken token: CancellationToken
): Promise<CallHierarchyOutgoingCall[] | null> { ): Promise<CallHierarchyOutgoingCall[] | null> {
const uri = this.decodeUri(params.item.uri); const uri = this.convertLspUriStringToUri(params.item.uri);
const workspace = await this.getWorkspaceForFile(uri); const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1107,7 +1070,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
protected async onDidOpenTextDocument(params: DidOpenTextDocumentParams, ipythonMode = IPythonMode.None) { protected async onDidOpenTextDocument(params: DidOpenTextDocumentParams, ipythonMode = IPythonMode.None) {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
let doc = this.openFileMap.get(uri.key); let doc = this.openFileMap.get(uri.key);
if (doc) { if (doc) {
@ -1134,7 +1097,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected async onDidChangeTextDocument(params: DidChangeTextDocumentParams, ipythonMode = IPythonMode.None) { protected async onDidChangeTextDocument(params: DidChangeTextDocumentParams, ipythonMode = IPythonMode.None) {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const doc = this.openFileMap.get(uri.key); const doc = this.openFileMap.get(uri.key);
if (!doc) { if (!doc) {
// We shouldn't get a change text request for a closed doc. // We shouldn't get a change text request for a closed doc.
@ -1153,7 +1116,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
protected async onDidCloseTextDocument(params: DidCloseTextDocumentParams) { protected async onDidCloseTextDocument(params: DidCloseTextDocumentParams) {
const uri = this.decodeUri(params.textDocument.uri); const uri = this.convertLspUriStringToUri(params.textDocument.uri);
// Send this close to all the workspaces that might contain this file. // Send this close to all the workspaces that might contain this file.
const workspaces = await this.getContainingWorkspacesForFile(uri); const workspaces = await this.getContainingWorkspacesForFile(uri);
@ -1166,7 +1129,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) { protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) {
params.changes.forEach((change) => { params.changes.forEach((change) => {
const filePath = this.fs.realCasePath(this.decodeUri(change.uri)); const filePath = this.fs.realCasePath(this.convertLspUriStringToUri(change.uri));
const eventType: FileWatcherEventType = change.type === 1 ? 'add' : 'change'; const eventType: FileWatcherEventType = change.type === 1 ? 'add' : 'change';
this.serverOptions.fileWatcherHandler.onFileChange(eventType, filePath); this.serverOptions.fileWatcherHandler.onFileChange(eventType, filePath);
}); });
@ -1241,7 +1204,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected convertDiagnostics(fs: FileSystem, fileDiagnostics: FileDiagnostics): PublishDiagnosticsParams[] { protected convertDiagnostics(fs: FileSystem, fileDiagnostics: FileDiagnostics): PublishDiagnosticsParams[] {
return [ return [
{ {
uri: encodeUri(fs, fileDiagnostics.fileUri), uri: convertUriToLspUriString(fs, fileDiagnostics.fileUri),
version: fileDiagnostics.version, version: fileDiagnostics.version,
diagnostics: this._convertDiagnostics(fs, fileDiagnostics.diagnostics), diagnostics: this._convertDiagnostics(fs, fileDiagnostics.diagnostics),
}, },
@ -1272,21 +1235,31 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
// Update progress. // Update progress.
if (results.filesRequiringAnalysis > 0) { const progressMessage = this.getProgressMessage(results);
if (progressMessage) {
this._progressReporter.begin(); this._progressReporter.begin();
const progressMessage =
results.filesRequiringAnalysis === 1
? Localizer.CodeAction.filesToAnalyzeOne()
: Localizer.CodeAction.filesToAnalyzeCount().format({
count: results.filesRequiringAnalysis,
});
this._progressReporter.report(progressMessage); this._progressReporter.report(progressMessage);
} else { } else {
this._progressReporter.end(); this._progressReporter.end();
} }
} }
protected getProgressMessage(results: AnalysisResults): string | undefined {
const fileCount = results.requiringAnalysisCount.files;
if (fileCount === 0) {
return undefined;
}
const progressMessage =
fileCount === 1
? Localizer.CodeAction.filesToAnalyzeOne()
: Localizer.CodeAction.filesToAnalyzeCount().format({
count: fileCount,
});
return progressMessage;
}
protected onWorkspaceCreated(workspace: Workspace) { protected onWorkspaceCreated(workspace: Workspace) {
// Update settings on this workspace (but only if initialize has happened) // Update settings on this workspace (but only if initialize has happened)
if (this._initialized) { if (this._initialized) {
@ -1300,7 +1273,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
const otherWorkspaces = this.workspaceFactory.items().filter((w) => w !== workspace); const otherWorkspaces = this.workspaceFactory.items().filter((w) => w !== workspace);
for (const uri of documentsWithDiagnosticsList) { for (const uri of documentsWithDiagnosticsList) {
const fileUri = this.decodeUri(uri); const fileUri = this.convertLspUriStringToUri(uri);
if (workspace.service.isTracked(fileUri)) { if (workspace.service.isTracked(fileUri)) {
// Do not clean up diagnostics for files tracked by multiple workspaces // Do not clean up diagnostics for files tracked by multiple workspaces
@ -1387,7 +1360,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
} }
} }
protected decodeUri(uri: string) { protected convertLspUriStringToUri(uri: string) {
return Uri.parse(uri, this.serverOptions.serviceProvider); return Uri.parse(uri, this.serverOptions.serviceProvider);
} }
@ -1479,7 +1452,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
.filter((info) => this.canNavigateToFile(info.uri, fs)) .filter((info) => this.canNavigateToFile(info.uri, fs))
.map((info) => .map((info) =>
DiagnosticRelatedInformation.create( DiagnosticRelatedInformation.create(
Location.create(encodeUri(fs, info.uri), info.range), Location.create(convertUriToLspUriString(fs, info.uri), info.range),
info.message info.message
) )
); );

View File

@ -13,7 +13,7 @@ import { AnalyzerService, getNextServiceId } from '../analyzer/service';
import { CommandLineOptions } from '../common/commandLineOptions'; import { CommandLineOptions } from '../common/commandLineOptions';
import { LogLevel } from '../common/console'; import { LogLevel } from '../common/console';
import { FileSystem } from '../common/fileSystem'; import { FileSystem } from '../common/fileSystem';
import { LanguageServerInterface, ServerSettings } from '../common/languageServerInterface'; import { LanguageServerBaseInterface, ServerSettings } from '../common/languageServerInterface';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { WellKnownWorkspaceKinds, Workspace, createInitStatus } from '../workspaceFactory'; import { WellKnownWorkspaceKinds, Workspace, createInitStatus } from '../workspaceFactory';
@ -44,7 +44,7 @@ export class AnalyzerServiceExecutor {
} }
static async cloneService( static async cloneService(
ls: LanguageServerInterface, ls: LanguageServerBaseInterface,
workspace: Workspace, workspace: Workspace,
options?: CloneOptions options?: CloneOptions
): Promise<AnalyzerService> { ): Promise<AnalyzerService> {

View File

@ -34,7 +34,7 @@ import { convertOffsetsToRange } from '../common/positionUtils';
import { ServiceKeys } from '../common/serviceKeys'; import { ServiceKeys } from '../common/serviceKeys';
import { Position, rangesAreEqual } from '../common/textRange'; import { Position, rangesAreEqual } from '../common/textRange';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { encodeUri } from '../common/uri/uriUtils'; import { convertUriToLspUriString } from '../common/uri/uriUtils';
import { ReferencesProvider, ReferencesResult } from '../languageService/referencesProvider'; import { ReferencesProvider, ReferencesResult } from '../languageService/referencesProvider';
import { CallNode, MemberAccessNode, NameNode, ParseNode, ParseNodeType } from '../parser/parseNodes'; import { CallNode, MemberAccessNode, NameNode, ParseNode, ParseNodeType } from '../parser/parseNodes';
import { ParseFileResults } from '../parser/parser'; import { ParseFileResults } from '../parser/parser';
@ -88,7 +88,7 @@ export class CallHierarchyProvider {
const callItem: CallHierarchyItem = { const callItem: CallHierarchyItem = {
name: symbolName, name: symbolName,
kind: getSymbolKind(targetDecl, this._evaluator, symbolName) ?? SymbolKind.Module, kind: getSymbolKind(targetDecl, this._evaluator, symbolName) ?? SymbolKind.Module,
uri: encodeUri(this._program.fileSystem, callItemUri), uri: convertUriToLspUriString(this._program.fileSystem, callItemUri),
range: targetDecl.range, range: targetDecl.range,
selectionRange: targetDecl.range, selectionRange: targetDecl.range,
}; };
@ -384,7 +384,7 @@ class FindOutgoingCallTreeWalker extends ParseTreeWalker {
const callDest: CallHierarchyItem = { const callDest: CallHierarchyItem = {
name: nameNode.value, name: nameNode.value,
kind: getSymbolKind(resolvedDecl, this._evaluator, nameNode.value) ?? SymbolKind.Module, kind: getSymbolKind(resolvedDecl, this._evaluator, nameNode.value) ?? SymbolKind.Module,
uri: encodeUri(this._fs, resolvedDecl.uri), uri: convertUriToLspUriString(this._fs, resolvedDecl.uri),
range: resolvedDecl.range, range: resolvedDecl.range,
selectionRange: resolvedDecl.range, selectionRange: resolvedDecl.range,
}; };
@ -569,7 +569,7 @@ class FindIncomingCallTreeWalker extends ParseTreeWalker {
callSource = { callSource = {
name: `(module) ${fileName}`, name: `(module) ${fileName}`,
kind: SymbolKind.Module, kind: SymbolKind.Module,
uri: encodeUri(this._program.fileSystem, this._fileUri), uri: convertUriToLspUriString(this._program.fileSystem, this._fileUri),
range: moduleRange, range: moduleRange,
selectionRange: moduleRange, selectionRange: moduleRange,
}; };
@ -583,7 +583,7 @@ class FindIncomingCallTreeWalker extends ParseTreeWalker {
callSource = { callSource = {
name: '(lambda)', name: '(lambda)',
kind: SymbolKind.Function, kind: SymbolKind.Function,
uri: encodeUri(this._program.fileSystem, this._fileUri), uri: convertUriToLspUriString(this._program.fileSystem, this._fileUri),
range: lambdaRange, range: lambdaRange,
selectionRange: lambdaRange, selectionRange: lambdaRange,
}; };
@ -597,7 +597,7 @@ class FindIncomingCallTreeWalker extends ParseTreeWalker {
callSource = { callSource = {
name: executionNode.name.value, name: executionNode.name.value,
kind: SymbolKind.Function, kind: SymbolKind.Function,
uri: encodeUri(this._program.fileSystem, this._fileUri), uri: convertUriToLspUriString(this._program.fileSystem, this._fileUri),
range: functionRange, range: functionRange,
selectionRange: functionRange, selectionRange: functionRange,
}; };

View File

@ -15,7 +15,7 @@ import { throwIfCancellationRequested } from '../common/cancellationUtils';
import { ProgramView } from '../common/extensibility'; import { ProgramView } from '../common/extensibility';
import { ReadOnlyFileSystem } from '../common/fileSystem'; import { ReadOnlyFileSystem } from '../common/fileSystem';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { encodeUri } from '../common/uri/uriUtils'; import { convertUriToLspUriString } from '../common/uri/uriUtils';
import { ParseFileResults } from '../parser/parser'; import { ParseFileResults } from '../parser/parser';
import { IndexOptions, IndexSymbolData, SymbolIndexer } from './symbolIndexer'; import { IndexOptions, IndexSymbolData, SymbolIndexer } from './symbolIndexer';
@ -125,7 +125,7 @@ function _appendToFlatSymbolsRecursive(
const flatSymbol: SymbolInformation = { const flatSymbol: SymbolInformation = {
name: symbol.name, name: symbol.name,
kind: symbol.kind, kind: symbol.kind,
location: Location.create(encodeUri(fs, documentUri), symbol.range), location: Location.create(convertUriToLspUriString(fs, documentUri), symbol.range),
}; };
if (symbol.tags) { if (symbol.tags) {

View File

@ -9,7 +9,7 @@ import { Location } from 'vscode-languageserver-types';
import { ReadOnlyFileSystem } from '../common/fileSystem'; import { ReadOnlyFileSystem } from '../common/fileSystem';
import { DocumentRange } from '../common/textRange'; import { DocumentRange } from '../common/textRange';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { encodeUri } from '../common/uri/uriUtils'; import { convertUriToLspUriString } from '../common/uri/uriUtils';
export function canNavigateToFile(fs: ReadOnlyFileSystem, path: Uri): boolean { export function canNavigateToFile(fs: ReadOnlyFileSystem, path: Uri): boolean {
return !fs.isInZip(path); return !fs.isInZip(path);
@ -28,5 +28,5 @@ export function convertDocumentRangeToLocation(fs: ReadOnlyFileSystem, range: Do
return undefined; return undefined;
} }
return Location.create(encodeUri(fs, range.uri), range.range); return Location.create(convertUriToLspUriString(fs, range.uri), range.range);
} }

View File

@ -14,7 +14,7 @@ import { appendArray } from '../common/collectionUtils';
import { ProgramView } from '../common/extensibility'; import { ProgramView } from '../common/extensibility';
import * as StringUtils from '../common/stringUtils'; import * as StringUtils from '../common/stringUtils';
import { Uri } from '../common/uri/uri'; import { Uri } from '../common/uri/uri';
import { encodeUri } from '../common/uri/uriUtils'; import { convertUriToLspUriString } from '../common/uri/uriUtils';
import { Workspace } from '../workspaceFactory'; import { Workspace } from '../workspaceFactory';
import { IndexSymbolData, SymbolIndexer } from './symbolIndexer'; import { IndexSymbolData, SymbolIndexer } from './symbolIndexer';
@ -100,7 +100,7 @@ export class WorkspaceSymbolProvider {
if (StringUtils.isPatternInSymbol(this._query, symbolData.name)) { if (StringUtils.isPatternInSymbol(this._query, symbolData.name)) {
const location: Location = { const location: Location = {
uri: encodeUri(program.fileSystem, fileUri), uri: convertUriToLspUriString(program.fileSystem, fileUri),
range: symbolData.selectionRange!, range: symbolData.selectionRange!,
}; };

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Rozbalení se v tomto kontextu nepovoluje", "unpackNotAllowed": "Rozbalení se v tomto kontextu nepovoluje",
"unpackOperatorNotAllowed": "Operace rozbalení není v tomto kontextu povolená", "unpackOperatorNotAllowed": "Operace rozbalení není v tomto kontextu povolená",
"unpackTuplesIllegal": "Operace rozbalení není povolená v řazených kolekcích členů před Pythonem 3.8", "unpackTuplesIllegal": "Operace rozbalení není povolená v řazených kolekcích členů před Pythonem 3.8",
"unpackedArgInTypeArgument": "Rozbalené argumenty není možné použít v seznamech argumentů typu", "unpackedArgInTypeArgument": "V tomto kontextu nelze použít rozbalené argumenty.",
"unpackedArgWithVariadicParam": "Pro parametr TypeVarTuple nejde použít rozbalený argument", "unpackedArgWithVariadicParam": "Pro parametr TypeVarTuple nejde použít rozbalený argument",
"unpackedDictArgumentNotMapping": "Výraz argumentu za ** musí být mapování s typem klíče str", "unpackedDictArgumentNotMapping": "Výraz argumentu za ** musí být mapování s typem klíče str",
"unpackedDictSubscriptIllegal": "Operátor rozbalení slovníku v dolním indexu není povolený", "unpackedDictSubscriptIllegal": "Operátor rozbalení slovníku v dolním indexu není povolený",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "Die Methode \"{name}\" überschreibt die Klasse \"{className}\" auf inkompatible Weise.", "incompatibleMethodOverride": "Die Methode \"{name}\" überschreibt die Klasse \"{className}\" auf inkompatible Weise.",
"inconsistentIndent": "Der Betrag für Nichteinzug stimmt nicht mit dem vorherigen Einzug überein.", "inconsistentIndent": "Der Betrag für Nichteinzug stimmt nicht mit dem vorherigen Einzug überein.",
"inconsistentTabs": "Inkonsistente Verwendung von Tabulatoren und Leerzeichen im Einzug.", "inconsistentTabs": "Inkonsistente Verwendung von Tabulatoren und Leerzeichen im Einzug.",
"initMethodSelfParamTypeVar": "Die Typanmerkung für den Parameter „self“ der Methode „__init__“ darf keine klassenbezogenen Typvariablen enthalten", "initMethodSelfParamTypeVar": "Typ-Anmerkung für \"self\"-Parameter der \"__init__\"-Methode kann keine klassenübergreifenden Typvariablen enthalten",
"initMustReturnNone": "Der Rückgabetyp von \"__init__\" muss \"None\" sein.", "initMustReturnNone": "Der Rückgabetyp von \"__init__\" muss \"None\" sein.",
"initSubclassCallFailed": "Falsche Schlüsselwortargumente für __init_subclass__ Methode.", "initSubclassCallFailed": "Falsche Schlüsselwortargumente für __init_subclass__ Methode.",
"initSubclassClsParam": "__init_subclass__ Außerkraftsetzung sollte einen \"cls\"-Parameter annehmen.", "initSubclassClsParam": "__init_subclass__ Außerkraftsetzung sollte einen \"cls\"-Parameter annehmen.",
@ -595,7 +595,7 @@
"unpackNotAllowed": "\"Unpack\" ist in diesem Kontext nicht zulässig.", "unpackNotAllowed": "\"Unpack\" ist in diesem Kontext nicht zulässig.",
"unpackOperatorNotAllowed": "Der Entpackvorgang ist in diesem Kontext nicht zulässig.", "unpackOperatorNotAllowed": "Der Entpackvorgang ist in diesem Kontext nicht zulässig.",
"unpackTuplesIllegal": "Der Entpackvorgang ist in Tupeln vor Python 3.8 nicht zulässig.", "unpackTuplesIllegal": "Der Entpackvorgang ist in Tupeln vor Python 3.8 nicht zulässig.",
"unpackedArgInTypeArgument": "Ungepackte Argumente können nicht in Typargumentlisten verwendet werden.", "unpackedArgInTypeArgument": "Nicht gepackte Argumente können in diesem Kontext nicht verwendet werden.",
"unpackedArgWithVariadicParam": "Das nicht gepackte Argument kann nicht für den Parameter \"TypeVarTuple\" verwendet werden.", "unpackedArgWithVariadicParam": "Das nicht gepackte Argument kann nicht für den Parameter \"TypeVarTuple\" verwendet werden.",
"unpackedDictArgumentNotMapping": "Der Argumentausdruck nach ** muss eine Zuordnung mit dem Schlüsseltyp \"str\" sein.", "unpackedDictArgumentNotMapping": "Der Argumentausdruck nach ** muss eine Zuordnung mit dem Schlüsseltyp \"str\" sein.",
"unpackedDictSubscriptIllegal": "Der Operator zum Entpacken des Wörterbuchs in tiefgestellten Zeichen ist nicht zulässig.", "unpackedDictSubscriptIllegal": "Der Operator zum Entpacken des Wörterbuchs in tiefgestellten Zeichen ist nicht zulässig.",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "El método \"{name}\" sobrescribe la clase \"{className}\" de forma incompatible", "incompatibleMethodOverride": "El método \"{name}\" sobrescribe la clase \"{className}\" de forma incompatible",
"inconsistentIndent": "La cantidad sin sangría no coincide con la sangría anterior", "inconsistentIndent": "La cantidad sin sangría no coincide con la sangría anterior",
"inconsistentTabs": "Uso incoherente de tabuladores y espacios en la sangría", "inconsistentTabs": "Uso incoherente de tabuladores y espacios en la sangría",
"initMethodSelfParamTypeVar": "La anotación de tipo para el parámetro \"self\" del método \"__init__\" no puede contener tipos con ámbito de clase.", "initMethodSelfParamTypeVar": "La anotación de tipo para el parámetro \"self\" del método \"__init__\" no puede contener variables de tipo con ámbito de clase",
"initMustReturnNone": "El tipo de retorno de \"__init__\" debe ser None", "initMustReturnNone": "El tipo de retorno de \"__init__\" debe ser None",
"initSubclassCallFailed": "Argumentos de palabra clave incorrectos para el método __init_subclass__", "initSubclassCallFailed": "Argumentos de palabra clave incorrectos para el método __init_subclass__",
"initSubclassClsParam": "__init_subclass__ debe tomar un parámetro \"cls\"", "initSubclassClsParam": "__init_subclass__ debe tomar un parámetro \"cls\"",
@ -595,7 +595,7 @@
"unpackNotAllowed": "El desempaquetado no está permitido en este contexto", "unpackNotAllowed": "El desempaquetado no está permitido en este contexto",
"unpackOperatorNotAllowed": "La operación de desempaquetado no está permitida en este contexto", "unpackOperatorNotAllowed": "La operación de desempaquetado no está permitida en este contexto",
"unpackTuplesIllegal": "Operación de desempaquetado no permitida en tuplas anteriores a Python 3.8", "unpackTuplesIllegal": "Operación de desempaquetado no permitida en tuplas anteriores a Python 3.8",
"unpackedArgInTypeArgument": "Los argumentos sin empaquetar no pueden utilizarse en listas de argumentos de tipo", "unpackedArgInTypeArgument": "No se pueden usar argumentos sin empaquetar en este contexto",
"unpackedArgWithVariadicParam": "No se puede usar un argumento desempaquetado para el parámetro TypeVarTuple", "unpackedArgWithVariadicParam": "No se puede usar un argumento desempaquetado para el parámetro TypeVarTuple",
"unpackedDictArgumentNotMapping": "La expresión del argumento después de ** debe ser un mapeo con un tipo de clave \"str\".", "unpackedDictArgumentNotMapping": "La expresión del argumento después de ** debe ser un mapeo con un tipo de clave \"str\".",
"unpackedDictSubscriptIllegal": "El operador de desempaquetado del diccionario en el subíndice no está permitido", "unpackedDictSubscriptIllegal": "El operador de desempaquetado del diccionario en el subíndice no está permitido",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "La méthode « {name} » remplace la classe « {className} » de manière incompatible", "incompatibleMethodOverride": "La méthode « {name} » remplace la classe « {className} » de manière incompatible",
"inconsistentIndent": "Le montant du retrait ne correspond pas au retrait précédent", "inconsistentIndent": "Le montant du retrait ne correspond pas au retrait précédent",
"inconsistentTabs": "Utilisation incohérente des onglets et des espaces dans la mise en retrait", "inconsistentTabs": "Utilisation incohérente des onglets et des espaces dans la mise en retrait",
"initMethodSelfParamTypeVar": "Lannotation de type pour le paramètre « self » de la méthode « __init__ » ne peut pas contenir de variables de type dont létendue est une classe", "initMethodSelfParamTypeVar": "Lannotation de type pour le paramètre « self » de la méthode « __init__ » ne peut pas contenir de variables de type de portée de classe",
"initMustReturnNone": "Le type de retour de « __init__ » doit être None", "initMustReturnNone": "Le type de retour de « __init__ » doit être None",
"initSubclassCallFailed": "Arguments de mot clé incorrects pour la méthode __init_subclass__", "initSubclassCallFailed": "Arguments de mot clé incorrects pour la méthode __init_subclass__",
"initSubclassClsParam": "__init_subclass__ remplacement doit prendre un paramètre « cls »", "initSubclassClsParam": "__init_subclass__ remplacement doit prendre un paramètre « cls »",
@ -595,7 +595,7 @@
"unpackNotAllowed": "Le décompression nest pas autorisé dans ce contexte", "unpackNotAllowed": "Le décompression nest pas autorisé dans ce contexte",
"unpackOperatorNotAllowed": "Lopération de décompression nest pas autorisée dans ce contexte", "unpackOperatorNotAllowed": "Lopération de décompression nest pas autorisée dans ce contexte",
"unpackTuplesIllegal": "Opération de décompression non autorisée dans les tuples avant Python 3.8", "unpackTuplesIllegal": "Opération de décompression non autorisée dans les tuples avant Python 3.8",
"unpackedArgInTypeArgument": "Les arguments décompressés ne peuvent pas être utilisés dans les listes darguments de type", "unpackedArgInTypeArgument": "Les arguments décompressés ne peuvent pas être utilisés dans ce contexte",
"unpackedArgWithVariadicParam": "L'argument décompressé ne peut pas être utilisé pour le paramètre TypeVarTuple", "unpackedArgWithVariadicParam": "L'argument décompressé ne peut pas être utilisé pour le paramètre TypeVarTuple",
"unpackedDictArgumentNotMapping": "Lexpression dargument après ** doit être un mappage avec un type de clé « str »", "unpackedDictArgumentNotMapping": "Lexpression dargument après ** doit être un mappage avec un type de clé « str »",
"unpackedDictSubscriptIllegal": "Lopérateur de décompression de dictionnaire dans lindice nest pas autorisé", "unpackedDictSubscriptIllegal": "Lopérateur de décompression de dictionnaire dans lindice nest pas autorisé",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "La decompressione non è consentita in questo contesto", "unpackNotAllowed": "La decompressione non è consentita in questo contesto",
"unpackOperatorNotAllowed": "Loperazione di decompressione non è consentita in questo contesto", "unpackOperatorNotAllowed": "Loperazione di decompressione non è consentita in questo contesto",
"unpackTuplesIllegal": "L'operazione di decompressione non è consentita nelle tuple precedenti a Python 3.8", "unpackTuplesIllegal": "L'operazione di decompressione non è consentita nelle tuple precedenti a Python 3.8",
"unpackedArgInTypeArgument": "Gli argomenti non compressi non possono essere usati negli elenchi di argomenti tipo", "unpackedArgInTypeArgument": "Non è possibile usare argomenti decompressi in questo contesto",
"unpackedArgWithVariadicParam": "Non è possibile usare l'argomento decompresso per il parametro TypeVarTuple", "unpackedArgWithVariadicParam": "Non è possibile usare l'argomento decompresso per il parametro TypeVarTuple",
"unpackedDictArgumentNotMapping": "L'espressione dell'argomento dopo ** deve essere un mapping con un tipo di chiave \"str\"", "unpackedDictArgumentNotMapping": "L'espressione dell'argomento dopo ** deve essere un mapping con un tipo di chiave \"str\"",
"unpackedDictSubscriptIllegal": "L'operatore di decompressione del dizionario nel pedice non è consentito", "unpackedDictSubscriptIllegal": "L'operatore di decompressione del dizionario nel pedice non è consentito",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "メソッド \"{name}\" は互換性のない方法でクラス \"{className}\" をオーバーライドします", "incompatibleMethodOverride": "メソッド \"{name}\" は互換性のない方法でクラス \"{className}\" をオーバーライドします",
"inconsistentIndent": "元のサイズが前のインデントと一致しません", "inconsistentIndent": "元のサイズが前のインデントと一致しません",
"inconsistentTabs": "インデントでのタブとスペースの一貫性のない使用", "inconsistentTabs": "インデントでのタブとスペースの一貫性のない使用",
"initMethodSelfParamTypeVar": "\"__init__\" メソッドの \"self\" パラメーターの型注釈にクラス スコープ型の変数を含めることはできません", "initMethodSelfParamTypeVar": "\"__init__\" メソッドの \"self\" パラメーターの型注釈にクラス スコープ型の変数を含めることはできません",
"initMustReturnNone": "\"__init__\" の戻り値の型は None でなければなりません", "initMustReturnNone": "\"__init__\" の戻り値の型は None でなければなりません",
"initSubclassCallFailed": "__init_subclass__ メソッドのキーワード引数が正しくありません", "initSubclassCallFailed": "__init_subclass__ メソッドのキーワード引数が正しくありません",
"initSubclassClsParam": "__class_getitem__ override は \"cls\" パラメーターを受け取る必要があります", "initSubclassClsParam": "__class_getitem__ override は \"cls\" パラメーターを受け取る必要があります",
@ -595,7 +595,7 @@
"unpackNotAllowed": "アンパックはこのコンテキストでは許可されていません", "unpackNotAllowed": "アンパックはこのコンテキストでは許可されていません",
"unpackOperatorNotAllowed": "このコンテキストではアンパック操作は許可されていません", "unpackOperatorNotAllowed": "このコンテキストではアンパック操作は許可されていません",
"unpackTuplesIllegal": "Python 3.8 より前のタプルではアンパック操作は許可されていません", "unpackTuplesIllegal": "Python 3.8 より前のタプルではアンパック操作は許可されていません",
"unpackedArgInTypeArgument": "アンパックされた引数は、型引数リストでは使用できません", "unpackedArgInTypeArgument": "アンパックされた引数は、このコンテキストでは使用できません",
"unpackedArgWithVariadicParam": "アンパックされた引数は TypeVarTuple パラメーターには使用できません", "unpackedArgWithVariadicParam": "アンパックされた引数は TypeVarTuple パラメーターには使用できません",
"unpackedDictArgumentNotMapping": "** の後の引数式は、\"str\" キー型のマッピングである必要があります", "unpackedDictArgumentNotMapping": "** の後の引数式は、\"str\" キー型のマッピングである必要があります",
"unpackedDictSubscriptIllegal": "下付き文字の辞書アンパック演算子は使用できません", "unpackedDictSubscriptIllegal": "下付き文字の辞書アンパック演算子は使用できません",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "이 컨텍스트에서는 압축 풀기가 허용되지 않습니다.", "unpackNotAllowed": "이 컨텍스트에서는 압축 풀기가 허용되지 않습니다.",
"unpackOperatorNotAllowed": "이 컨텍스트에서는 압축 풀기 작업이 허용되지 않습니다.", "unpackOperatorNotAllowed": "이 컨텍스트에서는 압축 풀기 작업이 허용되지 않습니다.",
"unpackTuplesIllegal": "Python 3.8 이전의 튜플에서는 압축 풀기 작업이 허용되지 않습니다.", "unpackTuplesIllegal": "Python 3.8 이전의 튜플에서는 압축 풀기 작업이 허용되지 않습니다.",
"unpackedArgInTypeArgument": "압축되지 않은 인수는 형식 인수 목록에 사용할 수 없습니다.", "unpackedArgInTypeArgument": "압축을 푼 인수는 이 컨텍스트에서 사용할 수 없음",
"unpackedArgWithVariadicParam": "압축을 푼 인수는 TypeVarTuple 매개 변수에 사용할 수 없습니다.", "unpackedArgWithVariadicParam": "압축을 푼 인수는 TypeVarTuple 매개 변수에 사용할 수 없습니다.",
"unpackedDictArgumentNotMapping": "** 뒤의 인수 식은 \"str\" 키 형식의 매핑이어야 합니다.", "unpackedDictArgumentNotMapping": "** 뒤의 인수 식은 \"str\" 키 형식의 매핑이어야 합니다.",
"unpackedDictSubscriptIllegal": "아래 첨자에서 사전 압축 풀기 연산자는 사용할 수 없습니다.", "unpackedDictSubscriptIllegal": "아래 첨자에서 사전 압축 풀기 연산자는 사용할 수 없습니다.",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Rozpakowywanie jest niedozwolone w tym kontekście", "unpackNotAllowed": "Rozpakowywanie jest niedozwolone w tym kontekście",
"unpackOperatorNotAllowed": "Operacja rozpakowywania jest niedozwolona w tym kontekście", "unpackOperatorNotAllowed": "Operacja rozpakowywania jest niedozwolona w tym kontekście",
"unpackTuplesIllegal": "Operacja rozpakowywania nie jest dozwolona w krotkach przed językiem Python w wersji 3.8", "unpackTuplesIllegal": "Operacja rozpakowywania nie jest dozwolona w krotkach przed językiem Python w wersji 3.8",
"unpackedArgInTypeArgument": "Rozpakowanych argumentów nie można używać na listach argumentów typu", "unpackedArgInTypeArgument": "Nie można użyć nierozpakowanych argumentów w tym kontekście",
"unpackedArgWithVariadicParam": "Nie można użyć nierozpakowanego argumentu dla parametru TypeVarTuple", "unpackedArgWithVariadicParam": "Nie można użyć nierozpakowanego argumentu dla parametru TypeVarTuple",
"unpackedDictArgumentNotMapping": "Wyrażenie argumentu po znakach ** musi być mapowaniem z typem klucza „str”", "unpackedDictArgumentNotMapping": "Wyrażenie argumentu po znakach ** musi być mapowaniem z typem klucza „str”",
"unpackedDictSubscriptIllegal": "Operator rozpakowywania słownika w indeksie dolnym jest niedozwolony", "unpackedDictSubscriptIllegal": "Operator rozpakowywania słownika w indeksie dolnym jest niedozwolony",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Descompactar não é permitido neste contexto", "unpackNotAllowed": "Descompactar não é permitido neste contexto",
"unpackOperatorNotAllowed": "A operação de descompactação não é permitida neste contexto", "unpackOperatorNotAllowed": "A operação de descompactação não é permitida neste contexto",
"unpackTuplesIllegal": "Operação de desempacotamento não permitida em tuplas anteriores ao Python 3.8", "unpackTuplesIllegal": "Operação de desempacotamento não permitida em tuplas anteriores ao Python 3.8",
"unpackedArgInTypeArgument": "Argumentos desempacotamento não podem ser usados em listas de argumentos de tipo", "unpackedArgInTypeArgument": "Os argumentos descompactados não podem ser usados nesse contexto",
"unpackedArgWithVariadicParam": "O argumento desempacotado não pode ser usado para o parâmetro TypeVarTuple", "unpackedArgWithVariadicParam": "O argumento desempacotado não pode ser usado para o parâmetro TypeVarTuple",
"unpackedDictArgumentNotMapping": "A expressão de argumento após ** deve ser um mapeamento com um tipo de chave \"str\"", "unpackedDictArgumentNotMapping": "A expressão de argumento após ** deve ser um mapeamento com um tipo de chave \"str\"",
"unpackedDictSubscriptIllegal": "O operador de desempacotamento de dicionário no subscrito não é permitido", "unpackedDictSubscriptIllegal": "O operador de desempacotamento de dicionário no subscrito não é permitido",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "[i45Ka][นั้Mëthøð \"{ñæmë}\" øvërrïðës çlæss \"{çlæssÑæmë}\" ïñ æñ ïñçømpætïþlë mæññërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]", "incompatibleMethodOverride": "[i45Ka][นั้Mëthøð \"{ñæmë}\" øvërrïðës çlæss \"{çlæssÑæmë}\" ïñ æñ ïñçømpætïþlë mæññërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]",
"inconsistentIndent": "[gdrcy][นั้Üñïñðëñt æmøµñt ðøës ñøt mætçh prëvïøµs ïñðëñtẤğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]", "inconsistentIndent": "[gdrcy][นั้Üñïñðëñt æmøµñt ðøës ñøt mætçh prëvïøµs ïñðëñtẤğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]",
"inconsistentTabs": "[I3Z6K][นั้Ïñçøñsïstëñt µsë øf tæþs æñð spæçës ïñ ïñðëñtætïøñẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]", "inconsistentTabs": "[I3Z6K][นั้Ïñçøñsïstëñt µsë øf tæþs æñð spæçës ïñ ïñðëñtætïøñẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]",
"initMethodSelfParamTypeVar": "[S5RC7][นั้Tÿpë æññøtætïøñ før \"sëlf\" pæræmëtër øf \"__ïñït__\" mëthøð çæññøt çøñtæïñ çlæss-sçøpëð tÿpë væræïæþlësẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]", "initMethodSelfParamTypeVar": "[S5RC7][นั้Tÿpë æññøtætïøñ før \"sëlf\" pæræmëtër øf \"__ïñït__\" mëthøð çæññøt çøñtæïñ çlæss-sçøpëð tÿpë værïæþlësẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]",
"initMustReturnNone": "[RlXyC][นั้Rëtµrñ tÿpë øf \"__ïñït__\" mµst þë ÑøñëẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]", "initMustReturnNone": "[RlXyC][นั้Rëtµrñ tÿpë øf \"__ïñït__\" mµst þë ÑøñëẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
"initSubclassCallFailed": "[w22Kh][นั้Ïñçørrëçt këÿwørð ærgµmëñts før __ïñït_sµþçlæss__ mëthøðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "initSubclassCallFailed": "[w22Kh][นั้Ïñçørrëçt këÿwørð ærgµmëñts før __ïñït_sµþçlæss__ mëthøðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
"initSubclassClsParam": "[6CWuS][นั้__ïñït_sµþçlæss__ øvërrïðë shøµlð tækë æ \"çls\" pæræmëtërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "initSubclassClsParam": "[6CWuS][นั้__ïñït_sµþçlæss__ øvërrïðë shøµlð tækë æ \"çls\" pæræmëtërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
@ -595,7 +595,7 @@
"unpackNotAllowed": "[MZq6e][นั้Üñpæçk ïs ñøt ælløwëð ïñ thïs çøñtëxtẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]", "unpackNotAllowed": "[MZq6e][นั้Üñpæçk ïs ñøt ælløwëð ïñ thïs çøñtëxtẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
"unpackOperatorNotAllowed": "[lMq2B][นั้Üñpæçk øpërætïøñ ïs ñøt ælløwëð ïñ thïs çøñtëxtẤğ倪İЂҰक्र्तिृまẤğ倪İЂนั้ढूँ]", "unpackOperatorNotAllowed": "[lMq2B][นั้Üñpæçk øpërætïøñ ïs ñøt ælløwëð ïñ thïs çøñtëxtẤğ倪İЂҰक्र्तिृまẤğ倪İЂนั้ढूँ]",
"unpackTuplesIllegal": "[RJvzW][นั้Üñpæçk øpërætïøñ ñøt ælløwëð ïñ tµplës prïør tø Pÿthøñ 3.8Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]", "unpackTuplesIllegal": "[RJvzW][นั้Üñpæçk øpërætïøñ ñøt ælløwëð ïñ tµplës prïør tø Pÿthøñ 3.8Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]",
"unpackedArgInTypeArgument": "[skxlo][นั้Üñpæçkëð ærgµmëñts çæññøt þë µsëð ïñ tÿpë ærgµmëñt lïstsẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "unpackedArgInTypeArgument": "[skxlo][นั้Üñpæçkëð ærgµmëñts çæññøt þë µsëð ïñ thïs çøñtëxtẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]",
"unpackedArgWithVariadicParam": "[ZP3kP][นั้Üñpæçkëð ærgµmëñt çæññøt þë µsëð før TÿpëVærTµplë pæræmëtërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]", "unpackedArgWithVariadicParam": "[ZP3kP][นั้Üñpæçkëð ærgµmëñt çæññøt þë µsëð før TÿpëVærTµplë pæræmëtërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]",
"unpackedDictArgumentNotMapping": "[iSTnU][นั้Ærgµmëñt ëxprëssïøñ æftër ** mµst þë æ mæppïñg wïth æ \"str\" këÿ tÿpëẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]", "unpackedDictArgumentNotMapping": "[iSTnU][นั้Ærgµmëñt ëxprëssïøñ æftër ** mµst þë æ mæppïñg wïth æ \"str\" këÿ tÿpëẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]",
"unpackedDictSubscriptIllegal": "[slATr][นั้Ðïçtïøñærÿ µñpæçk øpërætør ïñ sµþsçrïpt ïs ñøt ælløwëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "unpackedDictSubscriptIllegal": "[slATr][นั้Ðïçtïøñærÿ µñpæçk øpërætør ïñ sµþsçrïpt ïs ñøt ælløwëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "Метод \"{name}\" переопределяет класс \"{className}\" несовместимым образом", "incompatibleMethodOverride": "Метод \"{name}\" переопределяет класс \"{className}\" несовместимым образом",
"inconsistentIndent": "Сумма отступа не соответствует предыдущему отступу", "inconsistentIndent": "Сумма отступа не соответствует предыдущему отступу",
"inconsistentTabs": "Непоследовательное использование вкладок и пробелов в отступах", "inconsistentTabs": "Непоследовательное использование вкладок и пробелов в отступах",
"initMethodSelfParamTypeVar": "Аннотация типа для параметра \"self\" метода \"__init__\" не может содержать переменные типов с областью класса", "initMethodSelfParamTypeVar": "Заметка типа для параметра \"self\" метода \"__init__\" не может содержать переменные типа в области класса.",
"initMustReturnNone": "Метод \"__init__\" должен возвращать тип None", "initMustReturnNone": "Метод \"__init__\" должен возвращать тип None",
"initSubclassCallFailed": "Неверные аргументы ключевых слов для метода __init_subclass__", "initSubclassCallFailed": "Неверные аргументы ключевых слов для метода __init_subclass__",
"initSubclassClsParam": "Переопределение метода __init_subclass__ должно принимать параметр \"cls\"", "initSubclassClsParam": "Переопределение метода __init_subclass__ должно принимать параметр \"cls\"",
@ -595,7 +595,7 @@
"unpackNotAllowed": "Распаковка допускается в этом контексте", "unpackNotAllowed": "Распаковка допускается в этом контексте",
"unpackOperatorNotAllowed": "Операция распаковки допускается в этом контексте", "unpackOperatorNotAllowed": "Операция распаковки допускается в этом контексте",
"unpackTuplesIllegal": "Операцию распаковки в кортежах можно использовать в Python версии не ниже 3.8", "unpackTuplesIllegal": "Операцию распаковки в кортежах можно использовать в Python версии не ниже 3.8",
"unpackedArgInTypeArgument": "Неупакованные аргументы нельзя использовать в списках аргументов типа", "unpackedArgInTypeArgument": "В этом контексте нельзя использовать распакованные аргументы",
"unpackedArgWithVariadicParam": "Невозможно использовать распакованный аргумент для параметра TypeVarTuple", "unpackedArgWithVariadicParam": "Невозможно использовать распакованный аргумент для параметра TypeVarTuple",
"unpackedDictArgumentNotMapping": "Выражение аргумента после ** должно быть сопоставлением с типом ключа \"str\".", "unpackedDictArgumentNotMapping": "Выражение аргумента после ** должно быть сопоставлением с типом ключа \"str\".",
"unpackedDictSubscriptIllegal": "Оператор распаковки словаря не допускается внутри операции взятия подстроки", "unpackedDictSubscriptIllegal": "Оператор распаковки словаря не допускается внутри операции взятия подстроки",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Bu bağlamda paketi açma işlemine izin verilmiyor", "unpackNotAllowed": "Bu bağlamda paketi açma işlemine izin verilmiyor",
"unpackOperatorNotAllowed": "Bu bağlamda paket açma işlemi kullanılamaz", "unpackOperatorNotAllowed": "Bu bağlamda paket açma işlemi kullanılamaz",
"unpackTuplesIllegal": "Python 3.8'den önceki demetler içinde paket açma işlemi kullanılamıyor", "unpackTuplesIllegal": "Python 3.8'den önceki demetler içinde paket açma işlemi kullanılamıyor",
"unpackedArgInTypeArgument": "Paketlenmemiş bağımsız değişkenler tür bağımsız değişkeni listelerinde kullanılamaz", "unpackedArgInTypeArgument": "Paketlenmemiş bağımsız değişkenler bu bağlamda kullanılamaz",
"unpackedArgWithVariadicParam": "Paketlenmemiş bağımsız değişken, TypeVarTuple parametresi için kullanılamaz", "unpackedArgWithVariadicParam": "Paketlenmemiş bağımsız değişken, TypeVarTuple parametresi için kullanılamaz",
"unpackedDictArgumentNotMapping": "** sonrasındaki bağımsız değişken ifadesi \"str\" anahtar türüne sahip bir eşleme olmalıdır", "unpackedDictArgumentNotMapping": "** sonrasındaki bağımsız değişken ifadesi \"str\" anahtar türüne sahip bir eşleme olmalıdır",
"unpackedDictSubscriptIllegal": "Alt simgede sözlük açma işlecine izin verilmiyor", "unpackedDictSubscriptIllegal": "Alt simgede sözlük açma işlecine izin verilmiyor",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "方法“{name}”以不兼容的方式替代类“{className}”", "incompatibleMethodOverride": "方法“{name}”以不兼容的方式替代类“{className}”",
"inconsistentIndent": "取消缩进量与以前的缩进不匹配", "inconsistentIndent": "取消缩进量与以前的缩进不匹配",
"inconsistentTabs": "缩进中制表符和空格的使用不一致", "inconsistentTabs": "缩进中制表符和空格的使用不一致",
"initMethodSelfParamTypeVar": "\"__init__\" 方法 “self” 参数的类型注不能包含类范围的类型变量", "initMethodSelfParamTypeVar": "\"__init__\" 方法 “self” 参数的类型不能包含类范围的类型变量",
"initMustReturnNone": "“__init__”的返回类型必须为 None", "initMustReturnNone": "“__init__”的返回类型必须为 None",
"initSubclassCallFailed": "__init_subclass__ 方法的关键字参数不正确", "initSubclassCallFailed": "__init_subclass__ 方法的关键字参数不正确",
"initSubclassClsParam": "__init_subclass__替代应采用“cls”参数", "initSubclassClsParam": "__init_subclass__替代应采用“cls”参数",
@ -595,7 +595,7 @@
"unpackNotAllowed": "此上下文中不允许解包", "unpackNotAllowed": "此上下文中不允许解包",
"unpackOperatorNotAllowed": "此上下文中不允许解压缩操作", "unpackOperatorNotAllowed": "此上下文中不允许解压缩操作",
"unpackTuplesIllegal": "Python 3.8 之前的元组中不允许解包操作", "unpackTuplesIllegal": "Python 3.8 之前的元组中不允许解包操作",
"unpackedArgInTypeArgument": "无法在类型参数列表中使用未打包的参数", "unpackedArgInTypeArgument": "未打包的参数不能用于此上下文",
"unpackedArgWithVariadicParam": "未打包的参数不能用于 TypeVarTuple 参数", "unpackedArgWithVariadicParam": "未打包的参数不能用于 TypeVarTuple 参数",
"unpackedDictArgumentNotMapping": "** 后面的参数表达式必须是具有“str”键类型的映射", "unpackedDictArgumentNotMapping": "** 后面的参数表达式必须是具有“str”键类型的映射",
"unpackedDictSubscriptIllegal": "不允许在下标中使用字典解包运算符", "unpackedDictSubscriptIllegal": "不允许在下标中使用字典解包运算符",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "此內容中不允許解壓縮", "unpackNotAllowed": "此內容中不允許解壓縮",
"unpackOperatorNotAllowed": "此內容中不允許解壓縮作業", "unpackOperatorNotAllowed": "此內容中不允許解壓縮作業",
"unpackTuplesIllegal": "Python 3.8 之前的 Tuple 中不允許解壓縮作業", "unpackTuplesIllegal": "Python 3.8 之前的 Tuple 中不允許解壓縮作業",
"unpackedArgInTypeArgument": "解壓縮的引數不能用於類型引數清單", "unpackedArgInTypeArgument": "無法在此內容中使用未封裝的引數",
"unpackedArgWithVariadicParam": "未封裝的引數無法用於 TypeVarTuple 參數", "unpackedArgWithVariadicParam": "未封裝的引數無法用於 TypeVarTuple 參數",
"unpackedDictArgumentNotMapping": "** 後的引數運算式必須是具有 \"str\" 金鑰類型的對應", "unpackedDictArgumentNotMapping": "** 後的引數運算式必須是具有 \"str\" 金鑰類型的對應",
"unpackedDictSubscriptIllegal": "字典解壓縮運算子在下標中不被允許", "unpackedDictSubscriptIllegal": "字典解壓縮運算子在下標中不被允許",

View File

@ -438,7 +438,7 @@ async function processArgs(): Promise<ExitStatus> {
} }
} }
if (args.createstub && results.filesRequiringAnalysis === 0) { if (args.createstub && results.requiringAnalysisCount.files === 0) {
try { try {
service.writeTypeStub(cancellationNone); service.writeTypeStub(cancellationNone);
service.dispose(); service.dispose();

View File

@ -359,3 +359,23 @@ test('import symbol tooltip - useLibraryCodeForTypes true', async () => {
marker1: '```python\n(class) bar\n```', marker1: '```python\n(class) bar\n```',
}); });
}); });
test('TypedDict doc string', async () => {
const code = `
// @filename: test.py
//// from typing import [|/*marker*/TypedDict|]
// @filename: typing.py
// @library: true
//// def TypedDict(typename, fields=None, /, *, total=True, **kwargs):
//// """A simple typed namespace. At runtime it is equivalent to a plain dict."""
`;
const state = parseAndGetTestState(code).state;
const marker1 = state.getMarkerByName('marker');
state.openFile(marker1.fileName);
state.verifyHover('markdown', {
marker: '```python\n(class) TypedDict\n```\n---\nA simple typed namespace. At runtime it is equivalent to a plain dict.',
});
});