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
16 changes: 8 additions & 8 deletions crates/oxc_language_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,15 +543,15 @@ impl Backend {
let Ok(root_path) = uri.to_file_path() else {
return None;
};
let mut config_path = None;
let config = root_path.join(self.options.lock().await.get_config_path().unwrap());
if config.exists() {
config_path = Some(config);
}
let relative_config_path = self.options.lock().await.get_config_path();
let oxlintrc = if relative_config_path.is_some() {
let config = root_path.join(relative_config_path.unwrap());
config.try_exists().expect("Invalid config file path");
Oxlintrc::from_file(&config).expect("Failed to initialize oxlintrc config")
} else {
Oxlintrc::default()
};

let config_path = config_path?;
let oxlintrc = Oxlintrc::from_file(&config_path)
.expect("should have initialized linter with new options");
let config_store = ConfigStoreBuilder::from_oxlintrc(true, oxlintrc.clone())
.expect("failed to build config")
.build()
Expand Down
19 changes: 18 additions & 1 deletion editors/vscode/client/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ export class Config implements ConfigInterface {
private _trace!: TraceLevel;
private _configPath!: string;
private _binPath: string | undefined;
private _flags!: Record<string, string>;

constructor() {
this.refresh();
}

public refresh(): void {
const conf = workspace.getConfiguration(Config._namespace);
const flags = conf.get<Record<string, string>>('flags') ?? {};
const useNestedConfigs = !('disable_nested_config' in flags);

this._runTrigger = conf.get<Trigger>('lint.run') || 'onType';
this._enable = conf.get<boolean>('enable') ?? true;
this._trace = conf.get<TraceLevel>('trace.server') || 'off';
this._configPath = conf.get<string>('configPath') || oxlintConfigFileName;
this._configPath = conf.get<string>('configPath') || (useNestedConfigs ? '' : oxlintConfigFileName);
this._binPath = conf.get<string>('path.server');
this._flags = flags;
}

get runTrigger(): Trigger {
Expand Down Expand Up @@ -80,11 +84,23 @@ export class Config implements ConfigInterface {
.update('path.server', value);
}

get flags(): Record<string, string> {
return this._flags;
}

updateFlags(value: Record<string, string>): PromiseLike<void> {
this._flags = value;
return workspace
.getConfiguration(Config._namespace)
.update('flags', value);
}

public toLanguageServerConfig(): LanguageServerConfig {
return {
run: this.runTrigger,
enable: this.enable,
configPath: this.configPath,
flags: this.flags,
};
}
}
Expand All @@ -93,6 +109,7 @@ interface LanguageServerConfig {
configPath: string;
enable: boolean;
run: Trigger;
flags: Record<string, string>;
}

export type Trigger = 'onSave' | 'onType';
Expand Down
29 changes: 27 additions & 2 deletions editors/vscode/client/config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { strictEqual } from 'assert';
import { deepStrictEqual, strictEqual } from 'assert';
import { workspace } from 'vscode';
import { Config } from './Config.js';

suite('Config', () => {
setup(async () => {
const wsConfig = workspace.getConfiguration('oxc');
const keys = ['lint.run', 'enable', 'trace.server', 'configPath', 'path.server'];
const keys = ['lint.run', 'enable', 'trace.server', 'configPath', 'path.server', 'flags'];

await Promise.all(keys.map(key => wsConfig.update(key, undefined)));
});
Expand All @@ -18,6 +18,29 @@ suite('Config', () => {
strictEqual(config.trace, 'off');
strictEqual(config.configPath, '.oxlintrc.json');
strictEqual(config.binPath, '');
deepStrictEqual(config.flags, {});
});

test('configPath defaults to empty string when using nested configs and configPath is empty', async () => {
const wsConfig = workspace.getConfiguration('oxc');
await wsConfig.update('configPath', '');
await wsConfig.update('flags', {});

const config = new Config();

deepStrictEqual(config.flags, {});
strictEqual(config.configPath, '');
});

test('configPath defaults to .oxlintrc.json when not using nested configs and configPath is empty', async () => {
const wsConfig = workspace.getConfiguration('oxc');
await wsConfig.update('configPath', '');
await wsConfig.update('flags', { disable_nested_config: '' });

const config = new Config();

deepStrictEqual(config.flags, { disable_nested_config: '' });
strictEqual(config.configPath, '.oxlintrc.json');
});

test('updating values updates the workspace configuration', async () => {
Expand All @@ -29,6 +52,7 @@ suite('Config', () => {
config.updateTrace('messages'),
config.updateConfigPath('./somewhere'),
config.updateBinPath('./binary'),
config.updateFlags({ test: 'value' }),
]);

const wsConfig = workspace.getConfiguration('oxc');
Expand All @@ -38,5 +62,6 @@ suite('Config', () => {
strictEqual(wsConfig.get('trace.server'), 'messages');
strictEqual(wsConfig.get('configPath'), './somewhere');
strictEqual(wsConfig.get('path.server'), './binary');
deepStrictEqual(wsConfig.get('flags'), { test: 'value' });
});
});
31 changes: 28 additions & 3 deletions editors/vscode/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ import {
StatusBarAlignment,
StatusBarItem,
ThemeColor,
Uri,
window,
workspace,
} from 'vscode';

import { ExecuteCommandRequest, MessageType, ShowMessageNotification } from 'vscode-languageclient';
import {
DidChangeWatchedFilesNotification,
ExecuteCommandRequest,
FileChangeType,
MessageType,
ShowMessageNotification,
} from 'vscode-languageclient';

import { Executable, LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';

Expand Down Expand Up @@ -231,7 +238,10 @@ export async function activate(context: ExtensionContext) {
if (event.affectsConfiguration('oxc.configPath')) {
client.clientOptions.synchronize = client.clientOptions.synchronize ?? {};
client.clientOptions.synchronize.fileEvents = createFileEventWatchers(configService.config.configPath);
client.restart();
client.restart().then(async () => {
const configFiles = await findOxlintrcConfigFiles();
await sendDidChangeWatchedFilesNotificationWith(client, configFiles);
});
}
};

Expand All @@ -255,7 +265,10 @@ export async function activate(context: ExtensionContext) {
myStatusBarItem.backgroundColor = bgColor;
}
updateStatsBar(configService.config.enable);
client.start();
await client.start();

const configFiles = await findOxlintrcConfigFiles();
await sendDidChangeWatchedFilesNotificationWith(client, configFiles);
}

export function deactivate(): Thenable<void> | undefined {
Expand All @@ -277,3 +290,15 @@ function createFileEventWatchers(configRelativePath: string) {
}),
];
}

async function findOxlintrcConfigFiles() {
return workspace.findFiles(`**/${oxlintConfigFileName}`);
}

async function sendDidChangeWatchedFilesNotificationWith(languageClient: LanguageClient, files: Uri[]) {
await languageClient.sendNotification(DidChangeWatchedFilesNotification.type, {
changes: files.map(file => {
return { uri: file.toString(), type: FileChangeType.Created };
}),
});
}
6 changes: 6 additions & 0 deletions editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@
"type": "string",
"scope": "window",
"description": "Path to Oxc language server binary."
},
"oxc.flags": {
"type": "object",
"scope": "window",
"default": {},
"description": "Oxc options that would normally be passed when executing on the command line."
}
}
},
Expand Down
Loading