Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(language_server): auto detect oxlint config #7256

Closed
57 changes: 44 additions & 13 deletions crates/oxc_language_server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
mod linter;

use std::{fmt::Debug, path::PathBuf, str::FromStr};

use dashmap::DashMap;
use futures::future::join_all;
use globset::Glob;
use ignore::gitignore::Gitignore;
use log::{debug, error, info};
use log::{debug, error, info, warn};
use oxc_linter::{FixKind, LinterBuilder, Oxlintrc};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::{fmt::Debug, str::FromStr};
use tokio::sync::{Mutex, OnceCell, RwLock, SetError};
use tower_lsp::{
jsonrpc::{Error, ErrorCode, Result},
Expand Down Expand Up @@ -47,12 +47,12 @@ enum Run {
struct Options {
run: Run,
enable: bool,
config_path: String,
config_path: Option<String>,
}

impl Default for Options {
fn default() -> Self {
Self { enable: true, run: Run::default(), config_path: ".eslintrc".into() }
Self { enable: true, run: Run::default(), config_path: None }
}
}

Expand All @@ -68,11 +68,44 @@ impl Options {
}
}

fn get_config_path(&self) -> Option<PathBuf> {
if self.config_path.is_empty() {
fn get_config_path(&self, root_path: &Path) -> Option<PathBuf> {
let Some(config_path) = &self.config_path else {
// no config file is provided, let search in the root_path for one
let search_configs = vec![
"oxlintrc.json",
"oxlint.json",
".oxlintrc.json",
".oxlint.json",
".oxlintrc",
".eslintrc",
Sysix marked this conversation as resolved.
Show resolved Hide resolved
".eslintrc.json",
];

for search_config in search_configs {
let config_path = root_path.join(search_config);

if config_path.exists() {
Sysix marked this conversation as resolved.
Show resolved Hide resolved
info!("Automatically detected config {config_path:?}");
return Some(config_path);
}
}

return None;
};

// config path is provided and is empty, e.g "oxc.configPath": ""
if config_path.is_empty() {
None
} else {
Some(PathBuf::from(&self.config_path))
// provided config path is not empty
let config_path = root_path.join(config_path);

if config_path.exists() {
return Some(config_path);
}

warn!("could not find oxlint config file {:?}", config_path);
None
Sysix marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down Expand Up @@ -362,11 +395,9 @@ impl Backend {
let Ok(root_path) = uri.to_file_path() else {
return;
};
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 config_path = self.options.lock().await.get_config_path(&root_path);

if let Some(config_path) = config_path {
let mut linter = self.server_linter.write().await;
*linter = ServerLinter::new_with_linter(
Expand Down
14 changes: 7 additions & 7 deletions editors/vscode/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class ConfigService implements Config, IDisposable {
private _runTrigger!: Trigger;
private _enable!: boolean;
private _trace!: TraceLevel;
private _configPath!: string;
private _configPath!: string | undefined;
private _binPath: string | undefined;

public onConfigChange:
Expand All @@ -31,7 +31,7 @@ export class ConfigService implements Config, IDisposable {
this._runTrigger = this._inner.get<Trigger>('lint.run') || 'onType';
this._enable = this._inner.get<boolean>('enable') ?? true;
this._trace = this._inner.get<TraceLevel>('trace.server') || 'off';
this._configPath = this._inner.get<string>('configPath') || '.eslintrc';
this._configPath = this._inner.get<string>('configPath');
this._binPath = this._inner.get<string>('path.server');
}

Expand Down Expand Up @@ -68,11 +68,11 @@ export class ConfigService implements Config, IDisposable {
.update('trace.server', value);
}

get configPath(): string {
get configPath(): string | undefined {
return this._configPath;
}

set configPath(value: string) {
set configPath(value: string | undefined) {
this._configPath = value;
workspace
.getConfiguration(ConfigService._namespace)
Expand Down Expand Up @@ -116,7 +116,7 @@ type Trigger = 'onSave' | 'onType';
type TraceLevel = 'off' | 'messages' | 'verbose';

interface LanguageServerConfig {
configPath: string;
configPath: string | undefined;
enable: boolean;
run: Trigger;
}
Expand Down Expand Up @@ -150,9 +150,9 @@ interface Config {
*
* `oxc.configPath`
*
* @default ".eslintrc"
* @default undefined
*/
configPath: string;
configPath: string | undefined;
/**
* Path to LSP binary
* `oxc.path.server`
Expand Down
6 changes: 3 additions & 3 deletions editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@
"description": "Traces the communication between VS Code and the language server."
},
"oxc.configPath": {
"type": "string",
"type": ["string", "null"],
"scope": "window",
"default": ".eslintrc",
"description": "Path to ESlint configuration."
"default": null,
"description": "Path to oxlint configuration."
},
"oxc.path.server": {
"type": "string",
Expand Down
Loading