Skip to content

Commit 1628aab

Browse files
bumahkib7claude
andcommitted
fix: enable Oxc provider by default for JS/TS analysis
The native Oxc provider (Rust-based JS/TS linting with 520+ rules) was added but not enabled in the default providers list. Changes: - Add ProviderType::Oxc to default_enabled_providers() - Update config template to show new default: ["rma", "oxc"] Oxc is a built-in provider with no external dependencies, so it should run by default for all JavaScript/TypeScript files. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent ac2efa6 commit 1628aab

File tree

1 file changed

+132
-5
lines changed

1 file changed

+132
-5
lines changed

crates/common/src/config.rs

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,9 @@ impl Default for ProvidersConfig {
438438
}
439439

440440
fn default_enabled_providers() -> Vec<ProviderType> {
441-
vec![ProviderType::Rma]
441+
// Rma: built-in rules for all languages
442+
// Oxc: native JS/TS linting (no external binary required)
443+
vec![ProviderType::Rma, ProviderType::Oxc]
442444
}
443445

444446
/// PMD Java provider configuration
@@ -768,6 +770,77 @@ fn default_baseline_file() -> PathBuf {
768770
PathBuf::from(".rma/baseline.json")
769771
}
770772

773+
// =============================================================================
774+
// SUPPRESSION DATABASE CONFIGURATION
775+
// =============================================================================
776+
777+
/// Configuration for the suppression database
778+
#[derive(Debug, Clone, Serialize, Deserialize)]
779+
pub struct SuppressionConfig {
780+
/// Path to the suppression database (relative to project root)
781+
#[serde(default = "default_suppression_database")]
782+
pub database: PathBuf,
783+
784+
/// Default expiration period for new suppressions (e.g., "90d", "30d", "7d")
785+
#[serde(default = "default_expiration")]
786+
pub default_expiration: String,
787+
788+
/// Whether a ticket reference is required for new suppressions
789+
#[serde(default)]
790+
pub require_ticket: bool,
791+
792+
/// Maximum expiration period allowed (e.g., "365d")
793+
#[serde(default = "default_max_expiration")]
794+
pub max_expiration: String,
795+
796+
/// Whether to enable the database suppression source
797+
#[serde(default = "default_enabled")]
798+
pub enabled: bool,
799+
}
800+
801+
impl Default for SuppressionConfig {
802+
fn default() -> Self {
803+
Self {
804+
database: default_suppression_database(),
805+
default_expiration: default_expiration(),
806+
require_ticket: false,
807+
max_expiration: default_max_expiration(),
808+
enabled: true,
809+
}
810+
}
811+
}
812+
813+
fn default_suppression_database() -> PathBuf {
814+
PathBuf::from(".rma/suppressions.db")
815+
}
816+
817+
fn default_expiration() -> String {
818+
"90d".to_string()
819+
}
820+
821+
fn default_max_expiration() -> String {
822+
"365d".to_string()
823+
}
824+
825+
fn default_enabled() -> bool {
826+
true
827+
}
828+
829+
/// Parse a duration string (e.g., "90d", "30d", "7d") to days
830+
pub fn parse_expiration_days(s: &str) -> Option<u32> {
831+
let s = s.trim().to_lowercase();
832+
if let Some(days_str) = s.strip_suffix('d') {
833+
days_str.parse().ok()
834+
} else if let Some(weeks_str) = s.strip_suffix('w') {
835+
weeks_str.parse::<u32>().ok().map(|w| w * 7)
836+
} else if let Some(months_str) = s.strip_suffix('m') {
837+
months_str.parse::<u32>().ok().map(|m| m * 30)
838+
} else {
839+
// Try parsing as plain number (days)
840+
s.parse().ok()
841+
}
842+
}
843+
771844
/// Current supported config version
772845
pub const CURRENT_CONFIG_VERSION: u32 = 1;
773846

@@ -813,6 +886,10 @@ pub struct RmaTomlConfig {
813886
/// Analysis providers configuration
814887
#[serde(default)]
815888
pub providers: ProvidersConfig,
889+
890+
/// Suppression database configuration
891+
#[serde(default)]
892+
pub suppressions: SuppressionConfig,
816893
}
817894

