Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 31 additions & 31 deletions src/client/activation/activationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { inject, injectable, multiInject } from 'inversify';
import { TextDocument, workspace } from 'vscode';
import { IApplicationDiagnostics } from '../application/types';
import { IDocumentManager, IWorkspaceService } from '../common/application/types';
import { isTestExecution } from '../common/constants';
import { PYTHON_LANGUAGE } from '../common/constants';
import { traceDecorators } from '../common/logger';
import { IDisposable, Resource } from '../common/types';
import { IInterpreterAutoSelectionService } from '../interpreter/autoSelection/types';
Expand All @@ -26,27 +26,40 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
@inject(IInterpreterAutoSelectionService) private readonly autoSelection: IInterpreterAutoSelectionService,
@inject(IApplicationDiagnostics) private readonly appDiagnostics: IApplicationDiagnostics,
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService
) { }
) {}

public dispose() {
while (this.disposables.length > 0) {
const disposable = this.disposables.shift();
const disposable = this.disposables.shift()!;
disposable.dispose();
}
if (this. docOpenedHandler){
if (this.docOpenedHandler) {
this.docOpenedHandler.dispose();
this.docOpenedHandler = undefined;
}
}
public async activate(): Promise<void> {
await this.initialize();
await this.activateWorkspace(this.getActiveResource());
await this.autoSelection.autoSelectInterpreter(undefined);
}
@traceDecorators.error('Failed to activate a workspace')
public async activateWorkspace(resource: Resource) {
const key = this.getWorkspaceKey(resource);
if (this.activatedWorkspaces.has(key)) {
return;
}
this.activatedWorkspaces.add(key);
// Get latest interpreter list in the background.
this.interpreterService.getInterpreters(resource).ignoreErrors();

await this.autoSelection.autoSelectInterpreter(resource);
await Promise.all(this.activationServices.map(item => item.activate(resource)));
await this.appDiagnostics.performPreStartupHealthCheck(resource);
}
protected async initialize() {
// Get latest interpreter list.
const mainWorkspaceUri = this.getActiveResource();
this.interpreterService.getInterpreters(mainWorkspaceUri).ignoreErrors();
this.addHandlers();
this.addRemoveDocOpenedHandlers();
}
protected addHandlers() {
this.disposables.push(this.workspaceService.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged, this));
Expand All @@ -67,45 +80,32 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
this.addRemoveDocOpenedHandlers();
}
protected hasMultipleWorkspaces() {
return this.workspaceService.hasWorkspaceFolders && this.workspaceService.workspaceFolders.length > 1;
return this.workspaceService.hasWorkspaceFolders && this.workspaceService.workspaceFolders!.length > 1;
}
protected onDocOpened(doc: TextDocument) {
if (doc.languageId !== PYTHON_LANGUAGE) {
return;
}
const key = this.getWorkspaceKey(doc.uri);
// If we have opened a doc that does not belong to workspace, then do nothing.
if (key === '' && this.workspaceService.hasWorkspaceFolders) {
return;
}
if (this.activatedWorkspaces.has(key)) {
return;
}
const folder = this.workspaceService.getWorkspaceFolder(doc.uri);
this.activateWorkspace(folder ? folder.uri : undefined).ignoreErrors();
}
@traceDecorators.error('Failed to activate a worksapce')
protected async activateWorkspace(resource: Resource) {
const key = this.getWorkspaceKey(resource);
this.activatedWorkspaces.add(key);

await Promise.all(this.activationServices.map(item => item.activate(resource)));

// When testing, do not perform health checks, as modal dialogs can be displayed.
if (!isTestExecution()) {
await this.appDiagnostics.performPreStartupHealthCheck(resource);
}
await this.autoSelection.autoSelectInterpreter(resource);
}
protected getWorkspaceKey(resource: Resource) {
if (!resource) {
return '';
}
const workspaceFolder = this.workspaceService.getWorkspaceFolder(resource);
if (!workspaceFolder) {
return '';
}
return workspaceFolder.uri.fsPath;
return this.workspaceService.getWorkspaceFolderIdentifier(resource, '');
}
private getActiveResource(): Resource {
if (this.documentManager.activeTextEditor && !this.documentManager.activeTextEditor.document.isUntitled) {
return this.documentManager.activeTextEditor.document.uri;
}
return Array.isArray(this.workspaceService.workspaceFolders) && workspace.workspaceFolders.length > 0
? workspace.workspaceFolders[0].uri
return Array.isArray(this.workspaceService.workspaceFolders) && workspace.workspaceFolders!.length > 0
? workspace.workspaceFolders![0].uri
: undefined;
}
}
13 changes: 6 additions & 7 deletions src/client/activation/activationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ type ActivatorInfo = { jedi: boolean; activator: ILanguageServerActivator };
@injectable()
export class LanguageServerExtensionActivationService implements IExtensionActivationService, Disposable {
private currentActivator?: ActivatorInfo;
private activatedOnce: boolean;
private activatedOnce: boolean = false;
private readonly workspaceService: IWorkspaceService;
private readonly output: OutputChannel;
private readonly appShell: IApplicationShell;
private readonly lsNotSupportedDiagnosticService: IDiagnosticsService;
private resource!: Resource;

constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
this.workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
Expand All @@ -41,10 +42,11 @@ export class LanguageServerExtensionActivationService implements IExtensionActiv
disposables.push(this.workspaceService.onDidChangeConfiguration(this.onDidChangeConfiguration.bind(this)));
}

