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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 7 additions & 12 deletions apps/oxlint/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use cow_utils::CowUtils;
use ignore::{gitignore::Gitignore, overrides::OverrideBuilder};
use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler, OxcDiagnostic};
use oxc_linter::{
AllowWarnDeny, ConfigStore, ConfigStoreBuilder, InvalidFilterKind, LintFilter, LintOptions,
LintService, LintServiceOptions, Linter, Oxlintrc,
AllowWarnDeny, Config, ConfigStore, ConfigStoreBuilder, InvalidFilterKind, LintFilter,
LintOptions, LintService, LintServiceOptions, Linter, Oxlintrc,
};
use rustc_hash::{FxHashMap, FxHashSet};
use serde_json::Value;
Expand Down Expand Up @@ -269,15 +269,10 @@ impl Runner for LintRunner {
_ => None,
};

let linter = if nested_configs.is_empty() {
Linter::new(LintOptions::default(), lint_config)
let linter =
Linter::new(LintOptions::default(), ConfigStore::new(lint_config, nested_configs))
.with_fix(fix_options.fix_kind())
.with_report_unused_directives(report_unused_directives)
} else {
Linter::new_with_nested_configs(LintOptions::default(), lint_config, nested_configs)
.with_fix(fix_options.fix_kind())
.with_report_unused_directives(report_unused_directives)
};
.with_report_unused_directives(report_unused_directives);