818895
/// Result of loading a config file
@@ -1294,10 +1371,11 @@ mode = "all"
12941371
# Providers can be enabled/disabled individually.
12951372
12961373
[providers]
1297-
# List of enabled providers (default: only "rma" built-in rules)
1298-
enabled = ["rma"]
1299-
# To enable PMD for Java: enabled = ["rma", "pmd"]
1300-
# To enable Oxlint for JS/TS: enabled = ["rma", "oxlint"]
1374+
# List of enabled providers
1375+
# Default: ["rma", "oxc"] - built-in rules + native JS/TS linting
1376+
enabled = ["rma", "oxc"]
1377+
# To add PMD for Java: enabled = ["rma", "oxc", "pmd"]
1378+
# To add external Oxlint: enabled = ["rma", "oxc", "oxlint"]
13011379
13021380
# -----------------------------------------------------------------------------
13031381
# PMD Provider - Java Static Analysis (optional)
@@ -1941,6 +2019,8 @@ pub enum SuppressionSource {
19412019
Preset,
19422020
/// Suppressed by baseline
19432021
Baseline,
2022+
/// Suppressed by database entry
2023+
Database,
19442024
}
19452025

19462026
impl std::fmt::Display for SuppressionSource {
@@ -1951,6 +2031,7 @@ impl std::fmt::Display for SuppressionSource {
19512031
SuppressionSource::PathRule => write!(f, "path-rule"),
19522032
SuppressionSource::Preset => write!(f, "preset"),
19532033
SuppressionSource::Baseline => write!(f, "baseline"),
2034+
SuppressionSource::Database => write!(f, "database"),
19542035
}
19552036
}
19562037
}
@@ -1963,6 +2044,7 @@ impl std::fmt::Display for SuppressionSource {
19632044
/// - Inline suppressions (rma-ignore comments)
19642045
/// - Default test/example presets for PR/CI mode
19652046
/// - Baseline filtering
2047+
/// - Database suppressions (when enabled)
19662048
pub struct SuppressionEngine {
19672049
/// Global ignore paths
19682050
global_ignore_paths: Vec<String>,
@@ -1980,6 +2062,8 @@ pub struct SuppressionEngine {
19802062
test_patterns: Vec<regex::Regex>,
19812063
/// Compiled regex patterns for default example paths
19822064
example_patterns: Vec<regex::Regex>,
2065+
/// Optional suppression store for database-backed suppressions
2066+
suppression_store: Option<std::sync::Arc<crate::suppression::SuppressionStore>>,
19832067
}
19842068

19852069
impl SuppressionEngine {
@@ -2027,6 +2111,7 @@ impl SuppressionEngine {
20272111
rule_patterns,
20282112
test_patterns,
20292113
example_patterns,
2114+
suppression_store: None,
20302115
}
20312116
}
20322117

@@ -2041,6 +2126,23 @@ impl SuppressionEngine {
20412126
self
20422127
}
20432128

2129+
/// Set the suppression store for database-backed suppressions
2130+
pub fn with_store(mut self, store: crate::suppression::SuppressionStore) -> Self {
2131+
self.suppression_store = Some(std::sync::Arc::new(store));
2132+
self
2133+
}
2134+
2135+
/// Set a shared suppression store reference
2136+
pub fn with_store_ref(mut self, store: std::sync::Arc<crate::suppression::SuppressionStore>) -> Self {
2137+
self.suppression_store = Some(store);
2138+
self
2139+
}
2140+
2141+
/// Get a reference to the suppression store (if available)
2142+
pub fn store(&self) -> Option<&crate::suppression::SuppressionStore> {
2143+
self.suppression_store.as_ref().map(|s| s.as_ref())
2144+
}
2145+
20442146
/// Compile a glob pattern to a regex
20452147
///
20462148
/// Handles cases like:
@@ -2208,6 +2310,19 @@ impl SuppressionEngine {
22082310
}
22092311
}
22102312

2313+
// 6. Check database suppressions (applies to all rules including always-enabled)
2314+
if let Some(ref store) = self.suppression_store
2315+
&& let Some(fp) = fingerprint
2316+
{
2317+
if let Ok(Some(entry)) = store.is_suppressed(fp) {
2318+
return SuppressionResult::suppressed(
2319+
SuppressionSource::Database,
2320+
entry.reason.clone(),
2321+
format!("database:{}", entry.id),
2322+
);
2323+
}
2324+
}
2325+
22112326
SuppressionResult::not_suppressed()
22122327
}
22132328

@@ -2250,6 +2365,18 @@ impl SuppressionEngine {
22502365
"suppression_source".to_string(),
22512366
serde_json::json!(source.to_string()),
22522367
);
2368+
2369+
// For database suppressions, extract the suppression_id
2370+
if *source == SuppressionSource::Database {
2371+
if let Some(ref location) = result.location {
2372+
if let Some(id) = location.strip_prefix("database:") {
2373+
properties.insert(
2374+
"suppression_id".to_string(),
2375+
serde_json::json!(id),
2376+
);
2377+
}
2378+
}
2379+
}
22532380
}
22542381
if let Some(ref location) = result.location {
22552382
properties.insert(

0 commit comments

Comments
 (0)