public async activate(_resource: Resource): Promise<void> {
public async activate(resource: Resource): Promise<void> {
if (this.currentActivator || this.activatedOnce) {
return;
}
this.resource = resource;
this.activatedOnce = true;

let jedi = this.useJedi();
Expand Down Expand Up @@ -114,10 +116,7 @@ export class LanguageServerExtensionActivationService implements IExtensionActiv
}
}
private useJedi(): boolean {
const workspacesUris: (Uri | undefined)[] = this.workspaceService.hasWorkspaceFolders
? this.workspaceService.workspaceFolders!.map(item => item.uri)
: [undefined];
const configuraionService = this.serviceContainer.get<IConfigurationService>(IConfigurationService);
return workspacesUris.filter(uri => configuraionService.getSettings(uri).jediEnabled).length > 0;
const configurationService = this.serviceContainer.get<IConfigurationService>(IConfigurationService);
return configurationService.getSettings(this.resource).jediEnabled;
}
}
1 change: 1 addition & 0 deletions src/client/activation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { IDisposable, LanguageServerDownloadChannels, Resource } from '../common
export const IExtensionActivationManager = Symbol('IExtensionActivationManager');
export interface IExtensionActivationManager extends IDisposable {
activate(): Promise<void>;
activateWorkspace(resource: Resource): Promise<void>;
}

