mirror of
https://github.com/microsoft/pyright.git
synced 2024-07-14 11:00:25 +03:00
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:
parent
766a012627
commit
0618acc535
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 }) });
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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([
|
||||
|
@ -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;
|
||||
|
@ -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}`;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
)
|
||||
);
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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!,
|
||||
};
|
||||
|
||||
|
@ -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ý",
|
||||
|
@ -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.",
|
||||
|
@ -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",
|
||||
|
@ -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é",
|
||||
|
@ -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",
|
||||
|
@ -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": "下付き文字の辞書アンパック演算子は使用できません",
|
||||
|
@ -595,7 +595,7 @@
|
||||
"unpackNotAllowed": "이 컨텍스트에서는 압축 풀기가 허용되지 않습니다.",
|
||||
"unpackOperatorNotAllowed": "이 컨텍스트에서는 압축 풀기 작업이 허용되지 않습니다.",
|
||||
"unpackTuplesIllegal": "Python 3.8 이전의 튜플에서는 압축 풀기 작업이 허용되지 않습니다.",
|
||||
"unpackedArgInTypeArgument": "압축되지 않은 인수는 형식 인수 목록에 사용할 수 없습니다.",
|
||||
"unpackedArgInTypeArgument": "압축을 푼 인수는 이 컨텍스트에서 사용할 수 없음",
|
||||
"unpackedArgWithVariadicParam": "압축을 푼 인수는 TypeVarTuple 매개 변수에 사용할 수 없습니다.",
|
||||
"unpackedDictArgumentNotMapping": "** 뒤의 인수 식은 \"str\" 키 형식의 매핑이어야 합니다.",
|
||||
"unpackedDictSubscriptIllegal": "아래 첨자에서 사전 압축 풀기 연산자는 사용할 수 없습니다.",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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ëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
|
||||
|
@ -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": "Оператор распаковки словаря не допускается внутри операции взятия подстроки",
|
||||
|
@ -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",
|
||||
|
@ -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": "不允许在下标中使用字典解包运算符",
|
||||
|
@ -595,7 +595,7 @@
|
||||
"unpackNotAllowed": "此內容中不允許解壓縮",
|
||||
"unpackOperatorNotAllowed": "此內容中不允許解壓縮作業",
|
||||
"unpackTuplesIllegal": "Python 3.8 之前的 Tuple 中不允許解壓縮作業",
|
||||
"unpackedArgInTypeArgument": "解壓縮的引數不能用於類型引數清單",
|
||||
"unpackedArgInTypeArgument": "無法在此內容中使用未封裝的引數",
|
||||
"unpackedArgWithVariadicParam": "未封裝的引數無法用於 TypeVarTuple 參數",
|
||||
"unpackedDictArgumentNotMapping": "** 後的引數運算式必須是具有 \"str\" 金鑰類型的對應",
|
||||
"unpackedDictSubscriptIllegal": "字典解壓縮運算子在下標中不被允許",
|
||||
|
@ -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();
|
||||
|
@ -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.',
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user