feat(rome_service): `--apply-suggested` argument to `rome check`
MODIFY
crates/rome_cli/src/commands/check.rs
crates/rome_cli/src/commands/check.rs
@@ -6,7 +6,7 @@ use crate::{
use rome_diagnostics::MAXIMUM_DISPLAYABLE_DIAGNOSTICS;
use rome_service::load_config;
use rome_service::settings::WorkspaceSettings;
-use rome_service::workspace::UpdateSettingsParams;
+use rome_service::workspace::{FixFileMode, UpdateSettingsParams};
/// Handler for the "check" command of the Rome CLI
pub(crate) fn check(mut session: CliSession) -> Result<(), Termination> {
@@ -47,10 +47,26 @@ pub(crate) fn check(mut session: CliSession) -> Result<(), Termination> {
settings: workspace_settings,
})?;
+ let apply = session.args.contains("--apply");
+ let apply_suggested = session.args.contains("--apply-suggested");
+
+ let fix_file_mode = if apply && apply_suggested {
+ return Err(Termination::IncompatibleArguments(
+ "--apply",
+ "--apply-suggested",
+ ));
+ } else if !apply && !apply_suggested {
+ None
+ } else if apply && !apply_suggested {
+ Some(FixFileMode::SafeFixes)
+ } else {
+ Some(FixFileMode::SafeAndSuggestedFixes)
+ };
+
traverse(
TraversalMode::Check {
max_diagnostics,
- should_fix: session.args.contains("--apply"),
+ fix_file_mode,
},
session,
)

MODIFY
crates/rome_cli/src/commands/help.rs
crates/rome_cli/src/commands/help.rs
@@ -32,6 +32,7 @@ const CHECK: Markup = markup! {
"<Emphasis>"OPTIONS:"</Emphasis>"
"<Dim>"--apply"</Dim>" Apply safe fixes
+ "<Dim>"--apply-suggested"</Dim>" Apply safe and suggested fixes
"<Dim>"--max-diagnostics"</Dim>" Cap the amount of diagnostics displayed - default 20
"
};

MODIFY
crates/rome_cli/src/traversal.rs
crates/rome_cli/src/traversal.rs
@@ -20,9 +20,9 @@ use rome_diagnostics::{
file::{FileId, SimpleFile},
Diagnostic, DiagnosticHeader, Severity, MAXIMUM_DISPLAYABLE_DIAGNOSTICS,
};
-use rome_formatter::IndentStyle;
use rome_fs::{AtomicInterner, FileSystem, OpenOptions, PathInterner, RomePath};
use rome_fs::{TraversalContext, TraversalScope};
+use rome_service::workspace::FixFileMode;
use rome_service::{
workspace::{FeatureName, FileGuard, OpenFileParams, RuleCategories, SupportsFeatureParams},
Workspace,
@@ -90,8 +90,8 @@ pub(crate) fn traverse(mode: TraversalMode, mut session: CliSession) -> Result<(
let skipped = skipped.load(Ordering::Relaxed);
match mode {
- TraversalMode::Check { should_fix, .. } => {
- if should_fix {
+ TraversalMode::Check { .. } => {
+ if mode.as_fix_file_mode().is_some() {
console.log(rome_console::markup! {
<Info>"Fixed "{count}" files in "{duration}</Info>
});
@@ -158,9 +158,16 @@ fn print_messages_to_console(
let mut paths = HashMap::new();
let mut printed_diagnostics: u16 = 0;
let mut not_printed_diagnostics = 0;
+ let mut total_skipped_suggested_fixes = 0;
while let Ok(msg) = recv_msgs.recv() {
match msg {
+ Message::SkippedFixes {
+ skipped_suggested_fixes,
+ } => {
+ total_skipped_suggested_fixes += skipped_suggested_fixes;
+ }
+
Message::Error(err) => {
// Retrieves the file name from the file ID cache, if it's a miss
// flush entries from the interner channel until it's found
@@ -274,6 +281,13 @@ fn print_messages_to_console(
}
}
+ if mode.is_check() && total_skipped_suggested_fixes > 0 {
+ console.log(markup! {
+ <Warn>"Skipped "{total_skipped_suggested_fixes}" suggested fixes.\n"</Warn>
+ <Info>"If you wish to apply the suggested fixes, use the command "<Emphasis>"rome check --apply-suggested\n"</Emphasis></Info>
+ })
+ }
+
if !mode.is_ci() && not_printed_diagnostics > 0 {
console.log(markup! {
<Warn>"The number of diagnostics exceeds the number allowed by Rome.\n"</Warn>
@@ -288,9 +302,14 @@ fn print_messages_to_console(
pub(crate) enum TraversalMode {
/// This mode is enabled when running the command `rome check`
Check {
+ /// The maximum number of diagnostics that can be printed in console
max_diagnostics: u16,
- /// `true` when running the command `check` with the `--apply` argument
- should_fix: bool,
+
+ /// The type of fixes that should be applied when analyzing a file.
+ ///
+ /// It's [None] if the `check` command is called without `--apply` or `--apply-suggested`
+ /// arguments.
+ fix_file_mode: Option<FixFileMode>,
},
/// This mode is enabled when running the command `rome ci`
CI,
@@ -309,17 +328,21 @@ impl TraversalMode {
}
/// `true` only when running the traversal in [TraversalMode::Check] and `should_fix` is `true`
- fn should_fix(&self) -> bool {
- if let TraversalMode::Check { should_fix, .. } = self {
- *should_fix
+ fn as_fix_file_mode(&self) -> Option<&FixFileMode> {
+ if let TraversalMode::Check { fix_file_mode, .. } = self {
+ fix_file_mode.as_ref()
} else {
- false
+ None
}
}
fn is_ci(&self) -> bool {
matches!(self, TraversalMode::CI { .. })
}
+
+ fn is_check(&self) -> bool {
+ matches!(self, TraversalMode::Check { .. })
+ }
}
/// Context object shared between directory traversal tasks
@@ -483,11 +506,15 @@ fn process_file(ctx: &TraversalOptions, path: &Path, file_id: FileId) -> FileRes
)
.with_file_id_and_code(file_id, "IO")?;
- if ctx.mode.should_fix() {
+ if let Some(fix_mode) = ctx.mode.as_fix_file_mode() {
let fixed = file_guard
- .fix_file()
+ .fix_file(*fix_mode)
.with_file_id_and_code(file_id, "Lint")?;
+ ctx.push_message(Message::SkippedFixes {
+ skipped_suggested_fixes: fixed.skipped_suggested_fixes,
+ });
+
if fixed.code != input {
file.set_content(fixed.code.as_bytes())
.with_file_id(file_id)?;
@@ -562,14 +589,21 @@ fn process_file(ctx: &TraversalOptions, path: &Path, file_id: FileId) -> FileRes
if can_format {
let write = match ctx.mode {
- // In check mode do not run the formatter and return the result immediately
- TraversalMode::Check { .. } => return Ok(result),
+ // In check mode do not run the formatter and return the result immediately,
+ // but only if the argument `--apply` is not passed.
+ TraversalMode::Check { .. } => {
+ if ctx.mode.as_fix_file_mode().is_some() {
+ true
+ } else {
+ return Ok(result);
+ }
+ }
TraversalMode::CI { .. } => false,
TraversalMode::Format { write, .. } => write,
};
let printed = file_guard
- .format_file(IndentStyle::default())
+ .format_file()
.with_file_id_and_code(file_id, "Format")?;
let output = printed.into_code();
@@ -599,6 +633,10 @@ fn process_file(ctx: &TraversalOptions, path: &Path, file_id: FileId) -> FileRes
/// Wrapper type for messages that can be printed during the traversal process
enum Message {
+ SkippedFixes {
+ /// Suggested fixes skipped during the lint traversal
+ skipped_suggested_fixes: u32,
+ },
Error(TraversalError),
Diagnostics {
name: String,

MODIFY
crates/rome_cli/tests/main.rs
crates/rome_cli/tests/main.rs
@@ -32,6 +32,12 @@ const FIX_AFTER: &str = "
if(a != 0) {}
";
+const APPLY_SUGGESTED_BEFORE: &str = "let a = 4;
+debugger;
+";
+
+const APPLY_SUGGESTED_AFTER: &str = "let a = 4;\n";
+
const CUSTOM_FORMAT_BEFORE: &str = r#"
function f() {
return { something }
@@ -44,14 +50,21 @@ const CUSTOM_FORMAT_AFTER: &str = r#"function f() {
}
"#;
-const NO_DEBUGGER: &str = "debugger;";
+const NO_DEBUGGER_BEFORE: &str = "debugger;";
+const NO_DEBUGGER_AFTER: &str = "debugger;";
-const JS_ERRORS: &str = r#"try {
- !a && !b
+const JS_ERRORS_BEFORE: &str = r#"try {
+ !a && !b;
} catch (err) {
err = 24;
}
"#;
+const JS_ERRORS_AFTER: &str = "try {
+ !a && !b;
+} catch (err) {
+ err = 24;
+}
+";
mod check {
use super::*;
@@ -219,6 +232,70 @@ mod check {
assert!(result.is_ok(), "run_cli returned {result:?}");
}
+ #[test]
+ fn apply_suggested_error() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let file_path = Path::new("fix.js");
+ fs.insert(file_path.into(), APPLY_SUGGESTED_BEFORE.as_bytes());
+
+ let result = run_cli(CliSession {
+ app: App::with_filesystem_and_console(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ ),
+ args: Arguments::from_vec(vec![
+ OsString::from("check"),
+ OsString::from("--apply-suggested"),
+ OsString::from("--apply"),
+ file_path.as_os_str().into(),
+ ]),
+ });
+
+ assert!(result.is_err(), "run_cli returned {result:?}");
+
+ match result {
+ Err(error) => {
+ assert!(error
+ .to_string()
+ .contains("incompatible arguments '--apply' and '--apply-suggested"),)
+ }
+ _ => panic!("expected an error, but found none"),
+ }
+ }
+
+ #[test]
+ fn apply_suggested() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let file_path = Path::new("fix.js");
+ fs.insert(file_path.into(), APPLY_SUGGESTED_BEFORE.as_bytes());
+
+ let result = run_cli(CliSession {
+ app: App::with_filesystem_and_console(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ ),
+ args: Arguments::from_vec(vec![
+ OsString::from("check"),
+ OsString::from("--apply-suggested"),
+ file_path.as_os_str().into(),
+ ]),
+ });
+
+ assert!(result.is_ok(), "run_cli returned {result:?}");
+
+ let mut buffer = String::new();
+ fs.open(file_path)
+ .unwrap()
+ .read_to_string(&mut buffer)
+ .unwrap();
+
+ assert_eq!(buffer, APPLY_SUGGESTED_AFTER);
+ }
+
#[test]
fn no_lint_if_linter_is_disabled_when_run_apply() {
let mut fs = MemoryFileSystem::default();
@@ -289,7 +366,7 @@ mod check {
let mut console = BufferConsole::default();
let file_path = Path::new("fix.js");
- fs.insert(file_path.into(), NO_DEBUGGER.as_bytes());
+ fs.insert(file_path.into(), NO_DEBUGGER_BEFORE.as_bytes());
let config_path = Path::new("rome.json");
fs.insert(config_path.into(), CONFIG_LINTER_SUPPRESSED_RULE.as_bytes());
@@ -314,7 +391,7 @@ mod check {
.read_to_string(&mut buffer)
.unwrap();
- assert_eq!(buffer, NO_DEBUGGER);
+ assert_eq!(buffer, NO_DEBUGGER_AFTER);
}
#[test]
@@ -323,7 +400,7 @@ mod check {
let mut console = BufferConsole::default();
let file_path = Path::new("fix.js");
- fs.insert(file_path.into(), JS_ERRORS.as_bytes());
+ fs.insert(file_path.into(), JS_ERRORS_BEFORE.as_bytes());
let config_path = Path::new("rome.json");
fs.insert(
@@ -351,7 +428,7 @@ mod check {
.read_to_string(&mut buffer)
.unwrap();
- assert_eq!(buffer, JS_ERRORS);
+ assert_eq!(buffer, JS_ERRORS_AFTER);
}
}

MODIFY
crates/rome_lsp/src/handlers/analysis.rs
crates/rome_lsp/src/handlers/analysis.rs
@@ -4,7 +4,7 @@ use anyhow::{Context, Result};
use rome_analyze::ActionCategory;
use rome_fs::RomePath;
use rome_service::workspace::{
- FeatureName, FixFileParams, PullActionsParams, SupportsFeatureParams,
+ FeatureName, FixFileMode, FixFileParams, PullActionsParams, SupportsFeatureParams,
};
use rome_service::RomeError;
use tower_lsp::lsp_types::{
@@ -122,9 +122,10 @@ fn fix_all(
line_index: &LineIndex,
diagnostics: &[lsp::Diagnostic],
) -> Result<Option<CodeActionOrCommand>, RomeError> {
- let fixed = session
- .workspace
- .fix_file(FixFileParams { path: rome_path })?;
+ let fixed = session.workspace.fix_file(FixFileParams {
+ path: rome_path,
+ fix_file_mode: FixFileMode::SafeFixes,
+ })?;
if fixed.actions.is_empty() {
return Ok(None);

MODIFY
crates/rome_lsp/src/handlers/formatting.rs
crates/rome_lsp/src/handlers/formatting.rs
use crate::session::Session;
use crate::utils;
use anyhow::{Context, Error, Result};
-use rome_formatter::IndentStyle;
use rome_rowan::TextRange;
use rome_service::{
workspace::{FormatFileParams, FormatOnTypeParams, FormatRangeParams},
@@ -20,17 +19,10 @@ pub(crate) fn format(
let doc = session.document(&url)?;
- let indent_style = if params.options.insert_spaces {
- IndentStyle::Space(params.options.tab_size as u8)
- } else {
- IndentStyle::Tab
- };
-
trace!("Formatting...");
- let result = session.workspace.format_file(FormatFileParams {
- path: rome_path,
- indent_style,
- });
+ let result = session
+ .workspace
+ .format_file(FormatFileParams { path: rome_path });
let printed = match result {
Ok(printed) => printed,
@@ -65,12 +57,6 @@ pub(crate) fn format_range(
let rome_path = session.file_path(&url);
let doc = session.document(&url)?;
- let indent_style = if params.options.insert_spaces {
- IndentStyle::Space(params.options.tab_size as u8)
- } else {
- IndentStyle::Tab
- };
-
let start_index = utils::offset(&doc.line_index, params.range.start).with_context(|| {
format!(
"failed to access position {:?} in document {url}",
@@ -88,7 +74,6 @@ pub(crate) fn format_range(
let result = session.workspace.format_range(FormatRangeParams {
path: rome_path,
range: format_range,
- indent_style,
});
let formatted = match result {
@@ -139,19 +124,12 @@ pub(crate) fn format_on_type(
let rome_path = session.file_path(&url);
let doc = session.document(&url)?;
- let indent_style = if params.options.insert_spaces {
- IndentStyle::Space(params.options.tab_size as u8)
- } else {
- IndentStyle::Tab
- };
-
let offset = utils::offset(&doc.line_index, position)
.with_context(|| format!("failed to access position {position:?} in document {url}"))?;
let result = session.workspace.format_on_type(FormatOnTypeParams {
path: rome_path,
offset,
- indent_style,
});
let formatted = match result {

MODIFY
crates/rome_service/src/file_handlers/javascript.rs
crates/rome_service/src/file_handlers/javascript.rs
use rome_analyze::{AnalysisFilter, ControlFlow, Never, RuleCategories, RuleFilter};
use rome_diagnostics::{Applicability, CodeSuggestion, Diagnostic};
-use rome_formatter::{FormatError, IndentStyle, Printed};
+use rome_formatter::{FormatError, Printed};
use rome_fs::RomePath;
use rome_js_analyze::analyze;
use rome_js_analyze::utils::rename::RenameError;
@@ -11,7 +11,9 @@ use rome_js_semantic::semantic_model;
use rome_js_syntax::{JsAnyRoot, JsLanguage, SourceType, TextRange, TextSize, TokenAtOffset};
use rome_rowan::{AstNode, BatchMutationExt, Direction};
-use crate::workspace::{CodeAction, FixAction, FixFileResult, PullActionsResult, RenameResult};
+use crate::workspace::{
+ CodeAction, FixAction, FixFileMode, FixFileResult, PullActionsResult, RenameResult,
+};
use crate::{
settings::{FormatSettings, Language, LanguageSettings, LanguagesSettings, SettingsHandle},
workspace::server::AnyParse,
@@ -19,6 +21,7 @@ use crate::{
};
use super::{ExtensionHandler, Mime};
+use crate::file_handlers::FixAllParams;
use indexmap::IndexSet;
use std::borrow::Cow;
use std::fmt::Debug;
@@ -53,11 +56,10 @@ impl Language for JsLanguage {
fn resolve_format_context(
global: &FormatSettings,
language: &JsFormatSettings,
- editor: IndentStyle,
path: &RomePath,
) -> JsFormatContext {
JsFormatContext::new(path.as_path().try_into().unwrap_or_default())
- .with_indent_style(global.indent_style.unwrap_or(editor))
+ .with_indent_style(global.indent_style.unwrap_or_default())
.with_line_width(global.line_width.unwrap_or_default())
.with_quote_style(language.quote_style.unwrap_or_default())
}
@@ -187,15 +189,21 @@ fn code_actions(
PullActionsResult { actions }
}
-fn fix_all(
- rome_path: &RomePath,
- parse: AnyParse,
- configuration_rules: Option<&Rules>,
-) -> FixFileResult {
+/// If applies all the safe fixes to the given syntax tree.
+///
+/// If `indent_style` is [Some], it means that the formatting should be applied at the end
+fn fix_all(params: FixAllParams) -> Result<FixFileResult, RomeError> {
+ let FixAllParams {
+ rome_path,
+ parse,
+ rules,
+ fix_file_mode,
+ } = params;
+
let mut tree: JsAnyRoot = parse.tree();
let mut actions = Vec::new();
- let enabled_rules: Option<Vec<RuleFilter>> = if let Some(rules) = configuration_rules {
+ let enabled_rules: Option<Vec<RuleFilter>> = if let Some(rules) = rules {
let enabled: IndexSet<RuleFilter> = rules.as_enabled_rules();
Some(enabled.into_iter().collect())
} else {
@@ -210,14 +218,29 @@ fn fix_all(
filter.categories = RuleCategories::SYNTAX | RuleCategories::LINT;
let file_id = rome_path.file_id();
-
+ let mut skipped_suggested_fixes = 0;
loop {
let action = analyze(file_id, &tree, filter, |signal| {
if let Some(action) = signal.action() {
+ match fix_file_mode {
+ FixFileMode::SafeFixes => {
+ if action.applicability == Applicability::MaybeIncorrect {
+ skipped_suggested_fixes += 1;
+ }
if action.applicability == Applicability::Always {
return ControlFlow::Break(action);
}
}
+ FixFileMode::SafeAndSuggestedFixes => {
+ if matches!(
+ action.applicability,
+ Applicability::Always | Applicability::MaybeIncorrect
+ ) {
+ return ControlFlow::Break(action);
+ }
+ }
+ }
+ }
ControlFlow::Continue(())
});
@@ -233,10 +256,11 @@ fn fix_all(
}
}
None => {
- return FixFileResult {
+ return Ok(FixFileResult {
code: tree.syntax().to_string(),
+ skipped_suggested_fixes,
actions,
- }
+ });
}
}
}
@@ -245,7 +269,7 @@ fn fix_all(
fn format(
rome_path: &RomePath,
parse: AnyParse,
- settings: SettingsHandle<IndentStyle>,
+ settings: SettingsHandle,
) -> Result<Printed, RomeError> {
let context = settings.format_context::<JsLanguage>(rome_path);
@@ -258,7 +282,7 @@ fn format(
fn format_range(
rome_path: &RomePath,
parse: AnyParse,
- settings: SettingsHandle<IndentStyle>,
+ settings: SettingsHandle,
range: TextRange,
) -> Result<Printed, RomeError> {
let context = settings.format_context::<JsLanguage>(rome_path);
@@ -271,7 +295,7 @@ fn format_range(
fn format_on_type(
rome_path: &RomePath,
parse: AnyParse,
- settings: SettingsHandle<IndentStyle>,
+ settings: SettingsHandle,
offset: TextSize,
) -> Result<Printed, RomeError> {
let context = settings.format_context::<JsLanguage>(rome_path);

MODIFY
crates/rome_service/src/file_handlers/mod.rs
crates/rome_service/src/file_handlers/mod.rs
use rome_analyze::AnalysisFilter;
use rome_diagnostics::Diagnostic;
-use rome_formatter::{IndentStyle, Printed};
+use rome_formatter::Printed;
use rome_fs::RomePath;
use rome_js_syntax::{TextRange, TextSize};
use std::ffi::OsStr;
@@ -17,6 +17,7 @@ mod javascript;
mod json;
mod unknown;
+use crate::workspace::FixFileMode;
pub use javascript::JsFormatSettings;
/// Supported languages by Rome
@@ -70,16 +71,21 @@ impl std::fmt::Display for Mime {
}
}
+pub struct FixAllParams<'a> {
+ pub(crate) rome_path: &'a RomePath,
+ pub(crate) parse: AnyParse,
+ pub(crate) rules: Option<&'a Rules>,
+ pub(crate) fix_file_mode: FixFileMode,
+}
+
type Parse = fn(&RomePath, &str) -> AnyParse;
type DebugPrint = fn(&RomePath, AnyParse) -> String;
type Lint = fn(&RomePath, AnyParse, AnalysisFilter) -> Vec<Diagnostic>;
type CodeActions = fn(&RomePath, AnyParse, TextRange, Option<&Rules>) -> PullActionsResult;
-type FixAll = fn(&RomePath, AnyParse, Option<&Rules>) -> FixFileResult;
-type Format = fn(&RomePath, AnyParse, SettingsHandle<IndentStyle>) -> Result<Printed, RomeError>;
-type FormatRange =
- fn(&RomePath, AnyParse, SettingsHandle<IndentStyle>, TextRange) -> Result<Printed, RomeError>;
-type FormatOnType =
- fn(&RomePath, AnyParse, SettingsHandle<IndentStyle>, TextSize) -> Result<Printed, RomeError>;
+type FixAll = fn(FixAllParams) -> Result<FixFileResult, RomeError>;
+type Format = fn(&RomePath, AnyParse, SettingsHandle) -> Result<Printed, RomeError>;
+type FormatRange = fn(&RomePath, AnyParse, SettingsHandle, TextRange) -> Result<Printed, RomeError>;
+type FormatOnType = fn(&RomePath, AnyParse, SettingsHandle, TextSize) -> Result<Printed, RomeError>;
type Rename = fn(&RomePath, AnyParse, TextSize, String) -> Result<RenameResult, RomeError>;
pub(crate) struct Capabilities {

MODIFY
crates/rome_service/src/settings.rs
crates/rome_service/src/settings.rs
@@ -125,7 +125,6 @@ pub trait Language: rome_rowan::Language {
fn resolve_format_context(
global: &FormatSettings,
language: &Self::FormatSettings,
- editor: IndentStyle,
path: &RomePath,
) -> Self::FormatContext;
}
@@ -155,28 +154,26 @@ pub struct LanguageSettings<L: Language> {
/// Handle object holding a temporary lock on the workspace settings until
/// the deferred language-specific options resolution is called
-pub(crate) struct SettingsHandle<'a, E> {
+#[derive(Debug)]
+pub(crate) struct SettingsHandle<'a> {
inner: RwLockReadGuard<'a, WorkspaceSettings>,
- /// Additional per-request state injected by the editor
- editor: E,
}
-impl<'a, E> SettingsHandle<'a, E> {
- pub(crate) fn new(settings: &'a RwLock<WorkspaceSettings>, editor: E) -> Self {
+impl<'a> SettingsHandle<'a> {
+ pub(crate) fn new(settings: &'a RwLock<WorkspaceSettings>) -> Self {
Self {
inner: settings.read().unwrap(),
- editor,
}
}
}
-impl<'a, E> AsRef<WorkspaceSettings> for SettingsHandle<'a, E> {
+impl<'a> AsRef<WorkspaceSettings> for SettingsHandle<'a> {
fn as_ref(&self) -> &WorkspaceSettings {
&*self.inner
}
}
-impl<'a> SettingsHandle<'a, IndentStyle> {
+impl<'a> SettingsHandle<'a> {
/// Resolve the formatting context for the given language
pub(crate) fn format_context<L>(self, path: &RomePath) -> L::FormatContext
where
@@ -185,7 +182,6 @@ impl<'a> SettingsHandle<'a, IndentStyle> {
L::resolve_format_context(
&self.inner.format,
&L::lookup_settings(&self.inner.languages).format,
- self.editor,
path,
)
}

MODIFY
crates/rome_service/src/workspace.rs
crates/rome_service/src/workspace.rs
@@ -56,7 +56,7 @@ use crate::RomeError;
use rome_analyze::ActionCategory;
pub use rome_analyze::RuleCategories;
use rome_diagnostics::{CodeSuggestion, Diagnostic};
-use rome_formatter::{IndentStyle, Printed};
+use rome_formatter::Printed;
use rome_fs::RomePath;
use rome_js_syntax::{TextRange, TextSize};
use rome_text_edit::Indel;
@@ -176,7 +176,6 @@ pub struct CodeAction {
)]
pub struct FormatFileParams {
pub path: RomePath,
- pub indent_style: IndentStyle,
}
#[cfg_attr(
@@ -186,7 +185,6 @@ pub struct FormatFileParams {
pub struct FormatRangeParams {
pub path: RomePath,
pub range: TextRange,
- pub indent_style: IndentStyle,
}
#[cfg_attr(
@@ -196,7 +194,19 @@ pub struct FormatRangeParams {
pub struct FormatOnTypeParams {
pub path: RomePath,
pub offset: TextSize,
- pub indent_style: IndentStyle,
+}
+
+#[derive(Clone, Copy)]
+#[cfg_attr(
+ feature = "serde_workspace",
+ derive(serde::Serialize, serde::Deserialize)
+)]
+/// Which fixes should be applied during the analyzing phase
+pub enum FixFileMode {
+ /// Applies [safe](rome_diagnostics::Applicability::Always) fixes
+ SafeFixes,
+ /// Applies [safe](rome_diagnostics::Applicability::Always) and suggested [safe](rome_diagnostics::Applicability::MaybeIncorrect)
+ SafeAndSuggestedFixes,
}
#[cfg_attr(
@@ -205,8 +215,10 @@ pub struct FormatOnTypeParams {
)]
pub struct FixFileParams {
pub path: RomePath,
+ pub fix_file_mode: FixFileMode,
}
+#[derive(Debug)]
#[cfg_attr(
feature = "serde_workspace",
derive(serde::Serialize, serde::Deserialize)
@@ -216,12 +228,16 @@ pub struct FixFileResult {
pub code: String,
/// List of all the code actions applied to the file
pub actions: Vec<FixAction>,
+
+ /// number of skipped suggested fixes
+ pub skipped_suggested_fixes: u32,
}
#[cfg_attr(
feature = "serde_workspace",
derive(serde::Serialize, serde::Deserialize)
)]
+#[derive(Debug)]
pub struct FixAction {
/// Name of the rule that emitted this code action
pub rule_name: Cow<'static, str>,
@@ -350,40 +366,30 @@ impl<'app, W: Workspace + ?Sized> FileGuard<'app, W> {
})
}
- pub fn format_file(&self, indent_style: IndentStyle) -> Result<Printed, RomeError> {
+ pub fn format_file(&self) -> Result<Printed, RomeError> {
self.workspace.format_file(FormatFileParams {
path: self.path.clone(),
- indent_style,
})
}
- pub fn format_range(
- &self,
- indent_style: IndentStyle,
- range: TextRange,
- ) -> Result<Printed, RomeError> {
+ pub fn format_range(&self, range: TextRange) -> Result<Printed, RomeError> {
self.workspace.format_range(FormatRangeParams {
path: self.path.clone(),
- indent_style,
range,
})
}
- pub fn format_on_type(
- &self,
- indent_style: IndentStyle,
- offset: TextSize,
- ) -> Result<Printed, RomeError> {
+ pub fn format_on_type(&self, offset: TextSize) -> Result<Printed, RomeError> {
self.workspace.format_on_type(FormatOnTypeParams {
path: self.path.clone(),
- indent_style,
offset,
})
}
- pub fn fix_file(&self) -> Result<FixFileResult, RomeError> {
+ pub fn fix_file(&self, fix_file_mode: FixFileMode) -> Result<FixFileResult, RomeError> {
self.workspace.fix_file(FixFileParams {
path: self.path.clone(),
+ fix_file_mode,
})
}
}

MODIFY
crates/rome_service/src/workspace/server.rs
crates/rome_service/src/workspace/server.rs
@@ -8,6 +8,7 @@ use rome_formatter::Printed;
use rome_fs::RomePath;
use rome_rowan::{AstNode, Language as RowanLanguage, SendNode, SyntaxNode};
+use crate::file_handlers::FixAllParams;
use crate::{
file_handlers::Features,
settings::{SettingsHandle, WorkspaceSettings},
@@ -107,8 +108,8 @@ impl WorkspaceServer {
}
}
- fn settings<E>(&self, editor: E) -> SettingsHandle<E> {
- SettingsHandle::new(&self.settings, editor)
+ fn settings(&self) -> SettingsHandle {
+ SettingsHandle::new(&self.settings)
}
/// Get the parser result for a given file
@@ -262,7 +263,7 @@ impl Workspace for WorkspaceServer {
.ok_or_else(|| RomeError::SourceFileNotSupported(params.path.clone()))?;
let parse = self.get_parse(params.path.clone())?;
- let settings = self.settings(params.indent_style);
+ let settings = self.settings();
if !settings.as_ref().format.format_with_errors && parse.has_errors() {
return Err(RomeError::FormatWithErrorsDisabled);
@@ -278,7 +279,7 @@ impl Workspace for WorkspaceServer {
.ok_or_else(|| RomeError::SourceFileNotSupported(params.path.clone()))?;
let parse = self.get_parse(params.path.clone())?;
- let settings = self.settings(params.indent_style);
+ let settings = self.settings();
if !settings.as_ref().format.format_with_errors && parse.has_errors() {
return Err(RomeError::FormatWithErrorsDisabled);
@@ -294,7 +295,7 @@ impl Workspace for WorkspaceServer {
.ok_or_else(|| RomeError::SourceFileNotSupported(params.path.clone()))?;
let parse = self.get_parse(params.path.clone())?;
- let settings = self.settings(params.indent_style);
+ let settings = self.settings();
if !settings.as_ref().format.format_with_errors && parse.has_errors() {
return Err(RomeError::FormatWithErrorsDisabled);
@@ -312,7 +313,12 @@ impl Workspace for WorkspaceServer {
let parse = self.get_parse(params.path.clone())?;
let settings = self.settings.read().unwrap();
let rules = settings.linter.rules.as_ref();
- Ok(fix_all(&params.path, parse, rules))
+ fix_all(FixAllParams {
+ rome_path: &params.path,
+ parse,
+ rules,
+ fix_file_mode: params.fix_file_mode,
+ })
}
fn rename(&self, params: super::RenameParams) -> Result<RenameResult, RomeError> {

feat(rome_service): `--apply-suggested` argument to `rome check` (#2952)