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[];
filesInProgram: number;
checkingOnlyOpenFiles: boolean;
filesRequiringAnalysis: number;
requiringAnalysisCount: RequiringAnalysisCount;
fatalErrorOccurred: boolean;
configParseErrorOccurred: boolean;
elapsedTime: number;
error?: Error | undefined;
}
export interface RequiringAnalysisCount {
files: number;
cells: number;
}
export type AnalysisCompleteCallback = (results: AnalysisResults) => void;
export function analyzeProgram(
@ -51,7 +56,7 @@ export function analyzeProgram(
const duration = new Duration();
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
// want to report all diagnostics rather than just the ones that have changed.
@ -66,7 +71,7 @@ export function analyzeProgram(
callback({
diagnostics,
filesInProgram: program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze,
requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false,
configParseErrorOccurred: false,
@ -84,7 +89,7 @@ export function analyzeProgram(
callback({
diagnostics: [],
filesInProgram: 0,
filesRequiringAnalysis: 0,
requiringAnalysisCount: { files: 0, cells: 0 },
checkingOnlyOpenFiles: true,
fatalErrorOccurred: true,
configParseErrorOccurred: false,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@ import { isMainThread } from 'worker_threads';
import { OperationCanceledException } from '../common/cancellationUtils';
import { appendArray } from '../common/collectionUtils';
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 { Diagnostic, DiagnosticCategory, TaskListToken, convertLevelToCategory } from '../common/diagnostic';
import { DiagnosticRule } from '../common/diagnosticRules';
@ -95,7 +95,6 @@ class WriteableData {
// the binder information hanging from it?
parseTreeNeedsCleaning = false;
parserOutput: ParserOutput | undefined;
parsedFileContents: string | undefined;
tokenizerLines: TextRangeCollection<TextRange> | undefined;
tokenizerOutput: TokenizerOutput | undefined;
@ -142,6 +141,30 @@ class WriteableData {
// True if the file appears to have been deleted.
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() {
return `WritableData:
diagnosticVersion=${this.diagnosticVersion},
@ -171,7 +194,8 @@ class WriteableData {
pyrightIgnoreLines=${this.pyrightIgnoreLines?.size},
checkTime=${this.checkTime},
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 {
// Data that changes when the source file changes.
private _writableData = new WriteableData();
// Console interface to use for debugging.
private _console: ConsoleInterface;
@ -232,6 +253,10 @@ export class SourceFile {
private _ipythonMode = IPythonMode.None;
private _logTracker: LogTracker;
private _preEditData: WriteableData | undefined;
// Data that changes when the source file changes.
private _writableData: WriteableData;
readonly fileSystem: FileSystem;
constructor(
@ -247,6 +272,8 @@ export class SourceFile {
) {
this.fileSystem = serviceProvider.get(ServiceKeys.fs);
this._console = console || new StandardConsole();
this._writableData = new WriteableData(this._console);
this._editMode = editMode;
this._uri = uri;
this._moduleName = moduleName;
@ -864,7 +891,7 @@ export class SourceFile {
sourceMapper: SourceMapper,
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._writableData.isBindingInProgress, 'Check called while binding in progress');
assert(this.isCheckingRequired(), 'Check called unnecessarily');
@ -1209,7 +1236,7 @@ export class SourceFile {
this._preEditData = this._writableData;
// 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

View File

@ -12,11 +12,12 @@ import {
ClassDeclaration,
Declaration,
DeclarationBase,
DeclarationType,
FunctionDeclaration,
isClassDeclaration,
isFunctionDeclaration,
isSpecialBuiltInClassDeclaration,
isVariableDeclaration,
SpecialBuiltInClassDeclaration,
VariableDeclaration,
} from '../analyzer/declaration';
import * as ParseTreeUtils from '../analyzer/parseTreeUtils';
@ -227,9 +228,9 @@ export function getClassDocString(
sourceMapper: SourceMapper
) {
let docString = classType.details.docString;
if (!docString && resolvedDecl && isClassDeclaration(resolvedDecl)) {
docString = _getFunctionOrClassDeclsDocString([resolvedDecl]);
if (!docString && resolvedDecl && isStubFile(resolvedDecl.uri) && resolvedDecl.type === DeclarationType.Class) {
if (!docString && resolvedDecl && _isAnyClassDeclaration(resolvedDecl)) {
docString = isClassDeclaration(resolvedDecl) ? _getFunctionOrClassDeclsDocString([resolvedDecl]) : undefined;
if (!docString && resolvedDecl && isStubFile(resolvedDecl.uri)) {
for (const implDecl of sourceMapper.findDeclarations(resolvedDecl)) {
if (isVariableDeclaration(implDecl) && !!implDecl.docString) {
docString = implDecl.docString;
@ -386,3 +387,7 @@ function _getFunctionOrClassDeclsDocString(decls: FunctionDeclaration[] | ClassD
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 { 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 { ImportResolver } from './analyzer/importResolver';
import { OpenFileOptions, Program } from './analyzer/program';
@ -473,12 +479,12 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
protected handleAnalyze(port: MessagePort, cancellationId: string, token: CancellationToken) {
// Report files to analyze first.
const filesLeftToAnalyze = this.program.getFilesToAnalyzeCount();
const requiringAnalysisCount = this.program.getFilesToAnalyzeCount();
this.onAnalysisCompletion(port, {
diagnostics: [],
filesInProgram: this.program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze,
requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: 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) {
this.onAnalysisCompletion(parentPort, {
diagnostics,
filesInProgram: this.program.getFileCount(),
filesRequiringAnalysis: filesLeftToAnalyze,
requiringAnalysisCount: requiringAnalysisCount,
checkingOnlyOpenFiles: this.program.isCheckingOnlyOpenFiles(),
fatalErrorOccurred: false,
configParseErrorOccurred: false,

View File

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

View File

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

View File

@ -6,13 +6,19 @@
* Interface for language server
*/
import { MarkupKind } from 'vscode-languageserver';
import { MaxAnalysisTime } from '../analyzer/program';
import { BackgroundAnalysisBase } from '../backgroundAnalysisBase';
import { Workspace } from '../workspaceFactory';
import { CancellationProvider } from './cancellationUtils';
import { DiagnosticSeverityOverridesMap } from './commandLineOptions';
import { SignatureDisplayType } from './configOptions';
import { ConsoleInterface, LogLevel } from './console';
import { TaskListToken } from './diagnostic';
import * as ext from './extensibility';
import { FileSystem } from './fileSystem';
import { FileWatcherHandler } from './fileWatcher';
import { ServiceProvider } from './serviceProvider';
import { Uri } from './uri/uri';
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 {
readonly console: ConsoleInterface;
readonly window: WindowInterface;

View File

@ -234,6 +234,8 @@ export namespace Uri {
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 DefaultWorkspaceRootPath = `/${DefaultWorkspaceRootComponent}`;

View File

@ -380,7 +380,7 @@ export function getRootUri(csdOrSp: CaseSensitivityDetector | ServiceProvider):
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).
return fs.getOriginalUri(uri).toString();
}

View File

@ -28,7 +28,7 @@ import { convertRangeToTextRange, convertTextRangeToRange } from './positionUtil
import { TextRange } from './textRange';
import { TextRangeCollection } from './textRangeCollection';
import { Uri } from './uri/uri';
import { encodeUri } from './uri/uriUtils';
import { convertUriToLspUriString } from './uri/uriUtils';
export function convertToTextEdits(editActions: TextEditAction[]): TextEdit[] {
return editActions.map((editAction) => ({
@ -68,7 +68,7 @@ export function convertToWorkspaceEdit(
export function appendToWorkspaceEdit(fs: ReadOnlyFileSystem, edits: FileEditAction[], workspaceEdit: WorkspaceEdit) {
edits.forEach((edit) => {
const uri = encodeUri(fs, edit.fileUri);
const uri = convertUriToLspUriString(fs, edit.fileUri);
workspaceEdit.changes![uri] = workspaceEdit.changes![uri] || [];
workspaceEdit.changes![uri].push({ range: edit.range, newText: edit.replacementText });
});
@ -185,7 +185,7 @@ export function generateWorkspaceEdit(
continue;
}
edits.changes![encodeUri(fs, uri)] = [
edits.changes![convertUriToLspUriString(fs, uri)] = [
{
range: convertTextRangeToRange(parseResults.parserOutput.parseTree, parseResults.tokenizerOutput.lines),
newText: final.getFileContent() ?? '',
@ -224,7 +224,11 @@ function _convertToWorkspaceEditWithDocumentChanges(
switch (operation.kind) {
case 'create':
workspaceEdit.documentChanges!.push(
CreateFile.create(encodeUri(fs, operation.fileUri), /* options */ undefined, defaultAnnotationId)
CreateFile.create(
convertUriToLspUriString(fs, operation.fileUri),
/* options */ undefined,
defaultAnnotationId
)
);
break;
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.
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) {
workspaceEdit.documentChanges!.push(
TextDocumentEdit.create(
@ -259,8 +263,8 @@ function _convertToWorkspaceEditWithDocumentChanges(
case 'rename':
workspaceEdit.documentChanges!.push(
RenameFile.create(
encodeUri(fs, operation.oldFileUri),
encodeUri(fs, operation.newFileUri),
convertUriToLspUriString(fs, operation.oldFileUri),
convertUriToLspUriString(fs, operation.newFileUri),
/* options */ undefined,
defaultAnnotationId
)
@ -268,7 +272,11 @@ function _convertToWorkspaceEditWithDocumentChanges(
break;
case 'delete':
workspaceEdit.documentChanges!.push(
DeleteFile.create(encodeUri(fs, operation.fileUri), /* options */ undefined, defaultAnnotationId)
DeleteFile.create(
convertUriToLspUriString(fs, operation.fileUri),
/* options */ undefined,
defaultAnnotationId
)
);
break;
default:

View File

@ -78,7 +78,7 @@ import { AnalyzerService, LibraryReanalysisTimeProvider, getNextServiceId } from
import { IPythonMode } from './analyzer/sourceFile';
import type { BackgroundAnalysisBase } from './backgroundAnalysisBase';
import { CommandResult } from './commands/commandResult';
import { CancelAfter, CancellationProvider } from './common/cancellationUtils';
import { CancelAfter } from './common/cancellationUtils';
import { CaseSensitivityDetector } from './common/caseSensitivityDetector';
import { getNestedProperty } from './common/collectionUtils';
import { DiagnosticSeverityOverrides, getDiagnosticSeverityOverrides } from './common/commandLineOptions';
@ -88,16 +88,22 @@ import { Diagnostic as AnalyzerDiagnostic, DiagnosticCategory, TaskListPriority
import { DiagnosticRule } from './common/diagnosticRules';
import { FileDiagnostics } from './common/diagnosticSink';
import { FileSystem, ReadOnlyFileSystem } from './common/fileSystem';
import { FileWatcherEventType, FileWatcherHandler } from './common/fileWatcher';
import { FileWatcherEventType } from './common/fileWatcher';
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 { ProgressReportTracker, ProgressReporter } from './common/progressReporter';
import { ServiceKeys } from './common/serviceKeys';
import { ServiceProvider } from './common/serviceProvider';
import { DocumentRange, Position, Range } from './common/textRange';
import { Uri } from './common/uri/uri';
import { encodeUri } from './common/uri/uriUtils';
import { convertUriToLspUriString } from './common/uri/uriUtils';
import { AnalyzerServiceExecutor } from './languageService/analyzerServiceExecutor';
import { CallHierarchyProvider } from './languageService/callHierarchyProvider';
import { CompletionItemData, CompletionProvider } from './languageService/completionProvider';
@ -117,49 +123,6 @@ import { InitStatus, WellKnownWorkspaceKinds, Workspace, WorkspaceFactory } from
import { DynamicFeature, DynamicFeatures } from './languageService/dynamicFeature';
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);
/*
@ -799,7 +762,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
) {
this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
@ -812,7 +775,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
return locations
.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(
@ -841,7 +804,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
this._pendingFindAllRefsCancellationSource = source;
try {
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
@ -868,7 +831,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
): Promise<DocumentSymbol[] | SymbolInformation[] | null | undefined> {
this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
return undefined;
@ -901,7 +864,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
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);
return workspace.service.run((program) => {
@ -913,7 +876,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: DocumentHighlightParams,
token: CancellationToken
): Promise<DocumentHighlight[] | null | undefined> {
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
return workspace.service.run((program) => {
@ -925,7 +888,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: SignatureHelpParams,
token: CancellationToken
): Promise<SignatureHelp | undefined | null> {
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
@ -967,7 +930,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
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);
if (workspace.disableLanguageServices) {
return null;
@ -1001,7 +964,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected async onCompletionResolve(params: CompletionItem, token: CancellationToken): Promise<CompletionItem> {
const completionItemData = fromLSPAny<CompletionItemData>(params.data);
if (completionItemData && completionItemData.uri) {
const uri = this.decodeUri(completionItemData.uri);
const uri = Uri.parse(completionItemData.uri, this.caseSensitiveDetector);
const workspace = await this.getWorkspaceForFile(uri);
workspace.service.run((program) => {
return new CompletionProvider(
@ -1024,7 +987,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: PrepareRenameParams,
token: CancellationToken
): 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 workspace = await this.getWorkspaceForFile(uri);
@ -1044,7 +1007,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: RenameParams,
token: CancellationToken
): Promise<WorkspaceEdit | null | undefined> {
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const isUntitled = uri.isUntitled();
const workspace = await this.getWorkspaceForFile(uri);
@ -1065,7 +1028,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: CallHierarchyPrepareParams,
token: CancellationToken
): Promise<CallHierarchyItem[] | null> {
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
@ -1078,7 +1041,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
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);
if (workspace.disableLanguageServices) {
@ -1094,7 +1057,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
params: CallHierarchyOutgoingCallsParams,
token: CancellationToken
): Promise<CallHierarchyOutgoingCall[] | null> {
const uri = this.decodeUri(params.item.uri);
const uri = this.convertLspUriStringToUri(params.item.uri);
const workspace = await this.getWorkspaceForFile(uri);
if (workspace.disableLanguageServices) {
@ -1107,7 +1070,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
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);
if (doc) {
@ -1134,7 +1097,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected async onDidChangeTextDocument(params: DidChangeTextDocumentParams, ipythonMode = IPythonMode.None) {
this.recordUserInteractionTime();
const uri = this.decodeUri(params.textDocument.uri);
const uri = this.convertLspUriStringToUri(params.textDocument.uri);
const doc = this.openFileMap.get(uri.key);
if (!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) {
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.
const workspaces = await this.getContainingWorkspacesForFile(uri);
@ -1166,7 +1129,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) {
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';
this.serverOptions.fileWatcherHandler.onFileChange(eventType, filePath);
});
@ -1241,7 +1204,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
protected convertDiagnostics(fs: FileSystem, fileDiagnostics: FileDiagnostics): PublishDiagnosticsParams[] {
return [
{
uri: encodeUri(fs, fileDiagnostics.fileUri),
uri: convertUriToLspUriString(fs, fileDiagnostics.fileUri),
version: fileDiagnostics.version,
diagnostics: this._convertDiagnostics(fs, fileDiagnostics.diagnostics),
},
@ -1272,21 +1235,31 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
}
// Update progress.
if (results.filesRequiringAnalysis > 0) {
const progressMessage = this.getProgressMessage(results);
if (progressMessage) {
this._progressReporter.begin();
const progressMessage =
results.filesRequiringAnalysis === 1
? Localizer.CodeAction.filesToAnalyzeOne()
: Localizer.CodeAction.filesToAnalyzeCount().format({
count: results.filesRequiringAnalysis,
});
this._progressReporter.report(progressMessage);
} else {
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) {
// Update settings on this workspace (but only if initialize has happened)
if (this._initialized) {
@ -1300,7 +1273,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
const otherWorkspaces = this.workspaceFactory.items().filter((w) => w !== workspace);
for (const uri of documentsWithDiagnosticsList) {
const fileUri = this.decodeUri(uri);
const fileUri = this.convertLspUriStringToUri(uri);
if (workspace.service.isTracked(fileUri)) {
// 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);
}
@ -1479,7 +1452,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
.filter((info) => this.canNavigateToFile(info.uri, fs))
.map((info) =>
DiagnosticRelatedInformation.create(
Location.create(encodeUri(fs, info.uri), info.range),
Location.create(convertUriToLspUriString(fs, info.uri), info.range),
info.message
)
);

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ import { Location } from 'vscode-languageserver-types';
import { ReadOnlyFileSystem } from '../common/fileSystem';
import { DocumentRange } from '../common/textRange';
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 {
return !fs.isInZip(path);
@ -28,5 +28,5 @@ export function convertDocumentRangeToLocation(fs: ReadOnlyFileSystem, range: Do
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 * as StringUtils from '../common/stringUtils';
import { Uri } from '../common/uri/uri';
import { encodeUri } from '../common/uri/uriUtils';
import { convertUriToLspUriString } from '../common/uri/uriUtils';
import { Workspace } from '../workspaceFactory';
import { IndexSymbolData, SymbolIndexer } from './symbolIndexer';
@ -100,7 +100,7 @@ export class WorkspaceSymbolProvider {
if (StringUtils.isPatternInSymbol(this._query, symbolData.name)) {
const location: Location = {
uri: encodeUri(program.fileSystem, fileUri),
uri: convertUriToLspUriString(program.fileSystem, fileUri),
range: symbolData.selectionRange!,
};

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Rozbalení se v tomto kontextu nepovoluje",
"unpackOperatorNotAllowed": "Operace rozbalení není v tomto kontextu povolená",
"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",
"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ý",

View File

@ -252,7 +252,7 @@
"incompatibleMethodOverride": "Die Methode \"{name}\" überschreibt die Klasse \"{className}\" auf inkompatible Weise.",
"inconsistentIndent": "Der Betrag für Nichteinzug stimmt nicht mit dem vorherigen Einzug überein.",
"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.",
"initSubclassCallFailed": "Falsche Schlüsselwortargumente für __init_subclass__ Methode.",
"initSubclassClsParam": "__init_subclass__ Außerkraftsetzung sollte einen \"cls\"-Parameter annehmen.",
@ -595,7 +595,7 @@
"unpackNotAllowed": "\"Unpack\" 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.",
"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.",
"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.",

View File

@ -252,7 +252,7 @@
"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",
"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",
"initSubclassCallFailed": "Argumentos de palabra clave incorrectos para el método __init_subclass__",
"initSubclassClsParam": "__init_subclass__ debe tomar un parámetro \"cls\"",
@ -595,7 +595,7 @@
"unpackNotAllowed": "El desempaquetado no está permitido 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",
"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",
"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",

View File

@ -252,7 +252,7 @@
"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",
"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",
"initSubclassCallFailed": "Arguments de mot clé incorrects pour la méthode __init_subclass__",
"initSubclassClsParam": "__init_subclass__ remplacement doit prendre un paramètre « cls »",
@ -595,7 +595,7 @@
"unpackNotAllowed": "Le décompression nest pas autorisé 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",
"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",
"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é",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "La 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",
"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",
"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",

View File

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

View File

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

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Rozpakowywanie jest niedozwolone 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",
"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",
"unpackedDictArgumentNotMapping": "Wyrażenie argumentu po znakach ** musi być mapowaniem z typem klucza „str”",
"unpackedDictSubscriptIllegal": "Operator rozpakowywania słownika w indeksie dolnym jest niedozwolony",

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Descompactar não é permitido 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",
"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",
"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",

View File

@ -252,7 +252,7 @@
"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Ấğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]",
"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 þë ÑøñëẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
"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Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
@ -595,7 +595,7 @@
"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Ấğ倪İЂҰक्र्तिृまẤğ倪İЂนั้ढूँ]",
"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Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]",
"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ëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",

View File

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

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "Bu bağlamda paketi açma işlemine izin verilmiyor",
"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",
"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",
"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",

View File

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

View File

@ -595,7 +595,7 @@
"unpackNotAllowed": "此內容中不允許解壓縮",
"unpackOperatorNotAllowed": "此內容中不允許解壓縮作業",
"unpackTuplesIllegal": "Python 3.8 之前的 Tuple 中不允許解壓縮作業",
"unpackedArgInTypeArgument": "解壓縮的引數不能用於類型引數清單",
"unpackedArgInTypeArgument": "無法在此內容中使用未封裝的引數",
"unpackedArgWithVariadicParam": "未封裝的引數無法用於 TypeVarTuple 參數",
"unpackedDictArgumentNotMapping": "** 後的引數運算式必須是具有 \"str\" 金鑰類型的對應",
"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 {
service.writeTypeStub(cancellationNone);
service.dispose();

View File

@ -359,3 +359,23 @@ test('import symbol tooltip - useLibraryCodeForTypes true', async () => {
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.',
});
});