diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index 34ebb0f7f058c..731c193f523f3 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -119,20 +119,20 @@ impl Runner for LintRunner { let oxlintrc_for_print = if misc_options.print_config { Some(oxlintrc.clone()) } else { None }; - let builder = LinterBuilder::from_oxlintrc(false, oxlintrc); + let (builder, builder_error) = LinterBuilder::from_oxlintrc(false, oxlintrc); // Gracefully report any linter builder errors as CLI errors - let builder = match builder { - Ok(builder) => builder, - Err(err) => match err { + if let Some(builder_error) = builder_error { + return match builder_error { LinterBuilderError::UnknownRules { rules } => { let rules = rules.iter().map(|r| r.full_name()).collect::>().join("\n"); let error = Error::from(OxcDiagnostic::warn(format!( "The following rules do not match the currently supported rules:\n{rules}" ))); - return CliRunResult::LintError { error: format!("{error:?}") }; + CliRunResult::LintError { error: format!("{error:?}") } } - }, - }; + }; + } + let builder = builder.with_filters(filter).with_fix(fix_options.fix_kind()); if let Some(basic_config_file) = oxlintrc_for_print { diff --git a/crates/oxc_language_server/src/main.rs b/crates/oxc_language_server/src/main.rs index c5d2ef27800b8..d90d5a2694d0b 100644 --- a/crates/oxc_language_server/src/main.rs +++ b/crates/oxc_language_server/src/main.rs @@ -17,9 +17,9 @@ use tower_lsp::{ CodeActionProviderCapability, CodeActionResponse, ConfigurationItem, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializeResult, - InitializedParams, OneOf, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, - TextDocumentSyncKind, TextEdit, Url, WorkDoneProgressOptions, WorkspaceEdit, - WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, + InitializedParams, MessageType, OneOf, ServerCapabilities, ServerInfo, + TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit, Url, WorkDoneProgressOptions, + WorkspaceEdit, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, }, Client, LanguageServer, LspService, Server, }; @@ -352,18 +352,17 @@ impl Backend { config_path = Some(config); } if let Some(config_path) = config_path { - let mut linter = self.server_linter.write().await; - *linter = ServerLinter::new_with_linter( - LinterBuilder::from_oxlintrc( - true, - Oxlintrc::from_file(&config_path) - .expect("should have initialized linter with new options"), - ) - // FIXME: Handle this error more gracefully and report it properly - .expect("failed to build linter from oxlint config") - .with_fix(FixKind::SafeFix) - .build(), + let (linter_builder, errors) = LinterBuilder::from_oxlintrc( + true, + Oxlintrc::from_file(&config_path) + .expect("should have initialized linter with new options"), ); + if let Some(errors) = errors { + self.client.show_message(MessageType::WARNING, errors).await; + } + let mut linter = self.server_linter.write().await; + *linter = + ServerLinter::new_with_linter(linter_builder.with_fix(FixKind::SafeFix).build()); } } diff --git a/crates/oxc_linter/src/builder.rs b/crates/oxc_linter/src/builder.rs index 53ffdd1bb3f33..0d97d0a96656e 100644 --- a/crates/oxc_linter/src/builder.rs +++ b/crates/oxc_linter/src/builder.rs @@ -83,7 +83,7 @@ impl LinterBuilder { pub fn from_oxlintrc( start_empty: bool, oxlintrc: Oxlintrc, - ) -> Result { + ) -> (Self, Option) { // TODO: monorepo config merging, plugin-based extends, etc. let Oxlintrc { plugins, settings, env, globals, categories, rules: mut oxlintrc_rules } = oxlintrc; @@ -105,12 +105,13 @@ impl LinterBuilder { } if !oxlintrc_rules.unknown_rules.is_empty() { - return Err(LinterBuilderError::UnknownRules { + let error = LinterBuilderError::UnknownRules { rules: std::mem::take(&mut oxlintrc_rules.unknown_rules), - }); + }; + return (builder, Some(error)); } - Ok(builder) + (builder, None) } #[inline] @@ -311,7 +312,11 @@ impl TryFrom for LinterBuilder { #[inline] fn try_from(oxlintrc: Oxlintrc) -> Result { - Self::from_oxlintrc(false, oxlintrc) + let (builder, error) = Self::from_oxlintrc(false, oxlintrc); + if let Some(error) = error { + return Err(error); + } + Ok(builder) } } @@ -338,7 +343,7 @@ impl std::fmt::Display for LinterBuilderError { LinterBuilderError::UnknownRules { rules } => { write!(f, "unknown rules: ")?; for rule in rules { - write!(f, "{}", rule.full_name())?; + writeln!(f, "{}", rule.full_name())?; } Ok(()) } @@ -643,7 +648,7 @@ mod test { "#, ) .unwrap(); - let builder = LinterBuilder::from_oxlintrc(false, oxlintrc).unwrap(); + let (builder, _) = LinterBuilder::from_oxlintrc(false, oxlintrc); for rule in &builder.rules { let name = rule.name(); let plugin = rule.plugin_name(); diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index aad7fdf7ae4ea..530fe90bf2ee8 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -432,7 +432,7 @@ impl Tester { let linter = eslint_config .as_ref() .map_or_else(LinterBuilder::empty, |v| { - LinterBuilder::from_oxlintrc(true, Oxlintrc::deserialize(v).unwrap()).unwrap() + LinterBuilder::from_oxlintrc(true, Oxlintrc::deserialize(v).unwrap()).0 }) .with_fix(fix.into()) .with_plugins(self.plugins)