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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ignorePatterns": [
"ignored_dir"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
debugger;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ignorePatterns": [
"ignored_dir"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
debugger;
13 changes: 12 additions & 1 deletion apps/oxlint/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ impl LintRunner {
} else {
None
};
let config_builder = match ConfigStoreBuilder::from_oxlintrc(
let config_builder = match ConfigStoreBuilder::from_base_oxlintrc(
&self.cwd,
false,
oxlintrc,
external_linter,
Expand Down Expand Up @@ -667,6 +668,16 @@ mod test {
.test_and_snapshot_multiple(&[args1, args2]);
}

#[test]
// https://github.com/oxc-project/oxc/issues/13204
fn ignore_pattern_non_glob_syntax() {
let args1 = &[];
let args2 = &["."];
Tester::new()
.with_cwd("fixtures/ignore_pattern_non_glob_syntax".into())
.test_and_snapshot_multiple(&[args1, args2]);
}

#[test]
fn filter_allow_all() {
let args = &["-A", "all", "fixtures/linter"];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: apps/oxlint/src/tester.rs
---
##########
arguments:
working directory: fixtures/ignore_pattern_non_glob_syntax
----------
Found 0 warnings and 0 errors.
Finished in <variable>ms on 0 files using 1 threads.
----------
CLI result: LintSucceeded
----------

##########
arguments: .
working directory: fixtures/ignore_pattern_non_glob_syntax
----------
Found 0 warnings and 0 errors.
Finished in <variable>ms on 0 files using 1 threads.
----------
CLI result: LintSucceeded
----------
3 changes: 2 additions & 1 deletion crates/oxc_language_server/src/linter/server_linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ impl ServerLinter {
Oxlintrc::default()
};

let config_builder = ConfigStoreBuilder::from_oxlintrc(
let config_builder = ConfigStoreBuilder::from_base_oxlintrc(
&root_path,
false,
oxlintrc,
None,
Expand Down
46 changes: 44 additions & 2 deletions crates/oxc_linter/src/config/config_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,49 @@ impl ConfigStoreBuilder {
oxlintrc: Oxlintrc,
external_linter: Option<&ExternalLinter>,
external_plugin_store: &mut ExternalPluginStore,
) -> Result<Self, ConfigBuilderError> {
let parent_path =
oxlintrc.path.parent().map_or_else(|| PathBuf::from("."), std::path::Path::to_path_buf);

Self::from_oxlintrc_with_ignore_root(
start_empty,
oxlintrc,
external_linter,
external_plugin_store,
parent_path.as_path(),
)
}

/// Similar to the [`ConfigStoreBuilder::from_oxlintrc`] method, but
/// applies the config on top of a default [`Oxlintrc`].
/// The ignore root of this file, should be the current working directory.
/// Even if the file is not located at the current working directory.
///
/// # Errors
///
/// Returns [`ConfigBuilderError::InvalidConfigFile`] if a referenced config file is not valid.
pub fn from_base_oxlintrc(
cwd: &Path,
start_empty: bool,
oxlintrc: Oxlintrc,
external_linter: Option<&ExternalLinter>,
external_plugin_store: &mut ExternalPluginStore,
) -> Result<Self, ConfigBuilderError> {
Self::from_oxlintrc_with_ignore_root(
start_empty,
oxlintrc,
external_linter,
external_plugin_store,
cwd,
)
}

fn from_oxlintrc_with_ignore_root(
start_empty: bool,
oxlintrc: Oxlintrc,
external_linter: Option<&ExternalLinter>,
external_plugin_store: &mut ExternalPluginStore,
ignore_root: &Path,
) -> Result<Self, ConfigBuilderError> {
// TODO: this can be cached to avoid re-computing the same oxlintrc
fn resolve_oxlintrc_config(
Expand Down Expand Up @@ -167,7 +210,6 @@ impl ConfigStoreBuilder {

let resolver = Resolver::default();

#[expect(clippy::missing_panics_doc, reason = "oxlintrc.path is always a file path")]
let oxlintrc_dir = oxlintrc.path.parent().unwrap();

for plugin_specifier in &external_plugins {
Expand Down Expand Up @@ -201,7 +243,7 @@ impl ConfigStoreBuilder {
globals: oxlintrc.globals,
ignore_patterns: LintConfig::resolve_oxlintrc_ignore_patterns(
&oxlintrc.ignore_patterns,
&oxlintrc.path,
ignore_root,
),
path: Some(oxlintrc.path),
};
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/src/config/config_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,9 @@ impl ConfigStore {
}

pub fn should_ignore(&self, path: &Path) -> bool {
self.get_related_config(path)
.ignore_patterns()
.is_some_and(|ignore_patterns| ignore_patterns.matched(path, false).is_ignore())
self.get_related_config(path).ignore_patterns().is_some_and(|ignore_patterns| {
ignore_patterns.matched_path_or_any_parents(path, false).is_ignore()
})
}

// NOTE: This function is not crate visible because it is used in `oxlint` as well to resolve configs
Expand Down
16 changes: 6 additions & 10 deletions crates/oxc_linter/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ pub use config_builder::{ConfigBuilderError, ConfigStoreBuilder};
pub use config_store::{Config, ConfigStore, ResolvedLinterState};
pub use env::OxlintEnv;
pub use globals::{GlobalValue, OxlintGlobals};
use ignore::overrides::OverrideBuilder;
use ignore::gitignore::{Gitignore, GitignoreBuilder};
pub use overrides::OxlintOverrides;
pub use oxlintrc::Oxlintrc;
pub use plugins::{BuiltinLintPlugins, LintPlugins};
pub use rules::{ESLintRule, OxlintRules};
pub use settings::{OxlintSettings, jsdoc::JSDocPluginSettings};

pub type ResolvedIgnorePatterns = ignore::overrides::Override;
pub type ResolvedIgnorePatterns = Gitignore;

#[derive(Debug, Default, Clone)]
pub struct LintConfig {
Expand Down Expand Up @@ -53,23 +53,19 @@ impl From<Oxlintrc> for LintConfig {
impl LintConfig {
pub(crate) fn resolve_oxlintrc_ignore_patterns(
ignore_patterns: &[String],
config_path: &Path,
ignore_root: &Path,
) -> Option<ResolvedIgnorePatterns> {
if ignore_patterns.is_empty() {
return None;
}
// expect that every oxlint config file with "ignorePatterns" provides its config path with parent.
// for the default config the path is empty, but there should be no ignore patterns
let oxlint_wd = config_path.parent()?.to_path_buf();

let mut builder = OverrideBuilder::new(&oxlint_wd);
let mut gitignore_builder = GitignoreBuilder::new(ignore_root);

for pattern in ignore_patterns {
let pattern = format!("!{pattern}");
builder.add(&pattern).unwrap();
gitignore_builder.add_line(None, pattern).unwrap();
}

builder.build().ok()
gitignore_builder.build().ok()
}
}

Expand Down
Loading