let tsconfig = basic_options.tsconfig;
if let Some(path) = tsconfig.as_ref() {
Expand Down Expand Up @@ -400,11 +395,11 @@ impl LintRunner {
handler: &GraphicalReportHandler,
filters: &Vec<LintFilter>,
paths: &Vec<Arc<OsStr>>,
) -> Result<FxHashMap<PathBuf, ConfigStore>, CliRunResult> {
) -> Result<FxHashMap<PathBuf, Config>, CliRunResult> {
// TODO(perf): benchmark whether or not it is worth it to store the configurations on a
// per-file or per-directory basis, to avoid calling `.parent()` on every path.
let mut nested_oxlintrc = FxHashMap::<&Path, Oxlintrc>::default();
let mut nested_configs = FxHashMap::<PathBuf, ConfigStore>::default();
let mut nested_configs = FxHashMap::<PathBuf, Config>::default();
// get all of the unique directories among the paths to use for search for
// oxlint config files in those directories and their ancestors
// e.g. `/some/file.js` will check `/some` and `/`
Expand Down
29 changes: 16 additions & 13 deletions crates/oxc_language_server/src/linter/server_linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use log::{debug, warn};
use rustc_hash::{FxBuildHasher, FxHashMap};
use tower_lsp_server::lsp_types::Uri;

use oxc_linter::{ConfigStore, ConfigStoreBuilder, LintOptions, Linter, Oxlintrc};
use oxc_linter::{Config, ConfigStore, ConfigStoreBuilder, LintOptions, Linter, Oxlintrc};
use tower_lsp_server::UriExt;

use crate::linter::{
Expand Down Expand Up @@ -61,21 +61,24 @@ impl ServerLinter {
config_builder.plugins().has_import()
};

let config_store = config_builder.build().expect("Failed to build config store");
let base_config = config_builder.build().expect("Failed to build config store");

let lint_options = LintOptions { fix: options.fix_kind(), ..Default::default() };

let linter = if use_nested_config {
let nested_configs = nested_configs.pin();
let nested_configs_copy: FxHashMap<PathBuf, ConfigStore> = nested_configs
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect::<FxHashMap<_, _>>();
let config_store = ConfigStore::new(
base_config,
if use_nested_config {
let nested_configs = nested_configs.pin();
nested_configs
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect::<FxHashMap<_, _>>()
} else {
FxHashMap::default()
},
);

Linter::new_with_nested_configs(lint_options, config_store, nested_configs_copy)
} else {
Linter::new(lint_options, config_store)
};
let linter = Linter::new(lint_options, config_store);

let isolated_linter = IsolatedLintHandler::new(
linter,
Expand All @@ -93,7 +96,7 @@ impl ServerLinter {
fn create_nested_configs(
root_uri: &Uri,
options: &Options,
) -> ConcurrentHashMap<PathBuf, ConfigStore> {
) -> ConcurrentHashMap<PathBuf, Config> {
// nested config is disabled, no need to search for configs
if !options.use_nested_configs() {
return ConcurrentHashMap::default();
Expand Down
22 changes: 11 additions & 11 deletions crates/oxc_linter/src/config/config_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ use oxc_span::{CompactStr, format_compact_str};
use crate::{
AllowWarnDeny, LintConfig, LintFilter, LintFilterKind, Oxlintrc, RuleCategory, RuleEnum,
RuleWithSeverity,
config::{
ConfigStore, ESLintRule, LintPlugins, OxlintOverrides, OxlintRules,
overrides::OxlintOverride,
},
config::{ESLintRule, LintPlugins, OxlintOverrides, OxlintRules, overrides::OxlintOverride},
rules::RULES,
};

use super::Config;

#[must_use = "You dropped your builder without building a Linter! Did you mean to call .build()?"]
pub struct ConfigStoreBuilder {
pub(super) rules: FxHashSet<RuleWithSeverity>,
Expand Down Expand Up @@ -72,7 +71,7 @@ impl ConfigStoreBuilder {
/// will be applied on top of a default [`Oxlintrc`].
///
/// # Example
/// Here's how to create a [`ConfigStore`] from a `.oxlintrc.json` file.
/// Here's how to create a [`Config`] from a `.oxlintrc.json` file.
/// ```ignore
/// use oxc_linter::{ConfigBuilder, Oxlintrc};
/// let oxlintrc = Oxlintrc::from_file("path/to/.oxlintrc.json").unwrap();
Expand Down Expand Up @@ -301,7 +300,7 @@ impl ConfigStoreBuilder {
}

/// # Errors
pub fn build(self) -> Result<ConfigStore, OxcDiagnostic> {
pub fn build(self) -> Result<Config, OxcDiagnostic> {
// When a plugin gets disabled before build(), rules for that plugin aren't removed until
// with_filters() gets called. If the user never calls it, those now-undesired rules need
// to be taken out.
Expand All @@ -312,7 +311,8 @@ impl ConfigStoreBuilder {
self.rules.into_iter().collect::<Vec<_>>()
};
rules.sort_unstable_by_key(|r| r.id());
Ok(ConfigStore::new(rules, self.config, self.overrides))

Ok(Config::new(rules, self.config, self.overrides))
}

/// Warn for all correctness rules in the given set of plugins.
Expand Down Expand Up @@ -386,7 +386,7 @@ impl Debug for ConfigStoreBuilder {
}
}

/// An error that can occur while building a [`ConfigStore`] from an [`Oxlintrc`].
/// An error that can occur while building a [`Config`] from an [`Oxlintrc`].
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum ConfigBuilderError {
/// There were unknown rules that could not be matched to any known plugins/rules.
Expand Down Expand Up @@ -656,7 +656,7 @@ mod test {
desired_plugins.set(LintPlugins::TYPESCRIPT, false);

let linter = ConfigStoreBuilder::default().with_plugins(desired_plugins).build().unwrap();
for rule in linter.rules().iter() {
for rule in linter.base.rules.iter() {
let name = rule.name();
let plugin = rule.plugin_name();
assert_ne!(
Expand Down Expand Up @@ -1030,14 +1030,14 @@ mod test {
assert!(config.rules().is_empty());
}

fn config_store_from_path(path: &str) -> ConfigStore {
fn config_store_from_path(path: &str) -> Config {
ConfigStoreBuilder::from_oxlintrc(true, Oxlintrc::from_file(&PathBuf::from(path)).unwrap())
.unwrap()
.build()
.unwrap()
}

fn config_store_from_str(s: &str) -> ConfigStore {
fn config_store_from_str(s: &str) -> Config {
ConfigStoreBuilder::from_oxlintrc(true, serde_json::from_str(s).unwrap())
.unwrap()
.build()
Expand Down
Loading
Loading