Skip to content

Commit f071316

Browse files
committed
Refactor + simplify executable access
Executables access is now handled purely through the RExecutableManager, rather than any member classes
1 parent 70d38b0 commit f071316

File tree

15 files changed

+466
-350
lines changed

15 files changed

+466
-350
lines changed

src/executables/index.ts

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,23 @@ import path = require('path');
22
import * as fs from 'fs-extra';
33
import * as vscode from 'vscode';
44

5-
import { LocatorServiceFactory, AbstractLocatorService } from './locator';
65
import { ExecutableStatusItem, ExecutableQuickPick } from './ui';
7-
import { RExecutableService, WorkspaceExecutableEvent } from './service';
6+
import { isVirtual, RExecutableService, ExecutableType, WorkspaceExecutableEvent } from './service';
87
import { extensionContext } from '../extension';
98
import { spawnAsync } from '../util';
10-
import { RExecutable, VirtualRExecutable } from './executable';
9+
10+
export { ExecutableType as IRExecutable, VirtualExecutableType as IVirtualRExecutable } from './service';
1111

1212
// super class that manages relevant sub classes
13-
export class RExecutableManager {
14-
private retrievalService: AbstractLocatorService;
15-
private statusBar: ExecutableStatusItem;
16-
private quickPick: ExecutableQuickPick;
17-
private executableService: RExecutableService;
13+
export class RExecutableManager implements vscode.Disposable {
14+
private readonly statusBar: ExecutableStatusItem;
15+
private readonly quickPick: ExecutableQuickPick;
16+
private readonly executableService: RExecutableService;
1817

1918
constructor() {
20-
this.retrievalService = LocatorServiceFactory.getLocator();
21-
this.retrievalService.refreshPaths();
2219
this.executableService = new RExecutableService();
2320
this.statusBar = new ExecutableStatusItem(this.executableService);
24-
this.quickPick = new ExecutableQuickPick(this.executableService, this.retrievalService);
21+
this.quickPick = new ExecutableQuickPick(this.executableService);
2522

2623
extensionContext.subscriptions.push(
2724
this.onDidChangeActiveExecutable(() => {
@@ -32,26 +29,35 @@ export class RExecutableManager {
3229
this.reload();
3330
}
3431
}),
35-
this.executableService,
36-
this.statusBar,
37-
this.quickPick
32+
this
3833
);
34+
3935
this.reload();
4036
}
4137

42-
public get activeExecutable(): RExecutable {
43-
return this.executableService.activeExecutable;
38+
public dispose(): void {
39+
this.executableService.dispose();
40+
this.statusBar.dispose();
41+
this.quickPick.dispose();
4442
}
4543

4644
public get executableQuickPick(): ExecutableQuickPick {
4745
return this.quickPick;
4846
}
4947

50-
public get executableStatusItem(): ExecutableStatusItem {
51-
return this.statusBar;
48+
public get activeExecutablePath(): string {
49+
return this.executableService.activeExecutable.rBin;
50+
}
51+
52+
public getExecutablePath(workingDir: string): string {
53+
return this.executableService.getWorkspaceExecutable(workingDir).rBin;
54+
}
55+
56+
public get activeExecutable(): ExecutableType {
57+
return this.executableService.activeExecutable;
5258
}
5359

54-
public get onDidChangeActiveExecutable(): vscode.Event<RExecutable> {
60+
public get onDidChangeActiveExecutable(): vscode.Event<ExecutableType> {
5561
return this.executableService.onDidChangeActiveExecutable;
5662
}
5763

@@ -72,21 +78,23 @@ export class RExecutableManager {
7278
}
7379

7480
private async activateEnvironment(): Promise<unknown> {
81+
if (!isVirtual(this.activeExecutable) ||
82+
process.env.CONDA_DEFAULT_ENV !== this.activeExecutable.name) {
83+
return Promise.resolve();
84+
}
85+
7586
const opts = {
7687
env: {
7788
...process.env
7889
},
7990
};
80-
if (this.activeExecutable instanceof VirtualRExecutable && opts.env.CONDA_DEFAULT_ENV !== this.activeExecutable.name) {
81-
return spawnAsync(
82-
'conda', // hard coded for now
83-
this.activeExecutable.activationCommand,
84-
opts,
85-
undefined
86-
);
87-
} else {
88-
return Promise.resolve();
89-
}
91+
92+
return spawnAsync(
93+
'conda', // hard coded for now
94+
this.activeExecutable.activationCommand,
95+
opts,
96+
undefined
97+
);
9098
}
9199

92100
}
@@ -99,8 +107,7 @@ export class RExecutableManager {
99107
* @param execPath
100108
* @returns boolean
101109
*/
102-
export function validateRFolder(execPath: string): boolean {
110+
export function validateRExecutablePath(execPath: string): boolean {
103111
const basename = process.platform === 'win32' ? 'R.exe' : 'R';
104-
const scriptPath = path.normalize(`${execPath}/../Rcmd`);
105-
return fs.existsSync(execPath) && path.basename(basename) && fs.existsSync(scriptPath);
112+
return fs.existsSync(execPath) && (path.basename(execPath) === basename);
106113
}

src/executables/locator/shared.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/executables/service.ts

Lines changed: 0 additions & 144 deletions
This file was deleted.
Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
import { getRDetailsFromPath } from './locator';
2+
import { RExecutableRegistry } from './registry';
3+
4+
export type ExecutableType = RExecutable;
5+
export type VirtualExecutableType = VirtualRExecutable;
6+
7+
export function isVirtual(executable: RExecutable): executable is VirtualRExecutable {
8+
return executable instanceof VirtualRExecutable;
9+
}
210

311
export class RExecutableFactory {
4-
static createExecutable(executablePath: string): RExecutable {
5-
if (new RegExp('\\.conda').exec(executablePath)?.length > 0) {
6-
return new VirtualRExecutable(executablePath);
7-
} else {
8-
return new RExecutable(executablePath);
9-
}
12+
private readonly registry: RExecutableRegistry;
13+
14+
constructor(registry: RExecutableRegistry) {
15+
this.registry = registry;
1016
}
1117

12-
private constructor() {
13-
//
18+
public create(executablePath: string): ExecutableType {
19+
const oldExec = [...this.registry.executables.values()].find((v) => v.rBin === executablePath);
20+
if (oldExec) {
21+
return oldExec;
22+
} else {
23+
let executable: RExecutable;
24+
if (new RegExp('\\.conda').exec(executablePath)?.length > 0) {
25+
executable = new VirtualRExecutable(executablePath);
26+
} else {
27+
executable = new RExecutable(executablePath);
28+
}
29+
this.registry.addExecutable(executable);
30+
return executable;
31+
}
1432
}
1533
}
1634

17-
export class RExecutable {
35+
class RExecutable {
1836
private _rBin: string;
1937
private _rVersion: string;
2038
private _arch: string;
@@ -45,7 +63,7 @@ export class RExecutable {
4563
}
4664
}
4765

48-
export class VirtualRExecutable extends RExecutable {
66+
class VirtualRExecutable extends RExecutable {
4967
constructor(bin_path: string) {
5068
super(bin_path);
5169
}

0 commit comments

Comments
 (0)