From 0618acc5356865ba95f8b94d08bfd982662526d3 Mon Sep 17 00:00:00 2001 From: Bill Schnurr Date: Wed, 22 May 2024 15:34:30 -0700 Subject: [PATCH] pylance-22-5-2024 -> pyright (#7980) * pullpylance-22-5-2024 Co-authored-by: Bill Schnurr Co-authored-by: HeeJae Chang Co-authored-by: Erik De Bonte Co-authored-by: Rich Chiodo Co-authored-by: Stella Huang Co-authored-by: Kacie Kang --- .../pyright-internal/src/analyzer/analysis.ts | 13 +- .../src/analyzer/backgroundAnalysisProgram.ts | 2 +- .../src/analyzer/importResolver.ts | 9 +- .../src/analyzer/parentDirectoryCache.ts | 3 +- .../pyright-internal/src/analyzer/program.ts | 22 ++- .../pyright-internal/src/analyzer/service.ts | 4 +- .../src/analyzer/sourceFile.ts | 43 ++++-- .../src/analyzer/typeDocStringUtils.ts | 13 +- .../src/backgroundAnalysisBase.ts | 20 ++- .../src/backgroundThreadBase.ts | 14 +- .../src/commands/createTypeStub.ts | 87 ++++++------ .../pyright-internal/src/common/console.ts | 4 + .../src/common/languageServerInterface.ts | 49 +++++++ .../pyright-internal/src/common/uri/uri.ts | 2 + .../src/common/uri/uriUtils.ts | 2 +- .../src/common/workspaceEditUtils.ts | 24 ++-- .../src/languageServerBase.ts | 127 +++++++----------- .../analyzerServiceExecutor.ts | 4 +- .../languageService/callHierarchyProvider.ts | 12 +- .../languageService/documentSymbolProvider.ts | 4 +- .../src/languageService/navigationUtils.ts | 4 +- .../workspaceSymbolProvider.ts | 4 +- .../src/localization/package.nls.cs.json | 2 +- .../src/localization/package.nls.de.json | 4 +- .../src/localization/package.nls.es.json | 4 +- .../src/localization/package.nls.fr.json | 4 +- .../src/localization/package.nls.it.json | 2 +- .../src/localization/package.nls.ja.json | 4 +- .../src/localization/package.nls.ko.json | 2 +- .../src/localization/package.nls.pl.json | 2 +- .../src/localization/package.nls.pt-br.json | 2 +- .../localization/package.nls.qps-ploc.json | 4 +- .../src/localization/package.nls.ru.json | 4 +- .../src/localization/package.nls.tr.json | 2 +- .../src/localization/package.nls.zh-cn.json | 4 +- .../src/localization/package.nls.zh-tw.json | 2 +- packages/pyright-internal/src/pyright.ts | 2 +- .../src/tests/hoverProvider.test.ts | 20 +++ 38 files changed, 333 insertions(+), 197 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/analysis.ts b/packages/pyright-internal/src/analyzer/analysis.ts index 5fa84c82f..21be06fe5 100644 --- a/packages/pyright-internal/src/analyzer/analysis.ts +++ b/packages/pyright-internal/src/analyzer/analysis.ts @@ -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, diff --git a/packages/pyright-internal/src/analyzer/backgroundAnalysisProgram.ts b/packages/pyright-internal/src/analyzer/backgroundAnalysisProgram.ts index 159c80cb0..3d1f8f2f0 100644 --- a/packages/pyright-internal/src/analyzer/backgroundAnalysisProgram.ts +++ b/packages/pyright-internal/src/analyzer/backgroundAnalysisProgram.ts @@ -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, diff --git a/packages/pyright-internal/src/analyzer/importResolver.ts b/packages/pyright-internal/src/analyzer/importResolver.ts index 146dbf119..5826bec1a 100644 --- a/packages/pyright-internal/src/analyzer/importResolver.ts +++ b/packages/pyright-internal/src/analyzer/importResolver.ts @@ -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; } diff --git a/packages/pyright-internal/src/analyzer/parentDirectoryCache.ts b/packages/pyright-internal/src/analyzer/parentDirectoryCache.ts index 04e9fd42e..7fe3e5361 100644 --- a/packages/pyright-internal/src/analyzer/parentDirectoryCache.ts +++ b/packages/pyright-internal/src/analyzer/parentDirectoryCache.ts @@ -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); diff --git a/packages/pyright-internal/src/analyzer/program.ts b/packages/pyright-internal/src/analyzer/program.ts index 2ed39faaa..03037efdf 100644 --- a/packages/pyright-internal/src/analyzer/program.ts +++ b/packages/pyright-internal/src/analyzer/program.ts @@ -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); diff --git a/packages/pyright-internal/src/analyzer/service.ts b/packages/pyright-internal/src/analyzer/service.ts index af8d78998..d10e8dbcc 100644 --- a/packages/pyright-internal/src/analyzer/service.ts +++ b/packages/pyright-internal/src/analyzer/service.ts @@ -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, diff --git a/packages/pyright-internal/src/analyzer/sourceFile.ts b/packages/pyright-internal/src/analyzer/sourceFile.ts index 1e9c52284..833743aea 100644 --- a/packages/pyright-internal/src/analyzer/sourceFile.ts +++ b/packages/pyright-internal/src/analyzer/sourceFile.ts @@ -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 | 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 diff --git a/packages/pyright-internal/src/analyzer/typeDocStringUtils.ts b/packages/pyright-internal/src/analyzer/typeDocStringUtils.ts index 972f9b3db..e6b1402a5 100644 --- a/packages/pyright-internal/src/analyzer/typeDocStringUtils.ts +++ b/packages/pyright-internal/src/analyzer/typeDocStringUtils.ts @@ -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); +} diff --git a/packages/pyright-internal/src/backgroundAnalysisBase.ts b/packages/pyright-internal/src/backgroundAnalysisBase.ts index a4f6b4ccd..a25f0932c 100644 --- a/packages/pyright-internal/src/backgroundAnalysisBase.ts +++ b/packages/pyright-internal/src/backgroundAnalysisBase.ts @@ -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, diff --git a/packages/pyright-internal/src/backgroundThreadBase.ts b/packages/pyright-internal/src/backgroundThreadBase.ts index b4ae22d25..8775b2615 100644 --- a/packages/pyright-internal/src/backgroundThreadBase.ts +++ b/packages/pyright-internal/src/backgroundThreadBase.ts @@ -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 }) }); } diff --git a/packages/pyright-internal/src/commands/createTypeStub.ts b/packages/pyright-internal/src/commands/createTypeStub.ts index 6729bae42..91f93435d 100644 --- a/packages/pyright-internal/src/commands/createTypeStub.ts +++ b/packages/pyright-internal/src/commands/createTypeStub.ts @@ -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 { - 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 { + 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); } } } diff --git a/packages/pyright-internal/src/common/console.ts b/packages/pyright-internal/src/common/console.ts index cddcf6eb6..c616897e5 100644 --- a/packages/pyright-internal/src/common/console.ts +++ b/packages/pyright-internal/src/common/console.ts @@ -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([ diff --git a/packages/pyright-internal/src/common/languageServerInterface.ts b/packages/pyright-internal/src/common/languageServerInterface.ts index 1dc131a77..fbcac4598 100644 --- a/packages/pyright-internal/src/common/languageServerInterface.ts +++ b/packages/pyright-internal/src/common/languageServerInterface.ts @@ -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; diff --git a/packages/pyright-internal/src/common/uri/uri.ts b/packages/pyright-internal/src/common/uri/uri.ts index 56c313984..11c5a2317 100644 --- a/packages/pyright-internal/src/common/uri/uri.ts +++ b/packages/pyright-internal/src/common/uri/uri.ts @@ -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 = ''; export const DefaultWorkspaceRootPath = `/${DefaultWorkspaceRootComponent}`; diff --git a/packages/pyright-internal/src/common/uri/uriUtils.ts b/packages/pyright-internal/src/common/uri/uriUtils.ts index 02483efb0..a366335c7 100644 --- a/packages/pyright-internal/src/common/uri/uriUtils.ts +++ b/packages/pyright-internal/src/common/uri/uriUtils.ts @@ -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(); } diff --git a/packages/pyright-internal/src/common/workspaceEditUtils.ts b/packages/pyright-internal/src/common/workspaceEditUtils.ts index aeefbc715..3420091a9 100644 --- a/packages/pyright-internal/src/common/workspaceEditUtils.ts +++ b/packages/pyright-internal/src/common/workspaceEditUtils.ts @@ -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: diff --git a/packages/pyright-internal/src/languageServerBase.ts b/packages/pyright-internal/src/languageServerBase.ts index 6e2413fd5..d52b20385 100644 --- a/packages/pyright-internal/src/languageServerBase.ts +++ b/packages/pyright-internal/src/languageServerBase.ts @@ -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 { 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 { - 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 { - 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 { - 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 { const completionItemData = fromLSPAny(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 { - 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 { - 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 { - 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 { - 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 ) ); diff --git a/packages/pyright-internal/src/languageService/analyzerServiceExecutor.ts b/packages/pyright-internal/src/languageService/analyzerServiceExecutor.ts index d334f6459..d185c8fac 100644 --- a/packages/pyright-internal/src/languageService/analyzerServiceExecutor.ts +++ b/packages/pyright-internal/src/languageService/analyzerServiceExecutor.ts @@ -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 { diff --git a/packages/pyright-internal/src/languageService/callHierarchyProvider.ts b/packages/pyright-internal/src/languageService/callHierarchyProvider.ts index a21f82386..920c2662e 100644 --- a/packages/pyright-internal/src/languageService/callHierarchyProvider.ts +++ b/packages/pyright-internal/src/languageService/callHierarchyProvider.ts @@ -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, }; diff --git a/packages/pyright-internal/src/languageService/documentSymbolProvider.ts b/packages/pyright-internal/src/languageService/documentSymbolProvider.ts index ff6b6a36e..203252e4a 100644 --- a/packages/pyright-internal/src/languageService/documentSymbolProvider.ts +++ b/packages/pyright-internal/src/languageService/documentSymbolProvider.ts @@ -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) { diff --git a/packages/pyright-internal/src/languageService/navigationUtils.ts b/packages/pyright-internal/src/languageService/navigationUtils.ts index 63e294cdf..3081721a2 100644 --- a/packages/pyright-internal/src/languageService/navigationUtils.ts +++ b/packages/pyright-internal/src/languageService/navigationUtils.ts @@ -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); } diff --git a/packages/pyright-internal/src/languageService/workspaceSymbolProvider.ts b/packages/pyright-internal/src/languageService/workspaceSymbolProvider.ts index 9f421170f..609e9a6a2 100644 --- a/packages/pyright-internal/src/languageService/workspaceSymbolProvider.ts +++ b/packages/pyright-internal/src/languageService/workspaceSymbolProvider.ts @@ -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!, }; diff --git a/packages/pyright-internal/src/localization/package.nls.cs.json b/packages/pyright-internal/src/localization/package.nls.cs.json index c0d7dfbeb..404205ae9 100644 --- a/packages/pyright-internal/src/localization/package.nls.cs.json +++ b/packages/pyright-internal/src/localization/package.nls.cs.json @@ -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ý", diff --git a/packages/pyright-internal/src/localization/package.nls.de.json b/packages/pyright-internal/src/localization/package.nls.de.json index b2cedbbb9..4daff9339 100644 --- a/packages/pyright-internal/src/localization/package.nls.de.json +++ b/packages/pyright-internal/src/localization/package.nls.de.json @@ -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.", diff --git a/packages/pyright-internal/src/localization/package.nls.es.json b/packages/pyright-internal/src/localization/package.nls.es.json index a40ba4ad5..84861345a 100644 --- a/packages/pyright-internal/src/localization/package.nls.es.json +++ b/packages/pyright-internal/src/localization/package.nls.es.json @@ -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", diff --git a/packages/pyright-internal/src/localization/package.nls.fr.json b/packages/pyright-internal/src/localization/package.nls.fr.json index f44f63fa9..ee6cb1f8f 100644 --- a/packages/pyright-internal/src/localization/package.nls.fr.json +++ b/packages/pyright-internal/src/localization/package.nls.fr.json @@ -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": "L’annotation 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": "L’annotation 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 n’est pas autorisé dans ce contexte", "unpackOperatorNotAllowed": "L’opération de décompression n’est 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 d’arguments 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": "L’expression d’argument après ** doit être un mappage avec un type de clé « str »", "unpackedDictSubscriptIllegal": "L’opérateur de décompression de dictionnaire dans l’indice n’est pas autorisé", diff --git a/packages/pyright-internal/src/localization/package.nls.it.json b/packages/pyright-internal/src/localization/package.nls.it.json index c5e7db62b..89b889dbf 100644 --- a/packages/pyright-internal/src/localization/package.nls.it.json +++ b/packages/pyright-internal/src/localization/package.nls.it.json @@ -595,7 +595,7 @@ "unpackNotAllowed": "La decompressione non è consentita in questo contesto", "unpackOperatorNotAllowed": "L’operazione 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", diff --git a/packages/pyright-internal/src/localization/package.nls.ja.json b/packages/pyright-internal/src/localization/package.nls.ja.json index d96fe3bf1..07c5436e8 100644 --- a/packages/pyright-internal/src/localization/package.nls.ja.json +++ b/packages/pyright-internal/src/localization/package.nls.ja.json @@ -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": "下付き文字の辞書アンパック演算子は使用できません", diff --git a/packages/pyright-internal/src/localization/package.nls.ko.json b/packages/pyright-internal/src/localization/package.nls.ko.json index fc215a422..4b3454cec 100644 --- a/packages/pyright-internal/src/localization/package.nls.ko.json +++ b/packages/pyright-internal/src/localization/package.nls.ko.json @@ -595,7 +595,7 @@ "unpackNotAllowed": "이 컨텍스트에서는 압축 풀기가 허용되지 않습니다.", "unpackOperatorNotAllowed": "이 컨텍스트에서는 압축 풀기 작업이 허용되지 않습니다.", "unpackTuplesIllegal": "Python 3.8 이전의 튜플에서는 압축 풀기 작업이 허용되지 않습니다.", - "unpackedArgInTypeArgument": "압축되지 않은 인수는 형식 인수 목록에 사용할 수 없습니다.", + "unpackedArgInTypeArgument": "압축을 푼 인수는 이 컨텍스트에서 사용할 수 없음", "unpackedArgWithVariadicParam": "압축을 푼 인수는 TypeVarTuple 매개 변수에 사용할 수 없습니다.", "unpackedDictArgumentNotMapping": "** 뒤의 인수 식은 \"str\" 키 형식의 매핑이어야 합니다.", "unpackedDictSubscriptIllegal": "아래 첨자에서 사전 압축 풀기 연산자는 사용할 수 없습니다.", diff --git a/packages/pyright-internal/src/localization/package.nls.pl.json b/packages/pyright-internal/src/localization/package.nls.pl.json index 30c5153a0..1cced3564 100644 --- a/packages/pyright-internal/src/localization/package.nls.pl.json +++ b/packages/pyright-internal/src/localization/package.nls.pl.json @@ -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", diff --git a/packages/pyright-internal/src/localization/package.nls.pt-br.json b/packages/pyright-internal/src/localization/package.nls.pt-br.json index f06aa6e3f..be29ae6b7 100644 --- a/packages/pyright-internal/src/localization/package.nls.pt-br.json +++ b/packages/pyright-internal/src/localization/package.nls.pt-br.json @@ -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", diff --git a/packages/pyright-internal/src/localization/package.nls.qps-ploc.json b/packages/pyright-internal/src/localization/package.nls.qps-ploc.json index 47314588f..21f262886 100644 --- a/packages/pyright-internal/src/localization/package.nls.qps-ploc.json +++ b/packages/pyright-internal/src/localization/package.nls.qps-ploc.json @@ -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ëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", diff --git a/packages/pyright-internal/src/localization/package.nls.ru.json b/packages/pyright-internal/src/localization/package.nls.ru.json index a8802a88e..beb2c5509 100644 --- a/packages/pyright-internal/src/localization/package.nls.ru.json +++ b/packages/pyright-internal/src/localization/package.nls.ru.json @@ -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": "Оператор распаковки словаря не допускается внутри операции взятия подстроки", diff --git a/packages/pyright-internal/src/localization/package.nls.tr.json b/packages/pyright-internal/src/localization/package.nls.tr.json index aea00f020..5f1f82ae8 100644 --- a/packages/pyright-internal/src/localization/package.nls.tr.json +++ b/packages/pyright-internal/src/localization/package.nls.tr.json @@ -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", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-cn.json b/packages/pyright-internal/src/localization/package.nls.zh-cn.json index 1468e91fd..0c73b51f9 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-cn.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-cn.json @@ -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": "不允许在下标中使用字典解包运算符", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-tw.json b/packages/pyright-internal/src/localization/package.nls.zh-tw.json index e4fffbb56..5707c5688 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-tw.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-tw.json @@ -595,7 +595,7 @@ "unpackNotAllowed": "此內容中不允許解壓縮", "unpackOperatorNotAllowed": "此內容中不允許解壓縮作業", "unpackTuplesIllegal": "Python 3.8 之前的 Tuple 中不允許解壓縮作業", - "unpackedArgInTypeArgument": "解壓縮的引數不能用於類型引數清單", + "unpackedArgInTypeArgument": "無法在此內容中使用未封裝的引數", "unpackedArgWithVariadicParam": "未封裝的引數無法用於 TypeVarTuple 參數", "unpackedDictArgumentNotMapping": "** 後的引數運算式必須是具有 \"str\" 金鑰類型的對應", "unpackedDictSubscriptIllegal": "字典解壓縮運算子在下標中不被允許", diff --git a/packages/pyright-internal/src/pyright.ts b/packages/pyright-internal/src/pyright.ts index 182dea1b6..174d8457f 100644 --- a/packages/pyright-internal/src/pyright.ts +++ b/packages/pyright-internal/src/pyright.ts @@ -438,7 +438,7 @@ async function processArgs(): Promise { } } - if (args.createstub && results.filesRequiringAnalysis === 0) { + if (args.createstub && results.requiringAnalysisCount.files === 0) { try { service.writeTypeStub(cancellationNone); service.dispose(); diff --git a/packages/pyright-internal/src/tests/hoverProvider.test.ts b/packages/pyright-internal/src/tests/hoverProvider.test.ts index 1a8153404..a2527dac2 100644 --- a/packages/pyright-internal/src/tests/hoverProvider.test.ts +++ b/packages/pyright-internal/src/tests/hoverProvider.test.ts @@ -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.', + }); +});