export const IExtensionActivationService = Symbol('IExtensionActivationService');
Expand Down
6 changes: 5 additions & 1 deletion src/client/application/diagnostics/applicationDiagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { inject, injectable, named } from 'inversify';
import { DiagnosticSeverity } from 'vscode';
import { STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
import { isTestExecution, STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
import { ILogger, IOutputChannel, Resource } from '../../common/types';
import { IServiceContainer } from '../../ioc/types';
import { IApplicationDiagnostics } from '../types';
Expand All @@ -21,6 +21,10 @@ export class ApplicationDiagnostics implements IApplicationDiagnostics {
this.serviceContainer.get<ISourceMapSupportService>(ISourceMapSupportService).register();
}
public async performPreStartupHealthCheck(resource: Resource): Promise<void> {
// When testing, do not perform health checks, as modal dialogs can be displayed.
if (!isTestExecution()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect. Replace if (!isTestExecution()) with if (isTestExecution()).

return;
}
const services = this.serviceContainer.getAll<IDiagnosticsService>(IDiagnosticsService);
// Perform these validation checks in the foreground.
await this.runDiagnostics(services.filter(item => !item.runInBackground), resource);
Expand Down
2 changes: 1 addition & 1 deletion src/client/common/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ export interface IWorkspaceService {
* @returns {string}
* @memberof IWorkspaceService
*/
getWorkspaceFolderIdentifier(resource: Uri | undefined): string;
getWorkspaceFolderIdentifier(resource: Uri | undefined, defaultValue?: string): string;
/**
* Returns a path that is relative to the workspace folder or folders.
*
Expand Down
5 changes: 3 additions & 2 deletions src/client/common/application/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { injectable } from 'inversify';
import { CancellationToken, ConfigurationChangeEvent, Event, FileSystemWatcher, GlobPattern, Uri, workspace, WorkspaceConfiguration, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode';
import { Resource } from '../types';
import { IWorkspaceService } from './types';

@injectable()
Expand Down Expand Up @@ -37,8 +38,8 @@ export class WorkspaceService implements IWorkspaceService {
public findFiles(include: GlobPattern, exclude?: GlobPattern, maxResults?: number, token?: CancellationToken): Thenable<Uri[]> {
return workspace.findFiles(include, exclude, maxResults, token);
}
public getWorkspaceFolderIdentifier(resource: Uri): string {
public getWorkspaceFolderIdentifier(resource: Resource, defaultValue: string = ''): string {
const workspaceFolder = resource ? workspace.getWorkspaceFolder(resource) : undefined;
return workspaceFolder ? workspaceFolder.uri.fsPath : '';
return workspaceFolder ? workspaceFolder.uri.fsPath : defaultValue;
}
}
8 changes: 4 additions & 4 deletions src/client/common/configSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class PythonSettings implements IPythonSettings {
return this.changed.event;
}

constructor(workspaceFolder: Uri | undefined, private readonly InterpreterAutoSelectionService: IInterpreterAutoSeletionProxyService,
constructor(workspaceFolder: Uri | undefined, private readonly interpreterAutoSelectionService: IInterpreterAutoSeletionProxyService,
workspace?: IWorkspaceService) {
this.workspace = workspace || new WorkspaceService();
this.workspaceRoot = workspaceFolder ? workspaceFolder : Uri.file(__dirname);
Expand Down Expand Up @@ -129,9 +129,9 @@ export class PythonSettings implements IPythonSettings {
this.pythonPath = systemVariables.resolveAny(pythonSettings.get<string>('pythonPath'))!;
// If user has defined a custom value, use it else try to get the best interpreter ourselves.
if (this.pythonPath.length === 0 || this.pythonPath === 'python') {
const autoSelectedPythonInterpreter = this.InterpreterAutoSelectionService.getAutoSelectedInterpreter(this.workspaceRoot);
const autoSelectedPythonInterpreter = this.interpreterAutoSelectionService.getAutoSelectedInterpreter(this.workspaceRoot);
if (autoSelectedPythonInterpreter) {
this.InterpreterAutoSelectionService.setWorkspaceInterpreter(this.workspaceRoot, autoSelectedPythonInterpreter).ignoreErrors();
this.interpreterAutoSelectionService.setWorkspaceInterpreter(this.workspaceRoot, autoSelectedPythonInterpreter).ignoreErrors();
}
this.pythonPath = autoSelectedPythonInterpreter ? autoSelectedPythonInterpreter.path : this.pythonPath;
}
Expand Down Expand Up @@ -382,7 +382,7 @@ export class PythonSettings implements IPythonSettings {
// Let's defer the change notification.
this.debounceChangeNotification();
};
this.disposables.push(this.InterpreterAutoSelectionService.onDidChangeAutoSelectedInterpreter(onDidChange.bind(this)));
this.disposables.push(this.interpreterAutoSelectionService.onDidChangeAutoSelectedInterpreter(onDidChange.bind(this)));
this.disposables.push(this.workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => {
if (event.affectsConfiguration('python')) {
onDidChange();
Expand Down
1 change: 1 addition & 0 deletions src/client/common/process/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export type InterpreterInfomation = {
sysVersion: string;
architecture: Architecture;
sysPrefix: string;
pipEnvWorkspaceFolder?: string;
};
export const IPythonExecutionService = Symbol('IPythonExecutionService');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
import { inject, injectable } from 'inversify';
import { Uri } from 'vscode';
import { IInterpreterService, InterpreterType, IPipEnvService } from '../../../interpreter/contracts';
import { IWorkspaceService } from '../../application/types';
import { IFileSystem } from '../../platform/types';
import { ITerminalActivationCommandProvider, TerminalShellType } from '../types';

@injectable()
export class PipEnvActivationCommandProvider implements ITerminalActivationCommandProvider {
constructor(
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
@inject(IPipEnvService) private readonly pipenvService: IPipEnvService
@inject(IPipEnvService) private readonly pipenvService: IPipEnvService,
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,
@inject(IFileSystem) private readonly fs: IFileSystem
) { }

public isShellSupported(_targetShell: TerminalShellType): boolean {
Expand All @@ -24,7 +28,12 @@ export class PipEnvActivationCommandProvider implements ITerminalActivationComma
if (!interpreter || interpreter.type !== InterpreterType.Pipenv) {
return;
}

// Activate using `pipenv shell` only if the current folder relates pipenv environment.
const workspaceFolder = resource ? this.workspaceService.getWorkspaceFolder(resource) : undefined;
if (workspaceFolder && interpreter.pipEnvWorkspaceFolder &&
!this.fs.arePathsSame(workspaceFolder.uri.fsPath, interpreter.pipEnvWorkspaceFolder)) {
return;
}
const execName = this.pipenvService.executable;
return [`${execName.fileToCommandArgument()} shell`];
}
Expand Down
Loading