Added new eslint rule to enforce that protected class variables and methods should never start with an underscore. We were somewhat inconsistent here. Fixed up the code to honor this rule.

This commit is contained in:
Eric Traut 2023-04-26 16:09:58 -07:00
parent c06831d23c
commit 05a3cdd69a
12 changed files with 223 additions and 230 deletions

View File

@ -77,7 +77,7 @@
"accessor" "accessor"
], ],
"modifiers": ["protected"], "modifiers": ["protected"],
"leadingUnderscore": "allow", "leadingUnderscore": "forbid",
"format": ["camelCase"], "format": ["camelCase"],
"filter": { "filter": {
"regex": "^(test_| )", "regex": "^(test_| )",

View File

@ -30,7 +30,7 @@ export class BackgroundAnalysisProgram {
private _console: ConsoleInterface, private _console: ConsoleInterface,
private _configOptions: ConfigOptions, private _configOptions: ConfigOptions,
private _importResolver: ImportResolver, private _importResolver: ImportResolver,
protected _backgroundAnalysis?: BackgroundAnalysisBase, private _backgroundAnalysis?: BackgroundAnalysisBase,
private _maxAnalysisTime?: MaxAnalysisTime, private _maxAnalysisTime?: MaxAnalysisTime,
private _disableChecker?: boolean, private _disableChecker?: boolean,
cacheManager?: CacheManager cacheManager?: CacheManager
@ -65,6 +65,10 @@ export class BackgroundAnalysisProgram {
return this._backgroundAnalysis; return this._backgroundAnalysis;
} }
set backgroundAnalysis(value: BackgroundAnalysisBase | undefined) {
this._backgroundAnalysis = value;
}
hasSourceFile(filePath: string): boolean { hasSourceFile(filePath: string): boolean {
return !!this._program.getSourceFile(filePath); return !!this._program.getSourceFile(filePath);
} }
@ -147,7 +151,7 @@ export class BackgroundAnalysisProgram {
startAnalysis(token: CancellationToken): boolean { startAnalysis(token: CancellationToken): boolean {
if (this._backgroundAnalysis) { if (this._backgroundAnalysis) {
this._backgroundAnalysis.startAnalysis(this._getIndices(), token); this._backgroundAnalysis.startAnalysis(this.getIndices(), token);
return false; return false;
} }
@ -183,7 +187,7 @@ export class BackgroundAnalysisProgram {
} }
getIndexing(filePath: string) { getIndexing(filePath: string) {
return this._getIndices()?.getIndex(this._configOptions.findExecEnvironment(filePath).root); return this.getIndices()?.getIndex(this._configOptions.findExecEnvironment(filePath).root);
} }
async getDiagnosticsForRange(filePath: string, range: Range, token: CancellationToken): Promise<Diagnostic[]> { async getDiagnosticsForRange(filePath: string, range: Range, token: CancellationToken): Promise<Diagnostic[]> {
@ -244,7 +248,7 @@ export class BackgroundAnalysisProgram {
this._backgroundAnalysis?.shutdown(); this._backgroundAnalysis?.shutdown();
} }
protected _getIndices(): Indices | undefined { protected getIndices(): Indices | undefined {
return undefined; return undefined;
} }

View File

@ -121,7 +121,7 @@ export class ImportResolver {
private _stdlibModules: Set<string> | undefined; private _stdlibModules: Set<string> | undefined;
protected cachedParentImportResults: ParentDirectoryCache; protected cachedParentImportResults: ParentDirectoryCache;
constructor(readonly fileSystem: FileSystem, protected _configOptions: ConfigOptions, readonly host: Host) { constructor(readonly fileSystem: FileSystem, private _configOptions: ConfigOptions, readonly host: Host) {
this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([])); this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([]));
} }
@ -145,9 +145,9 @@ export class ImportResolver {
execEnv: ExecutionEnvironment, execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor moduleDescriptor: ImportedModuleDescriptor
): ImportResult { ): ImportResult {
// Wrap internal call to _resolveImport() to prevent calling any // Wrap internal call to resolveImportInternal() to prevent calling any
// child class version of resolveImport(). // child class version of resolveImport().
return this._resolveImport(sourceFilePath, execEnv, moduleDescriptor); return this.resolveImportInternal(sourceFilePath, execEnv, moduleDescriptor);
} }
getCompletionSuggestions( getCompletionSuggestions(
@ -445,7 +445,7 @@ export class ImportResolver {
// Resolves the import and returns the path if it exists, otherwise // Resolves the import and returns the path if it exists, otherwise
// returns undefined. // returns undefined.
protected _resolveImport( protected resolveImportInternal(
sourceFilePath: string, sourceFilePath: string,
execEnv: ExecutionEnvironment, execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor moduleDescriptor: ImportedModuleDescriptor
@ -2297,7 +2297,7 @@ export class ImportResolver {
.isImportFound; .isImportFound;
} }
return this._resolveImport(sourceFilePath, execEnv, moduleDescriptor).isImportFound; return this.resolveImportInternal(sourceFilePath, execEnv, moduleDescriptor).isImportFound;
} }
private _isUniqueValidSuggestion(suggestionToAdd: string, suggestions: Map<string, string>) { private _isUniqueValidSuggestion(suggestionToAdd: string, suggestions: Map<string, string>) {

View File

@ -287,8 +287,8 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
private _configOptions: ConfigOptions; private _configOptions: ConfigOptions;
private _program: Program; private _program: Program;
protected _importResolver: ImportResolver; protected importResolver: ImportResolver;
protected _logTracker: LogTracker; protected logTracker: LogTracker;
protected constructor() { protected constructor() {
super(workerData as InitializationData); super(workerData as InitializationData);
@ -298,12 +298,12 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
this.log(LogLevel.Info, `Background analysis(${threadId}) root directory: ${data.rootDirectory}`); this.log(LogLevel.Info, `Background analysis(${threadId}) root directory: ${data.rootDirectory}`);
this._configOptions = new ConfigOptions(data.rootDirectory); this._configOptions = new ConfigOptions(data.rootDirectory);
this._importResolver = this.createImportResolver(this.fs, this._configOptions, this.createHost()); this.importResolver = this.createImportResolver(this.fs, this._configOptions, this.createHost());
const console = this.getConsole(); const console = this.getConsole();
this._logTracker = new LogTracker(console, `BG(${threadId})`); this.logTracker = new LogTracker(console, `BG(${threadId})`);
this._program = new Program(this._importResolver, this._configOptions, console, this._logTracker); this._program = new Program(this.importResolver, this._configOptions, console, this.logTracker);
// Create the extensions bound to the program for this background thread // Create the extensions bound to the program for this background thread
Extensions.createProgramExtensions(this._program, { Extensions.createProgramExtensions(this._program, {
@ -391,22 +391,18 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
} }
case 'setImportResolver': { case 'setImportResolver': {
this._importResolver = this.createImportResolver(this.fs, this._configOptions, this.createHost()); this.importResolver = this.createImportResolver(this.fs, this._configOptions, this.createHost());
this.program.setImportResolver(this._importResolver); this.program.setImportResolver(this.importResolver);
break; break;
} }
case 'setConfigOptions': { case 'setConfigOptions': {
this._configOptions = createConfigOptionsFrom(msg.data); this._configOptions = createConfigOptionsFrom(msg.data);
this._importResolver = this.createImportResolver( this.importResolver = this.createImportResolver(this.fs, this._configOptions, this.importResolver.host);
this.fs,
this._configOptions,
this._importResolver.host
);
this.program.setConfigOptions(this._configOptions); this.program.setConfigOptions(this._configOptions);
this.program.setImportResolver(this._importResolver); this.program.setImportResolver(this.importResolver);
break; break;
} }
@ -425,7 +421,7 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
const { executionRoot } = msg.data; const { executionRoot } = msg.data;
const execEnv = this._configOptions.getExecutionEnvironments().find((e) => e.root === executionRoot); const execEnv = this._configOptions.getExecutionEnvironments().find((e) => e.root === executionRoot);
if (execEnv) { if (execEnv) {
this._importResolver.ensurePartialStubPackages(execEnv); this.importResolver.ensurePartialStubPackages(execEnv);
} }
break; break;
} }
@ -470,7 +466,7 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
case 'invalidateAndForceReanalysis': { case 'invalidateAndForceReanalysis': {
// Make sure the import resolver doesn't have invalid // Make sure the import resolver doesn't have invalid
// cached entries. // cached entries.
this._importResolver.invalidateCache(); this.importResolver.invalidateCache();
// Mark all files with one or more errors dirty. // Mark all files with one or more errors dirty.
this.program.markAllFilesDirty(/* evenIfContentsAreSame */ true, /* indexingNeeded */ msg.data); this.program.markAllFilesDirty(/* evenIfContentsAreSame */ true, /* indexingNeeded */ msg.data);
@ -479,12 +475,8 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
case 'restart': { case 'restart': {
// recycle import resolver // recycle import resolver
this._importResolver = this.createImportResolver( this.importResolver = this.createImportResolver(this.fs, this._configOptions, this.importResolver.host);
this.fs, this.program.setImportResolver(this.importResolver);
this._configOptions,
this._importResolver.host
);
this.program.setImportResolver(this._importResolver);
break; break;
} }

View File

@ -60,7 +60,7 @@ export class LimitedAccessHost extends NoAccessHost {
} }
export class FullAccessHost extends LimitedAccessHost { export class FullAccessHost extends LimitedAccessHost {
constructor(protected _fs: FileSystem) { constructor(protected fs: FileSystem) {
super(); super();
} }
@ -84,7 +84,7 @@ export class FullAccessHost extends LimitedAccessHost {
override getPythonSearchPaths(pythonPath?: string, logInfo?: string[]): PythonPathResult { override getPythonSearchPaths(pythonPath?: string, logInfo?: string[]): PythonPathResult {
const importFailureInfo = logInfo ?? []; const importFailureInfo = logInfo ?? [];
let result = this._executePythonInterpreter(pythonPath, (p) => let result = this._executePythonInterpreter(pythonPath, (p) =>
this._getSearchPathResultFromInterpreter(this._fs, p, importFailureInfo) this._getSearchPathResultFromInterpreter(this.fs, p, importFailureInfo)
); );
if (!result) { if (!result) {

View File

@ -15,7 +15,7 @@ import { FileSystem } from './fileSystem';
import { convertUriToPath } from './pathUtils'; import { convertUriToPath } from './pathUtils';
export class UriParser { export class UriParser {
constructor(protected readonly _fs: FileSystem) {} constructor(protected readonly fs: FileSystem) {}
decodeTextDocumentPosition(textDocument: TextDocumentIdentifier, position: Position) { decodeTextDocumentPosition(textDocument: TextDocumentIdentifier, position: Position) {
const filePath = this.decodeTextDocumentUri(textDocument.uri); const filePath = this.decodeTextDocumentUri(textDocument.uri);
@ -23,7 +23,7 @@ export class UriParser {
} }
decodeTextDocumentUri(uriString: string) { decodeTextDocumentUri(uriString: string) {
return convertUriToPath(this._fs, uriString); return convertUriToPath(this.fs, uriString);
} }
isLocal(uri: URI | string | undefined) { isLocal(uri: URI | string | undefined) {

View File

@ -293,10 +293,6 @@ namespace VSDiagnosticRank {
} }
export abstract class LanguageServerBase implements LanguageServerInterface { export abstract class LanguageServerBase implements LanguageServerInterface {
protected _defaultClientConfig: any;
protected _workspaceFactory: WorkspaceFactory;
protected _cacheManager: CacheManager;
// We support running only one "find all reference" at a time. // We support running only one "find all reference" at a time.
private _pendingFindAllRefsCancellationSource: AbstractCancellationTokenSource | undefined; private _pendingFindAllRefsCancellationSource: AbstractCancellationTokenSource | undefined;
@ -338,37 +334,38 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
completionItemResolveSupportsAdditionalTextEdits: false, completionItemResolveSupportsAdditionalTextEdits: false,
}; };
// File system abstraction. protected defaultClientConfig: any;
protected _serviceFS: PyrightFileSystem; protected workspaceFactory: WorkspaceFactory;
protected cacheManager: CacheManager;
protected _uriParser: UriParser; protected fs: PyrightFileSystem;
protected uriParser: UriParser;
constructor( constructor(
protected _serverOptions: ServerOptions, protected serverOptions: ServerOptions,
protected _connection: Connection, protected connection: Connection,
readonly console: ConsoleInterface, readonly console: ConsoleInterface,
uriParserFactory = (fs: FileSystem) => new UriParser(fs) uriParserFactory = (fs: FileSystem) => new UriParser(fs)
) { ) {
// Stash the base directory into a global variable. // Stash the base directory into a global variable.
// This must happen before fs.getModulePath(). // This must happen before fs.getModulePath().
(global as any).__rootDirectory = _serverOptions.rootDirectory; (global as any).__rootDirectory = serverOptions.rootDirectory;
this.console.info( this.console.info(
`${_serverOptions.productName} language server ${ `${serverOptions.productName} language server ${
_serverOptions.version && _serverOptions.version + ' ' serverOptions.version && serverOptions.version + ' '
}starting` }starting`
); );
this.console.info(`Server root directory: ${_serverOptions.rootDirectory}`); this.console.info(`Server root directory: ${serverOptions.rootDirectory}`);
this._cacheManager = new CacheManager(); this.cacheManager = new CacheManager();
this._serviceFS = new PyrightFileSystem(this._serverOptions.fileSystem); this.fs = new PyrightFileSystem(this.serverOptions.fileSystem);
this._uriParser = uriParserFactory(this._serviceFS); this.uriParser = uriParserFactory(this.fs);
this._workspaceFactory = new WorkspaceFactory( this.workspaceFactory = new WorkspaceFactory(
this.console, this.console,
this._uriParser, this.uriParser,
this.createAnalyzerServiceForWorkspace.bind(this), this.createAnalyzerServiceForWorkspace.bind(this),
this.isPythonPathImmutable.bind(this), this.isPythonPathImmutable.bind(this),
this.onWorkspaceCreated.bind(this) this.onWorkspaceCreated.bind(this)
@ -377,18 +374,18 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// Set the working directory to a known location within // Set the working directory to a known location within
// the extension directory. Otherwise the execution of // the extension directory. Otherwise the execution of
// python can have unintended and surprising results. // python can have unintended and surprising results.
const moduleDirectory = this._serviceFS.getModulePath(); const moduleDirectory = this.fs.getModulePath();
if (moduleDirectory) { if (moduleDirectory) {
this._serviceFS.chdir(moduleDirectory); this.fs.chdir(moduleDirectory);
} }
// Set up callbacks. // Set up callbacks.
this.setupConnection(_serverOptions.supportedCommands ?? [], _serverOptions.supportedCodeActions ?? []); this.setupConnection(serverOptions.supportedCommands ?? [], serverOptions.supportedCodeActions ?? []);
this._progressReporter = new ProgressReportTracker(this.createProgressReporter()); this._progressReporter = new ProgressReportTracker(this.createProgressReporter());
// Listen on the connection. // Listen on the connection.
this._connection.listen(); this.connection.listen();
// Setup extensions // Setup extensions
Extensions.createLanguageServiceExtensions(this); Extensions.createLanguageServiceExtensions(this);
@ -396,7 +393,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// Provides access to the client's window. // Provides access to the client's window.
get window(): RemoteWindow { get window(): RemoteWindow {
return this._connection.window; return this.connection.window;
} }
get supportAdvancedEdits(): boolean { get supportAdvancedEdits(): boolean {
@ -405,7 +402,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// Convert uri to path // Convert uri to path
decodeTextDocumentUri(uriString: string): string { decodeTextDocumentUri(uriString: string): string {
return this._uriParser.decodeTextDocumentUri(uriString); return this.uriParser.decodeTextDocumentUri(uriString);
} }
abstract createBackgroundAnalysis(serviceId: string): BackgroundAnalysisBase | undefined; abstract createBackgroundAnalysis(serviceId: string): BackgroundAnalysisBase | undefined;
@ -422,16 +419,16 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
this.console.info(`Starting service instance "${name}"`); this.console.info(`Starting service instance "${name}"`);
const serviceId = getNextServiceId(name); const serviceId = getNextServiceId(name);
const service = new AnalyzerService(name, services?.fs ?? this._serviceFS, { const service = new AnalyzerService(name, services?.fs ?? this.fs, {
console: this.console, console: this.console,
hostFactory: this.createHost.bind(this), hostFactory: this.createHost.bind(this),
importResolverFactory: this.createImportResolver.bind(this), importResolverFactory: this.createImportResolver.bind(this),
backgroundAnalysis: services ? services.backgroundAnalysis : this.createBackgroundAnalysis(serviceId), backgroundAnalysis: services ? services.backgroundAnalysis : this.createBackgroundAnalysis(serviceId),
maxAnalysisTime: this._serverOptions.maxAnalysisTimeInForeground, maxAnalysisTime: this.serverOptions.maxAnalysisTimeInForeground,
backgroundAnalysisProgramFactory: this.createBackgroundAnalysisProgram.bind(this), backgroundAnalysisProgramFactory: this.createBackgroundAnalysisProgram.bind(this),
cancellationProvider: this._serverOptions.cancellationProvider, cancellationProvider: this.serverOptions.cancellationProvider,
libraryReanalysisTimeProvider, libraryReanalysisTimeProvider,
cacheManager: this._cacheManager, cacheManager: this.cacheManager,
serviceId, serviceId,
}); });
@ -440,7 +437,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
async test_getWorkspaces() { async test_getWorkspaces() {
const workspaces = [...this._workspaceFactory.items()]; const workspaces = [...this.workspaceFactory.items()];
for (const workspace of workspaces) { for (const workspace of workspaces) {
await workspace.isInitialized.promise; await workspace.isInitialized.promise;
} }
@ -449,28 +446,28 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
async getWorkspaceForFile(filePath: string, pythonPath?: string): Promise<Workspace> { async getWorkspaceForFile(filePath: string, pythonPath?: string): Promise<Workspace> {
return this._workspaceFactory.getWorkspaceForFile(filePath, pythonPath); return this.workspaceFactory.getWorkspaceForFile(filePath, pythonPath);
} }
async getContainingWorkspacesForFile(filePath: string): Promise<Workspace[]> { async getContainingWorkspacesForFile(filePath: string): Promise<Workspace[]> {
return this._workspaceFactory.getContainingWorkspacesForFile(filePath); return this.workspaceFactory.getContainingWorkspacesForFile(filePath);
} }
reanalyze() { reanalyze() {
this._workspaceFactory.items().forEach((workspace) => { this.workspaceFactory.items().forEach((workspace) => {
workspace.service.invalidateAndForceReanalysis(); workspace.service.invalidateAndForceReanalysis();
}); });
} }
restart() { restart() {
this._workspaceFactory.items().forEach((workspace) => { this.workspaceFactory.items().forEach((workspace) => {
workspace.service.restart(); workspace.service.restart();
}); });
} }
updateSettingsForAllWorkspaces(): void { updateSettingsForAllWorkspaces(): void {
const tasks: Promise<void>[] = []; const tasks: Promise<void>[] = [];
this._workspaceFactory.items().forEach((workspace) => { this.workspaceFactory.items().forEach((workspace) => {
// Updating settings can change workspace's file ownership. Make workspace uninitialized so that // Updating settings can change workspace's file ownership. Make workspace uninitialized so that
// features can wait until workspace gets new settings. // features can wait until workspace gets new settings.
// the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous // the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous
@ -497,7 +494,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
(this.console as ConsoleWithLogLevel).level = serverSettings.logLevel ?? LogLevel.Info; (this.console as ConsoleWithLogLevel).level = serverSettings.logLevel ?? LogLevel.Info;
// Apply the new path to the workspace (before restarting the service). // Apply the new path to the workspace (before restarting the service).
serverSettings.pythonPath = this._workspaceFactory.applyPythonPath(workspace, serverSettings.pythonPath); serverSettings.pythonPath = this.workspaceFactory.applyPythonPath(workspace, serverSettings.pythonPath);
// Then use the updated settings to restart the service. // Then use the updated settings to restart the service.
this.updateOptionsAndRestartService(workspace, serverSettings); this.updateOptionsAndRestartService(workspace, serverSettings);
@ -549,11 +546,11 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
if (section !== undefined) { if (section !== undefined) {
item.section = section; item.section = section;
} }
return this._connection.workspace.getConfiguration(item); return this.connection.workspace.getConfiguration(item);
} }
if (this._defaultClientConfig) { if (this.defaultClientConfig) {
return getNestedProperty(this._defaultClientConfig, section); return getNestedProperty(this.defaultClientConfig, section);
} }
return undefined; return undefined;
@ -607,54 +604,54 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
protected setupConnection(supportedCommands: string[], supportedCodeActions: string[]): void { protected setupConnection(supportedCommands: string[], supportedCodeActions: string[]): void {
// After the server has started the client sends an initialize request. The server receives // After the server has started the client sends an initialize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilities. // in the passed params the rootPath of the workspace plus the client capabilities.
this._connection.onInitialize((params) => this.initialize(params, supportedCommands, supportedCodeActions)); this.connection.onInitialize((params) => this.initialize(params, supportedCommands, supportedCodeActions));
this._connection.onInitialized(() => this.onInitialized()); this.connection.onInitialized(() => this.onInitialized());
this._connection.onDidChangeConfiguration((params) => this.onDidChangeConfiguration(params)); this.connection.onDidChangeConfiguration((params) => this.onDidChangeConfiguration(params));
this._connection.onCodeAction((params, token) => this.executeCodeAction(params, token)); this.connection.onCodeAction((params, token) => this.executeCodeAction(params, token));
this._connection.onDefinition(async (params, token) => this.onDefinition(params, token)); this.connection.onDefinition(async (params, token) => this.onDefinition(params, token));
this._connection.onDeclaration(async (params, token) => this.onDeclaration(params, token)); this.connection.onDeclaration(async (params, token) => this.onDeclaration(params, token));
this._connection.onTypeDefinition(async (params, token) => this.onTypeDefinition(params, token)); this.connection.onTypeDefinition(async (params, token) => this.onTypeDefinition(params, token));
this._connection.onReferences(async (params, token, workDoneReporter, resultReporter) => this.connection.onReferences(async (params, token, workDoneReporter, resultReporter) =>
this.onReferences(params, token, workDoneReporter, resultReporter) this.onReferences(params, token, workDoneReporter, resultReporter)
); );
this._connection.onDocumentSymbol(async (params, token) => this.onDocumentSymbol(params, token)); this.connection.onDocumentSymbol(async (params, token) => this.onDocumentSymbol(params, token));
this._connection.onWorkspaceSymbol(async (params, token, _, resultReporter) => this.connection.onWorkspaceSymbol(async (params, token, _, resultReporter) =>
this.onWorkspaceSymbol(params, token, resultReporter) this.onWorkspaceSymbol(params, token, resultReporter)
); );
this._connection.onHover(async (params, token) => this.onHover(params, token)); this.connection.onHover(async (params, token) => this.onHover(params, token));
this._connection.onDocumentHighlight(async (params, token) => this.onDocumentHighlight(params, token)); this.connection.onDocumentHighlight(async (params, token) => this.onDocumentHighlight(params, token));
this._connection.onSignatureHelp(async (params, token) => this.onSignatureHelp(params, token)); this.connection.onSignatureHelp(async (params, token) => this.onSignatureHelp(params, token));
this._connection.onCompletion((params, token) => this.onCompletion(params, token)); this.connection.onCompletion((params, token) => this.onCompletion(params, token));
this._connection.onCompletionResolve(async (params, token) => this.onCompletionResolve(params, token)); this.connection.onCompletionResolve(async (params, token) => this.onCompletionResolve(params, token));
this._connection.onPrepareRename(async (params, token) => this.onPrepareRenameRequest(params, token)); this.connection.onPrepareRename(async (params, token) => this.onPrepareRenameRequest(params, token));
this._connection.onRenameRequest(async (params, token) => this.onRenameRequest(params, token)); this.connection.onRenameRequest(async (params, token) => this.onRenameRequest(params, token));
const callHierarchy = this._connection.languages.callHierarchy; const callHierarchy = this.connection.languages.callHierarchy;
callHierarchy.onPrepare(async (params, token) => this.onPrepare(params, token)); callHierarchy.onPrepare(async (params, token) => this.onPrepare(params, token));
callHierarchy.onIncomingCalls(async (params, token) => this.onIncomingCalls(params, token)); callHierarchy.onIncomingCalls(async (params, token) => this.onIncomingCalls(params, token));
callHierarchy.onOutgoingCalls(async (params, token) => this.onOutgoingCalls(params, token)); callHierarchy.onOutgoingCalls(async (params, token) => this.onOutgoingCalls(params, token));
this._connection.onDidOpenTextDocument(async (params) => this.onDidOpenTextDocument(params)); this.connection.onDidOpenTextDocument(async (params) => this.onDidOpenTextDocument(params));
this._connection.onDidChangeTextDocument(async (params) => this.onDidChangeTextDocument(params)); this.connection.onDidChangeTextDocument(async (params) => this.onDidChangeTextDocument(params));
this._connection.onDidCloseTextDocument(async (params) => this.onDidCloseTextDocument(params)); this.connection.onDidCloseTextDocument(async (params) => this.onDidCloseTextDocument(params));
this._connection.onDidChangeWatchedFiles((params) => this.onDidChangeWatchedFiles(params)); this.connection.onDidChangeWatchedFiles((params) => this.onDidChangeWatchedFiles(params));
this._connection.onExecuteCommand(async (params, token, reporter) => this.connection.onExecuteCommand(async (params, token, reporter) =>
this.onExecuteCommand(params, token, reporter) this.onExecuteCommand(params, token, reporter)
); );
this._connection.onShutdown(async (token) => this.onShutdown(token)); this.connection.onShutdown(async (token) => this.onShutdown(token));
} }
protected initialize( protected initialize(
@ -714,7 +711,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
); );
// Create a service instance for each of the workspace folders. // Create a service instance for each of the workspace folders.
this._workspaceFactory.handleInitialize(params); this.workspaceFactory.handleInitialize(params);
const result: InitializeResult = { const result: InitializeResult = {
capabilities: { capabilities: {
@ -774,8 +771,8 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
return; return;
} }
this._connection.workspace.onDidChangeWorkspaceFolders((event) => { this.connection.workspace.onDidChangeWorkspaceFolders((event) => {
this._workspaceFactory.handleWorkspaceFoldersChanged(event); this.workspaceFactory.handleWorkspaceFoldersChanged(event);
this._setupFileWatcher(); this._setupFileWatcher();
}); });
@ -785,7 +782,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
protected onDidChangeConfiguration(params: DidChangeConfigurationParams) { protected onDidChangeConfiguration(params: DidChangeConfigurationParams) {
this.console.log(`Received updated settings`); this.console.log(`Received updated settings`);
if (params?.settings) { if (params?.settings) {
this._defaultClientConfig = params?.settings; this.defaultClientConfig = params?.settings;
} }
this.updateSettingsForAllWorkspaces(); this.updateSettingsForAllWorkspaces();
} }
@ -845,7 +842,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
) { ) {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -885,7 +882,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
this._pendingFindAllRefsCancellationSource = source; this._pendingFindAllRefsCancellationSource = source;
try { try {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition( const { filePath, position } = this.uriParser.decodeTextDocumentPosition(
params.textDocument, params.textDocument,
params.position params.position
); );
@ -915,7 +912,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
): Promise<DocumentSymbol[] | SymbolInformation[] | null | undefined> { ): Promise<DocumentSymbol[] | SymbolInformation[] | null | undefined> {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri); const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -942,7 +939,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
? (symbols) => resultReporter.report(symbols) ? (symbols) => resultReporter.report(symbols)
: (symbols) => appendArray(symbolList, symbols); : (symbols) => appendArray(symbolList, symbols);
for (const workspace of this._workspaceFactory.items()) { for (const workspace of this.workspaceFactory.items()) {
await workspace.isInitialized.promise; await workspace.isInitialized.promise;
if (!workspace.disableLanguageServices && !workspace.disableWorkspaceSymbol) { if (!workspace.disableLanguageServices && !workspace.disableWorkspaceSymbol) {
workspace.service.reportSymbolsForWorkspace(params.query, reporter, token); workspace.service.reportSymbolsForWorkspace(params.query, reporter, token);
@ -953,7 +950,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
protected async onHover(params: HoverParams, token: CancellationToken) { protected async onHover(params: HoverParams, token: CancellationToken) {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
return workspace.service.run((program) => { return workspace.service.run((program) => {
@ -962,7 +959,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
filePath, filePath,
position, position,
this.client.hoverContentFormat, this.client.hoverContentFormat,
!!this._serverOptions.supportsTelemetry, !!this.serverOptions.supportsTelemetry,
token token
).getHover(); ).getHover();
}, token); }, token);
@ -972,7 +969,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: DocumentHighlightParams, params: DocumentHighlightParams,
token: CancellationToken token: CancellationToken
): Promise<DocumentHighlight[] | null | undefined> { ): Promise<DocumentHighlight[] | null | undefined> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
return workspace.service.run((program) => { return workspace.service.run((program) => {
@ -984,7 +981,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: SignatureHelpParams, params: SignatureHelpParams,
token: CancellationToken token: CancellationToken
): Promise<SignatureHelp | undefined | null> { ): Promise<SignatureHelp | undefined | null> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1023,7 +1020,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
this._lastTriggerKind = params.context?.triggerKind; this._lastTriggerKind = params.context?.triggerKind;
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1049,7 +1046,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
completions.completionList && completions.completionList &&
completions.completionList.items.length > 0 && completions.completionList.items.length > 0 &&
completions.memberAccessInfo.lastKnownModule && completions.memberAccessInfo.lastKnownModule &&
this._serverOptions.supportsTelemetry this.serverOptions.supportsTelemetry
) { ) {
// Just stick it on the first item. It only checks the first one // Just stick it on the first item. It only checks the first one
completions.completionList.items[0].data = { completions.completionList.items[0].data = {
@ -1080,7 +1077,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: PrepareRenameParams, params: PrepareRenameParams,
token: CancellationToken token: CancellationToken
): Promise<Range | { range: Range; placeholder: string } | null> { ): Promise<Range | { range: Range; placeholder: string } | null> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1102,7 +1099,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: RenameParams, params: RenameParams,
token: CancellationToken token: CancellationToken
): Promise<WorkspaceEdit | null | undefined> { ): Promise<WorkspaceEdit | null | undefined> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1129,7 +1126,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: CallHierarchyPrepareParams, params: CallHierarchyPrepareParams,
token: CancellationToken token: CancellationToken
): Promise<CallHierarchyItem[] | null> { ): Promise<CallHierarchyItem[] | null> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1142,7 +1139,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
protected async onIncomingCalls(params: CallHierarchyIncomingCallsParams, token: CancellationToken) { protected async onIncomingCalls(params: CallHierarchyIncomingCallsParams, token: CancellationToken) {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.item, params.item.range.start); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1158,7 +1155,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
params: CallHierarchyOutgoingCallsParams, params: CallHierarchyOutgoingCallsParams,
token: CancellationToken token: CancellationToken
): Promise<CallHierarchyOutgoingCall[] | null> { ): Promise<CallHierarchyOutgoingCall[] | null> {
const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.item, params.item.range.start); const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
if (workspace.disableLanguageServices) { if (workspace.disableLanguageServices) {
@ -1171,9 +1168,9 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
protected async onDidOpenTextDocument(params: DidOpenTextDocumentParams, ipythonMode = IPythonMode.None) { protected async onDidOpenTextDocument(params: DidOpenTextDocumentParams, ipythonMode = IPythonMode.None) {
const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri); const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
if (!this._serviceFS.addUriMap(params.textDocument.uri, filePath)) { if (!this.fs.addUriMap(params.textDocument.uri, filePath)) {
// We do not support opening 1 file with 2 different uri. // We do not support opening 1 file with 2 different uri.
return; return;
} }
@ -1188,8 +1185,8 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
protected async onDidChangeTextDocument(params: DidChangeTextDocumentParams, ipythonMode = IPythonMode.None) { protected async onDidChangeTextDocument(params: DidChangeTextDocumentParams, ipythonMode = IPythonMode.None) {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri); const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
if (!this._serviceFS.hasUriMapEntry(params.textDocument.uri, filePath)) { if (!this.fs.hasUriMapEntry(params.textDocument.uri, filePath)) {
// We do not support opening 1 file with 2 different uri. // We do not support opening 1 file with 2 different uri.
return; return;
} }
@ -1202,8 +1199,8 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
protected async onDidCloseTextDocument(params: DidCloseTextDocumentParams) { protected async onDidCloseTextDocument(params: DidCloseTextDocumentParams) {
const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri); const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
if (!this._serviceFS.removeUriMap(params.textDocument.uri, filePath)) { if (!this.fs.removeUriMap(params.textDocument.uri, filePath)) {
// We do not support opening 1 file with 2 different uri. // We do not support opening 1 file with 2 different uri.
return; return;
} }
@ -1217,9 +1214,9 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) { protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) {
params.changes.forEach((change) => { params.changes.forEach((change) => {
const filePath = this._serviceFS.realCasePath(this._uriParser.decodeTextDocumentUri(change.uri)); const filePath = this.fs.realCasePath(this.uriParser.decodeTextDocumentUri(change.uri));
const eventType: FileWatcherEventType = change.type === 1 ? 'add' : 'change'; const eventType: FileWatcherEventType = change.type === 1 ? 'add' : 'change';
this._serverOptions.fileWatcherHandler.onFileChange(eventType, filePath); this.serverOptions.fileWatcherHandler.onFileChange(eventType, filePath);
}); });
} }
@ -1239,13 +1236,13 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
if (WorkspaceEdit.is(result)) { if (WorkspaceEdit.is(result)) {
// Tell client to apply edits. // Tell client to apply edits.
// Do not await; the client isn't expecting a result. // Do not await; the client isn't expecting a result.
this._connection.workspace.applyEdit({ label: `Command '${params.command}'`, edit: result }); this.connection.workspace.applyEdit({ label: `Command '${params.command}'`, edit: result });
} }
if (CommandResult.is(result)) { if (CommandResult.is(result)) {
// Tell client to apply edits. // Tell client to apply edits.
// Await so that we return after the edit is complete. // Await so that we return after the edit is complete.
await this._connection.workspace.applyEdit({ label: result.label, edit: result.edits }); await this.connection.workspace.applyEdit({ label: result.label, edit: result.edits });
} }
return result; return result;
@ -1273,7 +1270,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
protected onShutdown(token: CancellationToken) { protected onShutdown(token: CancellationToken) {
// Shutdown remaining workspaces. // Shutdown remaining workspaces.
this._workspaceFactory.clear(); this.workspaceFactory.clear();
return Promise.resolve(); return Promise.resolve();
} }
@ -1340,7 +1337,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
} }
this._sendDiagnostics(this.convertDiagnostics(fs, fileDiag)); this._sendDiagnostics(this.convertDiagnostics(fs, fileDiag));
this._serviceFS.pendingRequest(fileDiag.filePath, fileDiag.diagnostics.length > 0); this.fs.pendingRequest(fileDiag.filePath, fileDiag.diagnostics.length > 0);
}); });
if (!this._progressReporter.isEnabled(results)) { if (!this._progressReporter.isEnabled(results)) {
@ -1393,7 +1390,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
const libraryReanalysisTimeProvider = const libraryReanalysisTimeProvider =
kinds.length === 1 && kinds[0] === WellKnownWorkspaceKinds.Regular kinds.length === 1 && kinds[0] === WellKnownWorkspaceKinds.Regular
? () => ? () =>
this._workspaceFactory.hasMultipleWorkspaces(kinds[0]) this.workspaceFactory.hasMultipleWorkspaces(kinds[0])
? multiWorkspaceBackOffTime ? multiWorkspaceBackOffTime
: defaultBackOffTime : defaultBackOffTime
: () => defaultBackOffTime; : () => defaultBackOffTime;
@ -1405,7 +1402,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// Tell all of the services that the user is actively // Tell all of the services that the user is actively
// interacting with one or more editors, so they should // interacting with one or more editors, so they should
// back off from performing any work. // back off from performing any work.
this._workspaceFactory.items().forEach((workspace: { service: { recordUserInteractionTime: () => void } }) => { this.workspaceFactory.items().forEach((workspace: { service: { recordUserInteractionTime: () => void } }) => {
workspace.service.recordUserInteractionTime(); workspace.service.recordUserInteractionTime();
}); });
} }
@ -1440,22 +1437,22 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// Get rid of any search path under workspace root since it is already watched by // Get rid of any search path under workspace root since it is already watched by
// "**" above. // "**" above.
const foldersToWatch = deduplicateFolders( const foldersToWatch = deduplicateFolders(
this._workspaceFactory this.workspaceFactory
.getNonDefaultWorkspaces() .getNonDefaultWorkspaces()
.map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath))) .map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath)))
); );
foldersToWatch.forEach((p) => { foldersToWatch.forEach((p) => {
const globPattern = isFile(this._serviceFS, p, /* treatZipDirectoryAsFile */ true) const globPattern = isFile(this.fs, p, /* treatZipDirectoryAsFile */ true)
? { baseUri: convertPathToUri(this._serviceFS, getDirectoryPath(p)), pattern: getFileName(p) } ? { baseUri: convertPathToUri(this.fs, getDirectoryPath(p)), pattern: getFileName(p) }
: { baseUri: convertPathToUri(this._serviceFS, p), pattern: '**' }; : { baseUri: convertPathToUri(this.fs, p), pattern: '**' };
watchers.push({ globPattern, kind: watchKind }); watchers.push({ globPattern, kind: watchKind });
}); });
} }
// File watcher is pylance wide service. Dispose all existing file watchers and create new ones. // File watcher is pylance wide service. Dispose all existing file watchers and create new ones.
this._connection.client.register(DidChangeWatchedFilesNotification.type, { watchers }).then((d) => { this.connection.client.register(DidChangeWatchedFilesNotification.type, { watchers }).then((d) => {
if (this._lastFileWatcherRegistration) { if (this._lastFileWatcherRegistration) {
this._lastFileWatcherRegistration.dispose(); this._lastFileWatcherRegistration.dispose();
} }
@ -1466,7 +1463,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
private _sendDiagnostics(params: PublishDiagnosticsParams[]) { private _sendDiagnostics(params: PublishDiagnosticsParams[]) {
for (const param of params) { for (const param of params) {
this._connection.sendDiagnostics(param); this.connection.sendDiagnostics(param);
} }
} }
@ -1488,10 +1485,10 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
// created by the LSP library. If it's the latter, we'll create a server-initiated // created by the LSP library. If it's the latter, we'll create a server-initiated
// progress reporter. // progress reporter.
if (reporter.constructor !== nullProgressReporter.constructor) { if (reporter.constructor !== nullProgressReporter.constructor) {
return { reporter: reporter, source: CancelAfter(this._serverOptions.cancellationProvider, token) }; return { reporter: reporter, source: CancelAfter(this.serverOptions.cancellationProvider, token) };
} }
const serverInitiatedReporter = await this._connection.window.createWorkDoneProgress(); const serverInitiatedReporter = await this.connection.window.createWorkDoneProgress();
serverInitiatedReporter.begin( serverInitiatedReporter.begin(
title, title,
/* percentage */ undefined, /* percentage */ undefined,
@ -1501,7 +1498,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
return { return {
reporter: serverInitiatedReporter, reporter: serverInitiatedReporter,
source: CancelAfter(this._serverOptions.cancellationProvider, token, serverInitiatedReporter.token), source: CancelAfter(this.serverOptions.cancellationProvider, token, serverInitiatedReporter.token),
}; };
} }
@ -1511,7 +1508,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
diags.forEach((diag) => { diags.forEach((diag) => {
const severity = convertCategoryToSeverity(diag.category); const severity = convertCategoryToSeverity(diag.category);
const rule = diag.getRule(); const rule = diag.getRule();
const vsDiag = Diagnostic.create(diag.range, diag.message, severity, rule, this._serverOptions.productName); const vsDiag = Diagnostic.create(diag.range, diag.message, severity, rule, this.serverOptions.productName);
if ( if (
diag.category === DiagnosticCategory.UnusedCode || diag.category === DiagnosticCategory.UnusedCode ||

View File

@ -36,16 +36,16 @@ export enum DefinitionFilter {
class DefinitionProviderBase { class DefinitionProviderBase {
protected constructor( protected constructor(
protected readonly _sourceMapper: SourceMapper, protected readonly sourceMapper: SourceMapper,
protected readonly _evaluator: TypeEvaluator, protected readonly evaluator: TypeEvaluator,
protected readonly _node: ParseNode | undefined, protected readonly node: ParseNode | undefined,
protected readonly _offset: number, protected readonly offset: number,
private readonly _filter: DefinitionFilter, private readonly _filter: DefinitionFilter,
protected readonly _token: CancellationToken protected readonly token: CancellationToken
) {} ) {}
getDefinitionsForNode(node: ParseNode, offset: number) { getDefinitionsForNode(node: ParseNode, offset: number) {
throwIfCancellationRequested(this._token); throwIfCancellationRequested(this.token);
const definitions: DocumentRange[] = []; const definitions: DocumentRange[] = [];
@ -53,24 +53,24 @@ class DefinitionProviderBase {
Extensions.getProgramExtensions(node).forEach((e) => { Extensions.getProgramExtensions(node).forEach((e) => {
if (e.declarationProviderExtension) { if (e.declarationProviderExtension) {
const declarations = e.declarationProviderExtension.tryGetDeclarations( const declarations = e.declarationProviderExtension.tryGetDeclarations(
this._evaluator, this.evaluator,
node, node,
offset, offset,
DeclarationUseCase.Definition, DeclarationUseCase.Definition,
this._token this.token
); );
this._resolveDeclarations(declarations, definitions); this.resolveDeclarations(declarations, definitions);
} }
}); });
// There should be only one 'definition', so only if extensions failed should we try again. // There should be only one 'definition', so only if extensions failed should we try again.
if (definitions.length === 0) { if (definitions.length === 0) {
if (node.nodeType === ParseNodeType.Name) { if (node.nodeType === ParseNodeType.Name) {
const declarations = this._evaluator.getDeclarationsForNameNode(node); const declarations = this.evaluator.getDeclarationsForNameNode(node);
this._resolveDeclarations(declarations, definitions); this.resolveDeclarations(declarations, definitions);
} else if (node.nodeType === ParseNodeType.String) { } else if (node.nodeType === ParseNodeType.String) {
const declarations = this._evaluator.getDeclarationsForStringNode(node); const declarations = this.evaluator.getDeclarationsForStringNode(node);
this._resolveDeclarations(declarations, definitions); this.resolveDeclarations(declarations, definitions);
} }
} }
@ -93,10 +93,10 @@ class DefinitionProviderBase {
return definitions; return definitions;
} }
protected _resolveDeclarations(declarations: Declaration[] | undefined, definitions: DocumentRange[]) { protected resolveDeclarations(declarations: Declaration[] | undefined, definitions: DocumentRange[]) {
if (declarations) { if (declarations) {
declarations.forEach((decl) => { declarations.forEach((decl) => {
let resolvedDecl = this._evaluator.resolveAliasDeclaration( let resolvedDecl = this.evaluator.resolveAliasDeclaration(
decl, decl,
/* resolveLocalNames */ true, /* resolveLocalNames */ true,
/* allowExternallyHiddenAccess */ true /* allowExternallyHiddenAccess */ true
@ -126,7 +126,7 @@ class DefinitionProviderBase {
if (isFunctionDeclaration(resolvedDecl)) { if (isFunctionDeclaration(resolvedDecl)) {
// Handle overloaded function case // Handle overloaded function case
const functionType = this._evaluator.getTypeForDeclaration(resolvedDecl)?.type; const functionType = this.evaluator.getTypeForDeclaration(resolvedDecl)?.type;
if (functionType && isOverloadedFunction(functionType)) { if (functionType && isOverloadedFunction(functionType)) {
for (const overloadDecl of functionType.overloads for (const overloadDecl of functionType.overloads
.map((o) => o.details.declaration) .map((o) => o.details.declaration)
@ -142,13 +142,13 @@ class DefinitionProviderBase {
if (isStubFile(resolvedDecl.path)) { if (isStubFile(resolvedDecl.path)) {
if (resolvedDecl.type === DeclarationType.Alias) { if (resolvedDecl.type === DeclarationType.Alias) {
// Add matching source module // Add matching source module
this._sourceMapper this.sourceMapper
.findModules(resolvedDecl.path) .findModules(resolvedDecl.path)
.map((m) => getFileInfo(m)?.filePath) .map((m) => getFileInfo(m)?.filePath)
.filter(isDefined) .filter(isDefined)
.forEach((f) => _addIfUnique(definitions, _createModuleEntry(f))); .forEach((f) => _addIfUnique(definitions, _createModuleEntry(f)));
} else { } else {
const implDecls = this._sourceMapper.findDeclarations(resolvedDecl); const implDecls = this.sourceMapper.findDeclarations(resolvedDecl);
for (const implDecl of implDecls) { for (const implDecl of implDecls) {
if (implDecl && implDecl.path) { if (implDecl && implDecl.path) {
_addIfUnique(definitions, { _addIfUnique(definitions, {
@ -192,11 +192,11 @@ export class DefinitionProvider extends DefinitionProviderBase {
} }
getDefinitions(): DocumentRange[] | undefined { getDefinitions(): DocumentRange[] | undefined {
if (this._node === undefined) { if (this.node === undefined) {
return undefined; return undefined;
} }
return this.getDefinitionsForNode(this._node, this._offset); return this.getDefinitionsForNode(this.node, this.offset);
} }
} }
@ -213,15 +213,15 @@ export class TypeDefinitionProvider extends DefinitionProviderBase {
} }
getDefinitions(): DocumentRange[] | undefined { getDefinitions(): DocumentRange[] | undefined {
throwIfCancellationRequested(this._token); throwIfCancellationRequested(this.token);
if (this._node === undefined) { if (this.node === undefined) {
return undefined; return undefined;
} }
const definitions: DocumentRange[] = []; const definitions: DocumentRange[] = [];
if (this._node.nodeType === ParseNodeType.Name) { if (this.node.nodeType === ParseNodeType.Name) {
const type = this._evaluator.getType(this._node); const type = this.evaluator.getType(this.node);
if (type) { if (type) {
let declarations: Declaration[] = []; let declarations: Declaration[] = [];
@ -230,7 +230,7 @@ export class TypeDefinitionProvider extends DefinitionProviderBase {
if (subtype?.category === TypeCategory.Class) { if (subtype?.category === TypeCategory.Class) {
appendArray( appendArray(
declarations, declarations,
this._sourceMapper.findClassDeclarationsByType(this._filePath, subtype) this.sourceMapper.findClassDeclarationsByType(this._filePath, subtype)
); );
} }
}); });
@ -238,14 +238,14 @@ export class TypeDefinitionProvider extends DefinitionProviderBase {
// Fall back to Go To Definition if the type can't be found (ex. Go To Type Definition // Fall back to Go To Definition if the type can't be found (ex. Go To Type Definition
// was executed on a type name) // was executed on a type name)
if (declarations.length === 0) { if (declarations.length === 0) {
declarations = this._evaluator.getDeclarationsForNameNode(this._node) ?? []; declarations = this.evaluator.getDeclarationsForNameNode(this.node) ?? [];
} }
this._resolveDeclarations(declarations, definitions); this.resolveDeclarations(declarations, definitions);
} }
} else if (this._node.nodeType === ParseNodeType.String) { } else if (this.node.nodeType === ParseNodeType.String) {
const declarations = this._evaluator.getDeclarationsForStringNode(this._node); const declarations = this.evaluator.getDeclarationsForStringNode(this.node);
this._resolveDeclarations(declarations, definitions); this.resolveDeclarations(declarations, definitions);
} }
if (definitions.length === 0) { if (definitions.length === 0) {

View File

@ -66,27 +66,27 @@ export class PyrightFileSystem
} }
override mkdirSync(path: string, options?: MkDirOptions): void { override mkdirSync(path: string, options?: MkDirOptions): void {
this._realFS.mkdirSync(path, options); this.realFS.mkdirSync(path, options);
} }
override chdir(path: string): void { override chdir(path: string): void {
this._realFS.chdir(path); this.realFS.chdir(path);
} }
override writeFileSync(path: string, data: string | Buffer, encoding: BufferEncoding | null): void { override writeFileSync(path: string, data: string | Buffer, encoding: BufferEncoding | null): void {
this._realFS.writeFileSync(this._getOriginalPath(path), data, encoding); this.realFS.writeFileSync(this.getOriginalPath(path), data, encoding);
} }
override unlinkSync(path: string): void { override unlinkSync(path: string): void {
this._realFS.unlinkSync(this._getOriginalPath(path)); this.realFS.unlinkSync(this.getOriginalPath(path));
} }
override createWriteStream(path: string): fs.WriteStream { override createWriteStream(path: string): fs.WriteStream {
return this._realFS.createWriteStream(this._getOriginalPath(path)); return this.realFS.createWriteStream(this.getOriginalPath(path));
} }
override copyFileSync(src: string, dst: string): void { override copyFileSync(src: string, dst: string): void {
this._realFS.copyFileSync(this._getOriginalPath(src), this._getOriginalPath(dst)); this.realFS.copyFileSync(this.getOriginalPath(src), this.getOriginalPath(dst));
} }
override getUri(originalPath: string): string { override getUri(originalPath: string): string {
@ -95,7 +95,7 @@ export class PyrightFileSystem
return entry.uri; return entry.uri;
} }
return this._realFS.getUri(originalPath); return this.realFS.getUri(originalPath);
} }
hasUriMapEntry(uriString: string, mappedPath: string): boolean { hasUriMapEntry(uriString: string, mappedPath: string): boolean {
@ -165,14 +165,14 @@ export class PyrightFileSystem
for (const path of paths) { for (const path of paths) {
this._rootSearched.add(path); this._rootSearched.add(path);
if (!this._realFS.existsSync(path) || !isDirectory(this._realFS, path)) { if (!this.realFS.existsSync(path) || !isDirectory(this.realFS, path)) {
continue; continue;
} }
let dirEntries: fs.Dirent[] = []; let dirEntries: fs.Dirent[] = [];
try { try {
dirEntries = this._realFS.readdirEntriesSync(path); dirEntries = this.realFS.readdirEntriesSync(path);
} catch { } catch {
// Leave empty set of dir entries to process. // Leave empty set of dir entries to process.
} }
@ -182,13 +182,13 @@ export class PyrightFileSystem
const partialStubPackagePath = combinePaths(path, entry.name); const partialStubPackagePath = combinePaths(path, entry.name);
const isDirectory = !entry.isSymbolicLink() const isDirectory = !entry.isSymbolicLink()
? entry.isDirectory() ? entry.isDirectory()
: !!tryStat(this._realFS, partialStubPackagePath)?.isDirectory(); : !!tryStat(this.realFS, partialStubPackagePath)?.isDirectory();
if (!isDirectory || !entry.name.endsWith(stubsSuffix)) { if (!isDirectory || !entry.name.endsWith(stubsSuffix)) {
continue; continue;
} }
const pyTypedInfo = getPyTypedInfo(this._realFS, partialStubPackagePath); const pyTypedInfo = getPyTypedInfo(this.realFS, partialStubPackagePath);
if (!pyTypedInfo || !pyTypedInfo.isPartiallyTyped) { if (!pyTypedInfo || !pyTypedInfo.isPartiallyTyped) {
// Stub-Package is fully typed. // Stub-Package is fully typed.
continue; continue;
@ -203,7 +203,7 @@ export class PyrightFileSystem
for (const root of roots) { for (const root of roots) {
const packagePath = combinePaths(root, packageName); const packagePath = combinePaths(root, packageName);
try { try {
const stat = tryStat(this._realFS, packagePath); const stat = tryStat(this.realFS, packagePath);
if (!stat?.isDirectory()) { if (!stat?.isDirectory()) {
continue; continue;
} }
@ -211,7 +211,7 @@ export class PyrightFileSystem
if (isBundledStub) { if (isBundledStub) {
// If partial stub we found is from bundled stub and library installed is marked as py.typed // If partial stub we found is from bundled stub and library installed is marked as py.typed
// ignore bundled partial stub. // ignore bundled partial stub.
const packagePyTyped = getPyTypedInfo(this._realFS, packagePath); const packagePyTyped = getPyTypedInfo(this.realFS, packagePath);
if (packagePyTyped && !packagePyTyped.isPartiallyTyped) { if (packagePyTyped && !packagePyTyped.isPartiallyTyped) {
// We have fully typed package. // We have fully typed package.
continue; continue;
@ -224,7 +224,7 @@ export class PyrightFileSystem
const originalPyiFile = combinePaths(partialStubPackagePath, partialStub); const originalPyiFile = combinePaths(partialStubPackagePath, partialStub);
const mappedPyiFile = combinePaths(packagePath, partialStub); const mappedPyiFile = combinePaths(packagePath, partialStub);
this._recordMovedEntry(mappedPyiFile, originalPyiFile); this.recordMovedEntry(mappedPyiFile, originalPyiFile);
} }
} catch { } catch {
// ignore // ignore
@ -235,18 +235,18 @@ export class PyrightFileSystem
} }
override dispose(): void { override dispose(): void {
this._realFS.dispose(); this.realFS.dispose();
} }
clearPartialStubs(): void { clearPartialStubs(): void {
super._clear(); super.clear();
this._rootSearched.clear(); this._rootSearched.clear();
this._partialStubPackagePaths.clear(); this._partialStubPackagePaths.clear();
} }
protected override _isMovedEntry(path: string) { protected override isMovedEntry(path: string) {
return this._partialStubPackagePaths.has(path) || super._isMovedEntry(path); return this._partialStubPackagePaths.has(path) || super.isMovedEntry(path);
} }
private _getRelativePathPartialStubs(path: string) { private _getRelativePathPartialStubs(path: string) {
@ -254,13 +254,13 @@ export class PyrightFileSystem
const partialStubPathLength = ensureTrailingDirectorySeparator(path).length; const partialStubPathLength = ensureTrailingDirectorySeparator(path).length;
const searchAllStubs = (path: string) => { const searchAllStubs = (path: string) => {
for (const entry of this._realFS.readdirEntriesSync(path)) { for (const entry of this.realFS.readdirEntriesSync(path)) {
const filePath = combinePaths(path, entry.name); const filePath = combinePaths(path, entry.name);
let isDirectory = entry.isDirectory(); let isDirectory = entry.isDirectory();
let isFile = entry.isFile(); let isFile = entry.isFile();
if (entry.isSymbolicLink()) { if (entry.isSymbolicLink()) {
const stat = tryStat(this._realFS, filePath); const stat = tryStat(this.realFS, filePath);
if (stat) { if (stat) {
isDirectory = stat.isDirectory(); isDirectory = stat.isDirectory();
isFile = stat.isFile(); isFile = stat.isFile();

View File

@ -31,15 +31,15 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
// Mapped files per a containing folder map // Mapped files per a containing folder map
private readonly _folderMap = new Map<string, { name: string; isFile: boolean }[]>(); private readonly _folderMap = new Map<string, { name: string; isFile: boolean }[]>();
constructor(protected _realFS: FileSystem) {} constructor(protected realFS: FileSystem) {}
existsSync(path: string): boolean { existsSync(path: string): boolean {
if (this._isMovedEntry(path)) { if (this.isMovedEntry(path)) {
// Pretend partial stub folder and its files not exist // Pretend partial stub folder and its files not exist
return false; return false;
} }
return this._realFS.existsSync(this._getOriginalPath(path)); return this.realFS.existsSync(this.getOriginalPath(path));
} }
mkdirSync(path: string, options?: MkDirOptions): void { mkdirSync(path: string, options?: MkDirOptions): void {
@ -55,14 +55,14 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
const entries: fs.Dirent[] = []; const entries: fs.Dirent[] = [];
const movedEntries = this._folderMap.get(maybeDirectory); const movedEntries = this._folderMap.get(maybeDirectory);
if (!movedEntries || this._realFS.existsSync(path)) { if (!movedEntries || this.realFS.existsSync(path)) {
entries.push( entries.push(
...this._realFS.readdirEntriesSync(path).filter((item) => { ...this.realFS.readdirEntriesSync(path).filter((item) => {
// Filter out the stub package directory and any // Filter out the stub package directory and any
// entries that will be overwritten by stub package // entries that will be overwritten by stub package
// virtual items. // virtual items.
return ( return (
!this._isMovedEntry(combinePaths(path, item.name)) && !this.isMovedEntry(combinePaths(path, item.name)) &&
!movedEntries?.some((movedEntry) => movedEntry.name === item.name) !movedEntries?.some((movedEntry) => movedEntry.name === item.name)
); );
}) })
@ -83,7 +83,7 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
readFileSync(path: string, encoding?: null): Buffer; readFileSync(path: string, encoding?: null): Buffer;
readFileSync(path: string, encoding: BufferEncoding): string; readFileSync(path: string, encoding: BufferEncoding): string;
readFileSync(path: string, encoding?: BufferEncoding | null): string | Buffer { readFileSync(path: string, encoding?: BufferEncoding | null): string | Buffer {
return this._realFS.readFileSync(this._getOriginalPath(path), encoding); return this.realFS.readFileSync(this.getOriginalPath(path), encoding);
} }
writeFileSync(path: string, data: string | Buffer, encoding: BufferEncoding | null): void { writeFileSync(path: string, data: string | Buffer, encoding: BufferEncoding | null): void {
@ -91,7 +91,7 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
} }
statSync(path: string): Stats { statSync(path: string): Stats {
return this._realFS.statSync(this._getOriginalPath(path)); return this.realFS.statSync(this.getOriginalPath(path));
} }
unlinkSync(path: string): void { unlinkSync(path: string): void {
@ -103,19 +103,19 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
return path; return path;
} }
return this._realFS.realpathSync(path); return this.realFS.realpathSync(path);
} }
getModulePath(): string { getModulePath(): string {
return this._realFS.getModulePath(); return this.realFS.getModulePath();
} }
createFileSystemWatcher(paths: string[], listener: FileWatcherEventHandler): FileWatcher { createFileSystemWatcher(paths: string[], listener: FileWatcherEventHandler): FileWatcher {
return this._realFS.createFileSystemWatcher(paths, listener); return this.realFS.createFileSystemWatcher(paths, listener);
} }
createReadStream(path: string): fs.ReadStream { createReadStream(path: string): fs.ReadStream {
return this._realFS.createReadStream(this._getOriginalPath(path)); return this.realFS.createReadStream(this.getOriginalPath(path));
} }
createWriteStream(path: string): fs.WriteStream { createWriteStream(path: string): fs.WriteStream {
@ -128,55 +128,55 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
// Async I/O // Async I/O
readFile(path: string): Promise<Buffer> { readFile(path: string): Promise<Buffer> {
return this._realFS.readFile(this._getOriginalPath(path)); return this.realFS.readFile(this.getOriginalPath(path));
} }
readFileText(path: string, encoding?: BufferEncoding): Promise<string> { readFileText(path: string, encoding?: BufferEncoding): Promise<string> {
return this._realFS.readFileText(this._getOriginalPath(path), encoding); return this.realFS.readFileText(this.getOriginalPath(path), encoding);
} }
// The directory returned by tmpdir must exist and be the same each time tmpdir is called. // The directory returned by tmpdir must exist and be the same each time tmpdir is called.
tmpdir(): string { tmpdir(): string {
return this._realFS.tmpdir(); return this.realFS.tmpdir();
} }
tmpfile(options?: TmpfileOptions): string { tmpfile(options?: TmpfileOptions): string {
return this._realFS.tmpfile(options); return this.realFS.tmpfile(options);
} }
realCasePath(path: string): string { realCasePath(path: string): string {
return this._realFS.realCasePath(path); return this.realFS.realCasePath(path);
} }
getUri(originalPath: string): string { getUri(originalPath: string): string {
return this._realFS.getUri(originalPath); return this.realFS.getUri(originalPath);
} }
// See whether the file is mapped to another location. // See whether the file is mapped to another location.
isMappedFilePath(filepath: string): boolean { isMappedFilePath(filepath: string): boolean {
return this._entryMap.has(filepath) || this._realFS.isMappedFilePath(filepath); return this._entryMap.has(filepath) || this.realFS.isMappedFilePath(filepath);
} }
// Get original filepath if the given filepath is mapped. // Get original filepath if the given filepath is mapped.
getOriginalFilePath(mappedFilePath: string) { getOriginalFilePath(mappedFilePath: string) {
return this._realFS.getOriginalFilePath(this._getOriginalPath(mappedFilePath)); return this.realFS.getOriginalFilePath(this.getOriginalPath(mappedFilePath));
} }
// Get mapped filepath if the given filepath is mapped. // Get mapped filepath if the given filepath is mapped.
getMappedFilePath(originalFilepath: string) { getMappedFilePath(originalFilepath: string) {
const mappedFilePath = this._realFS.getMappedFilePath(originalFilepath); const mappedFilePath = this.realFS.getMappedFilePath(originalFilepath);
return this._reverseEntryMap.get(mappedFilePath) ?? mappedFilePath; return this._reverseEntryMap.get(mappedFilePath) ?? mappedFilePath;
} }
isInZipOrEgg(path: string): boolean { isInZipOrEgg(path: string): boolean {
return this._realFS.isInZipOrEgg(path); return this.realFS.isInZipOrEgg(path);
} }
dispose(): void { dispose(): void {
this._realFS.dispose(); this.realFS.dispose();
} }
protected _recordMovedEntry(mappedPath: string, originalPath: string, reversible = true, isFile = true) { protected recordMovedEntry(mappedPath: string, originalPath: string, reversible = true, isFile = true) {
this._entryMap.set(mappedPath, originalPath); this._entryMap.set(mappedPath, originalPath);
if (reversible) { if (reversible) {
@ -192,15 +192,15 @@ export class ReadOnlyAugmentedFileSystem implements FileSystem {
} }
} }
protected _getOriginalPath(mappedFilePath: string) { protected getOriginalPath(mappedFilePath: string) {
return this._entryMap.get(mappedFilePath) ?? mappedFilePath; return this._entryMap.get(mappedFilePath) ?? mappedFilePath;
} }
protected _isMovedEntry(path: string) { protected isMovedEntry(path: string) {
return this._reverseEntryMap.has(path); return this._reverseEntryMap.has(path);
} }
protected _clear() { protected clear() {
this._entryMap.clear(); this._entryMap.clear();
this._reverseEntryMap.clear(); this._reverseEntryMap.clear();
this._folderMap.clear(); this._folderMap.clear();

View File

@ -23,7 +23,7 @@ import { BackgroundAnalysisBase } from './backgroundAnalysisBase';
import { CommandController } from './commands/commandController'; import { CommandController } from './commands/commandController';
import { getCancellationFolderName } from './common/cancellationUtils'; import { getCancellationFolderName } from './common/cancellationUtils';
import { ConfigOptions, SignatureDisplayType } from './common/configOptions'; import { ConfigOptions, SignatureDisplayType } from './common/configOptions';
import { ConsoleWithLogLevel, convertLogLevel, LogLevel } from './common/console'; import { ConsoleWithLogLevel, LogLevel, convertLogLevel } from './common/console';
import { isDebugMode, isString } from './common/core'; import { isDebugMode, isString } from './common/core';
import { expandPathVariables } from './common/envVarUtils'; import { expandPathVariables } from './common/envVarUtils';
import { FileBasedCancellationProvider } from './common/fileBasedCancellationUtils'; import { FileBasedCancellationProvider } from './common/fileBasedCancellationUtils';
@ -32,7 +32,7 @@ import { FullAccessHost } from './common/fullAccessHost';
import { Host } from './common/host'; import { Host } from './common/host';
import { resolvePaths } from './common/pathUtils'; import { resolvePaths } from './common/pathUtils';
import { ProgressReporter } from './common/progressReporter'; import { ProgressReporter } from './common/progressReporter';
import { createFromRealFileSystem, WorkspaceFileWatcherProvider } from './common/realFileSystem'; import { WorkspaceFileWatcherProvider, createFromRealFileSystem } from './common/realFileSystem';
import { LanguageServerBase, ServerSettings } from './languageServerBase'; import { LanguageServerBase, ServerSettings } from './languageServerBase';
import { CodeActionProvider } from './languageService/codeActionProvider'; import { CodeActionProvider } from './languageService/codeActionProvider';
import { Workspace } from './workspaceFactory'; import { Workspace } from './workspaceFactory';
@ -219,7 +219,7 @@ export class PyrightServer extends LanguageServerBase {
} }
protected override createHost() { protected override createHost() {
return new FullAccessHost(this._serviceFS); return new FullAccessHost(this.fs);
} }
protected override createImportResolver(fs: FileSystem, options: ConfigOptions, host: Host): ImportResolver { protected override createImportResolver(fs: FileSystem, options: ConfigOptions, host: Host): ImportResolver {
@ -246,7 +246,7 @@ export class PyrightServer extends LanguageServerBase {
): Promise<(Command | CodeAction)[] | undefined | null> { ): Promise<(Command | CodeAction)[] | undefined | null> {
this.recordUserInteractionTime(); this.recordUserInteractionTime();
const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri); const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
const workspace = await this.getWorkspaceForFile(filePath); const workspace = await this.getWorkspaceForFile(filePath);
return CodeActionProvider.getCodeActionsForPosition( return CodeActionProvider.getCodeActionsForPosition(
workspace, workspace,
@ -266,14 +266,14 @@ export class PyrightServer extends LanguageServerBase {
isEnabled: (data: AnalysisResults) => true, isEnabled: (data: AnalysisResults) => true,
begin: () => { begin: () => {
if (this.client.hasWindowProgressCapability) { if (this.client.hasWindowProgressCapability) {
workDoneProgress = this._connection.window.createWorkDoneProgress(); workDoneProgress = this.connection.window.createWorkDoneProgress();
workDoneProgress workDoneProgress
.then((progress) => { .then((progress) => {
progress.begin(''); progress.begin('');
}) })
.ignoreErrors(); .ignoreErrors();
} else { } else {
this._connection.sendNotification('pyright/beginProgress'); this.connection.sendNotification('pyright/beginProgress');
} }
}, },
report: (message: string) => { report: (message: string) => {
@ -284,7 +284,7 @@ export class PyrightServer extends LanguageServerBase {
}) })
.ignoreErrors(); .ignoreErrors();
} else { } else {
this._connection.sendNotification('pyright/reportProgress', message); this.connection.sendNotification('pyright/reportProgress', message);
} }
}, },
end: () => { end: () => {
@ -296,7 +296,7 @@ export class PyrightServer extends LanguageServerBase {
.ignoreErrors(); .ignoreErrors();
workDoneProgress = undefined; workDoneProgress = undefined;
} else { } else {
this._connection.sendNotification('pyright/endProgress'); this.connection.sendNotification('pyright/endProgress');
} }
}, },
}; };

View File

@ -385,7 +385,7 @@ export class TestState {
if (this.testData.rangesByText) { if (this.testData.rangesByText) {
return this.testData.rangesByText; return this.testData.rangesByText;
} }
const result = this.createMultiMap<Range>(this.getRanges(), (r) => this._rangeText(r)); const result = this.createMultiMap<Range>(this.getRanges(), (r) => this.rangeText(r));
this.testData.rangesByText = result; this.testData.rangesByText = result;
return result; return result;
@ -394,7 +394,7 @@ export class TestState {
getFilteredRanges<T extends {}>( getFilteredRanges<T extends {}>(
predicate: (m: Marker | undefined, d: T | undefined, text: string) => boolean predicate: (m: Marker | undefined, d: T | undefined, text: string) => boolean
): Range[] { ): Range[] {
return this.getRanges().filter((r) => predicate(r.marker, r.marker?.data as T | undefined, this._rangeText(r))); return this.getRanges().filter((r) => predicate(r.marker, r.marker?.data as T | undefined, this.rangeText(r)));
} }
getRangeByMarkerName(markerName: string): Range | undefined { getRangeByMarkerName(markerName: string): Range | undefined {
@ -904,7 +904,7 @@ export class TestState {
} }
verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) {
this._verifyTextMatches(this._rangeText(this._getOnlyRange()), !!includeWhiteSpace, expectedText); this._verifyTextMatches(this.rangeText(this._getOnlyRange()), !!includeWhiteSpace, expectedText);
} }
async verifyCompletion( async verifyCompletion(
@ -1536,7 +1536,7 @@ export class TestState {
} }
} }
protected _rangeText({ fileName, pos, end }: Range): string { protected rangeText({ fileName, pos, end }: Range): string {
return this.getFileContent(fileName).slice(pos, end); return this.getFileContent(fileName).slice(pos, end);
} }