Skip to content

Commit f36ee36

Browse files
authored
feat(extension): support resovle bin path from user land (#179)
1 parent 784c8f4 commit f36ee36

File tree

9 files changed

+546
-85
lines changed

9 files changed

+546
-85
lines changed

.vscode/settings.template.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
},
1515
"cSpell.words": [
1616
"rslint"
17-
]
17+
],
18+
"typescript.tsdk": "node_modules/typescript/lib"
1819
}

packages/vscode-extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"engines": {
2323
"vscode": "^1.74.0"
2424
},
25-
"main": "./dist/extension.js",
25+
"main": "./dist/main.js",
2626
"activationEvents": [
2727
"onLanguage:typescript",
2828
"onLanguage:typescriptreact",

packages/vscode-extension/scripts/build.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const fs = require('fs');
44
const isWatchMode = process.argv.includes('--watch');
55

66
const config = {
7-
entryPoints: ['src/extension.ts'],
8-
outfile: 'dist/extension.js',
7+
entryPoints: ['src/main.ts'],
8+
outfile: 'dist/main.js',
99
format: 'cjs',
1010
bundle: true,
1111

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import {
2+
ExtensionContext,
3+
Disposable,
4+
workspace,
5+
WorkspaceFolder,
6+
ExtensionMode,
7+
} from 'vscode';
8+
import { State } from 'vscode-languageclient/node';
9+
import { LogLevel, Logger } from './logger';
10+
import { Rslint } from './Rslint';
11+
12+
export class Extension implements Disposable {
13+
private rslintInstances: Map<string, Rslint> = new Map();
14+
private disposables: Disposable[] = [];
15+
private logger: Logger;
16+
public context: ExtensionContext;
17+
18+
constructor(context: ExtensionContext) {
19+
Logger.setDefaultLogLevel(context);
20+
this.context = context;
21+
this.logger = new Logger('Rslint (extension)').useDefaultLogLevel();
22+
}
23+
24+
public async activate(): Promise<void> {
25+
this.logger.info('Rslint extension activating...');
26+
27+
const folders = workspace.workspaceFolders ?? [];
28+
for (const folder of folders) {
29+
const workspaceRslint = this.createRslintInstance(folder.name, folder);
30+
await workspaceRslint.start();
31+
this.setupStateChangeMonitoring(workspaceRslint, folder.name);
32+
}
33+
34+
this.logger.info('Rslint extension activated successfully');
35+
}
36+
37+
public async deactivate(): Promise<void> {
38+
this.logger.info('Rslint extension deactivating...');
39+
40+
const stopPromises = Array.from(this.rslintInstances.values()).map(
41+
instance => instance.stop(),
42+
);
43+
44+
try {
45+
await Promise.all(stopPromises);
46+
this.logger.info('All Rslint instances stopped');
47+
} catch (err: unknown) {
48+
this.logger.error('Error stopping some Rslint instances', err);
49+
}
50+
51+
this.dispose();
52+
this.logger.info('Rslint extension deactivated');
53+
}
54+
55+
public createRslintInstance(
56+
id: string,
57+
workspaceFolder: WorkspaceFolder,
58+
): Rslint {
59+
if (this.rslintInstances.has(id)) {
60+
this.logger.warn(`Rslint instance with id '${id}' already exists`);
61+
return this.rslintInstances.get(id)!;
62+
}
63+
64+
// TODO: single file mode
65+
const rslint = new Rslint(this, workspaceFolder);
66+
this.rslintInstances.set(id, rslint);
67+
this.logger.debug(`Created Rslint instance with id: ${id}`);
68+
return rslint;
69+
}
70+
71+
public getRslintInstance(id: string): Rslint | undefined {
72+
return this.rslintInstances.get(id);
73+
}
74+
75+
public async removeRslintInstance(id: string): Promise<void> {
76+
const instance = this.rslintInstances.get(id);
77+
if (!instance) {
78+
this.logger.warn(`Rslint instance with id '${id}' not found`);
79+
return;
80+
}
81+
82+
await instance.stop();
83+
instance.dispose();
84+
this.rslintInstances.delete(id);
85+
86+
this.logger.debug(`Removed Rslint instance with id: ${id}`);
87+
}
88+
89+
public getAllRslintInstances(): Map<string, Rslint> {
90+
return new Map(this.rslintInstances);
91+
}
92+
93+
public dispose(): void {
94+
this.rslintInstances.forEach(instance => {
95+
instance.dispose();
96+
});
97+
this.rslintInstances.clear();
98+
99+
this.disposables.forEach(disposable => {
100+
disposable.dispose();
101+
});
102+
this.disposables = [];
103+
104+
this.logger.dispose();
105+
}
106+
107+
private setupLogging(): void {
108+
this.logger.setLogLevel(
109+
this.context.extensionMode === ExtensionMode.Development
110+
? LogLevel.DEBUG
111+
: LogLevel.INFO,
112+
);
113+
}
114+
115+
private setupStateChangeMonitoring(rslint: Rslint, instanceId: string): void {
116+
const stateChangeDisposable = rslint.onDidChangeState(event => {
117+
this.logger.debug(
118+
`Rslint client state changed for instance '${instanceId}':`,
119+
event.oldState,
120+
'->',
121+
event.newState,
122+
);
123+
124+
if (event.newState === State.Running) {
125+
this.logger.info(
126+
`Rslint language server started for instance '${instanceId}'`,
127+
);
128+
} else if (event.newState === State.Stopped) {
129+
this.logger.info(
130+
`Rslint language server stopped for instance '${instanceId}'`,
131+
);
132+
}
133+
});
134+
135+
this.disposables.push(stateChangeDisposable);
136+
this.context.subscriptions.push(stateChangeDisposable);
137+
}
138+
}

0 commit comments

Comments
 (0)