diff --git a/CHANGELOG.md b/CHANGELOG.md index 08cc088b2f2..ba9c7572674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,14 @@ This wasn't ideal for users, because this could have created false positives in linting, or formatted code with a configuration that wasn't the of the user. +- The command `rome check` now shows formatter diagnostics when checking the code. + + The presence of the diagnostics will result in an error code when the command finishes. + This is in line with semantic and behaviour meant for the command `rome check`. #### Other changes -- The command `rome check` now shows formatter diagnostics when checking the code. - Fix [#4556](https://github.com/rome/tools/issues/4556), which correctly handles new lines in the `.gitignore` file across OS. - Add a new option to ignore unknown files `--files-ignore-unknown`: @@ -34,6 +37,8 @@ Rome won't exit with an error code in case no files were processed in the given paths. +- Fixed the diagnostics emitted when running the `rome format` command; + ### Configuration #### Other changes diff --git a/crates/rome_cli/src/execute/diagnostics.rs b/crates/rome_cli/src/execute/diagnostics.rs index dc90de71f9e..5f77450f1d4 100644 --- a/crates/rome_cli/src/execute/diagnostics.rs +++ b/crates/rome_cli/src/execute/diagnostics.rs @@ -8,11 +8,11 @@ use std::io; category = "format", message = "File content differs from formatting output" )] -pub(crate) struct CIFormatDiffDiagnostic<'a> { +pub(crate) struct CIFormatDiffDiagnostic { #[location(resource)] - pub(crate) file_name: &'a str, + pub(crate) file_name: String, #[advice] - pub(crate) diff: ContentDiffAdvice<'a>, + pub(crate) diff: ContentDiffAdvice, } #[derive(Debug, Diagnostic)] @@ -20,11 +20,11 @@ pub(crate) struct CIFormatDiffDiagnostic<'a> { category = "organizeImports", message = "Import statements differs from the output" )] -pub(crate) struct CIOrganizeImportsDiffDiagnostic<'a> { +pub(crate) struct CIOrganizeImportsDiffDiagnostic { #[location(resource)] - pub(crate) file_name: &'a str, + pub(crate) file_name: String, #[advice] - pub(crate) diff: ContentDiffAdvice<'a>, + pub(crate) diff: ContentDiffAdvice, } #[derive(Debug, Diagnostic)] @@ -33,11 +33,11 @@ category = "format", severity = Information, message = "Formatter would have printed the following content:" )] -pub(crate) struct FormatDiffDiagnostic<'a> { +pub(crate) struct FormatDiffDiagnostic { #[location(resource)] - pub(crate) file_name: &'a str, + pub(crate) file_name: String, #[advice] - pub(crate) diff: ContentDiffAdvice<'a>, + pub(crate) diff: ContentDiffAdvice, } #[derive(Debug, Diagnostic)] @@ -46,11 +46,11 @@ pub(crate) struct FormatDiffDiagnostic<'a> { severity = Information, message = "Import statements could be sorted:" )] -pub(crate) struct OrganizeImportsDiffDiagnostic<'a> { +pub(crate) struct OrganizeImportsDiffDiagnostic { #[location(resource)] - pub(crate) file_name: &'a str, + pub(crate) file_name: String, #[advice] - pub(crate) diff: ContentDiffAdvice<'a>, + pub(crate) diff: ContentDiffAdvice, } #[derive(Debug, Diagnostic)] @@ -59,22 +59,22 @@ pub(crate) struct OrganizeImportsDiffDiagnostic<'a> { severity = Information, message = "Configuration file can be updated." )] -pub(crate) struct MigrateDiffDiagnostic<'a> { +pub(crate) struct MigrateDiffDiagnostic { #[location(resource)] - pub(crate) file_name: &'a str, + pub(crate) file_name: String, #[advice] - pub(crate) diff: ContentDiffAdvice<'a>, + pub(crate) diff: ContentDiffAdvice, } #[derive(Debug)] -pub(crate) struct ContentDiffAdvice<'a> { - pub(crate) old: &'a str, - pub(crate) new: &'a str, +pub(crate) struct ContentDiffAdvice { + pub(crate) old: String, + pub(crate) new: String, } -impl Advices for ContentDiffAdvice<'_> { +impl Advices for ContentDiffAdvice { fn record(&self, visitor: &mut dyn Visit) -> io::Result<()> { - let diff = TextEdit::from_unicode_words(self.old, self.new); + let diff = TextEdit::from_unicode_words(&self.old, &self.new); visitor.record_diff(&diff) } } diff --git a/crates/rome_cli/src/execute/migrate.rs b/crates/rome_cli/src/execute/migrate.rs index f612dce9c2d..30c3eb6c284 100644 --- a/crates/rome_cli/src/execute/migrate.rs +++ b/crates/rome_cli/src/execute/migrate.rs @@ -81,10 +81,10 @@ pub(crate) fn run( } else { let file_name = configuration_path.display().to_string(); let diagnostic = MigrateDiffDiagnostic { - file_name: &file_name, + file_name, diff: ContentDiffAdvice { - old: configuration_content.as_str(), - new: new_configuration_content.as_str(), + old: configuration_content, + new: new_configuration_content, }, }; console.error(markup! { diff --git a/crates/rome_cli/src/execute/process_file.rs b/crates/rome_cli/src/execute/process_file.rs index f4f932b724d..cdac1b9a2c9 100644 --- a/crates/rome_cli/src/execute/process_file.rs +++ b/crates/rome_cli/src/execute/process_file.rs @@ -1,20 +1,22 @@ -mod format_file; -mod lint_file; - -use crate::execute::diagnostics::{ResultExt, ResultIoExt, SkippedDiagnostic, UnhandledDiagnostic}; -use crate::execute::process_file::format_file::{format_file, FormatFile}; -use crate::execute::process_file::lint_file::{lint_file, LintFile}; +mod check; +mod format; +mod lint; +mod organize_imports; +mod workspace_file; + +use crate::execute::diagnostics::{ResultExt, UnhandledDiagnostic}; +use crate::execute::process_file::check::check_file; +use crate::execute::process_file::format::format; +use crate::execute::process_file::lint::lint; use crate::execute::traverse::TraversalOptions; use crate::execute::TraversalMode; -use crate::{CliDiagnostic, FormatterReportFileDetail}; -use rome_diagnostics::{category, Context, DiagnosticExt, Error}; -use rome_fs::{OpenOptions, RomePath}; -use rome_service::workspace::{ - FeatureName, FeaturesBuilder, FileGuard, Language, OpenFileParams, RuleCategories, SupportKind, - SupportsFeatureParams, -}; +use crate::CliDiagnostic; +use rome_diagnostics::{category, DiagnosticExt, Error}; +use rome_fs::RomePath; +use rome_service::workspace::{FeatureName, FeaturesBuilder, SupportKind, SupportsFeatureParams}; +use std::marker::PhantomData; +use std::ops::Deref; use std::path::Path; -use std::sync::atomic::Ordering; #[derive(Debug)] pub(crate) enum FileStatus { @@ -46,6 +48,12 @@ pub(crate) enum Message { }, } +impl Message { + pub(crate) const fn is_diagnostic(&self) -> bool { + matches!(self, Message::Diff { .. } | Message::Diagnostics { .. }) + } +} + #[derive(Debug)] pub(crate) enum DiffKind { Format, @@ -73,6 +81,30 @@ where /// `skipped` counter pub(crate) type FileResult = Result; +/// Data structure that allows to pass [TraversalOptions] to multiple consumers, bypassing the +/// compiler constraints set by the lifetimes of the [TraversalOptions] +pub(crate) struct SharedTraversalOptions<'ctx, 'app> { + inner: &'app TraversalOptions<'ctx, 'app>, + _p: PhantomData<&'app ()>, +} + +impl<'ctx, 'app> SharedTraversalOptions<'ctx, 'app> { + fn new(t: &'app TraversalOptions<'ctx, 'app>) -> Self { + Self { + _p: PhantomData::default(), + inner: t, + } + } +} + +impl<'ctx, 'app> Deref for SharedTraversalOptions<'ctx, 'app> { + type Target = TraversalOptions<'ctx, 'app>; + + fn deref(&self) -> &Self::Target { + self.inner + } +} + /// This function performs the actual processing: it reads the file from disk /// and parse it; analyze and / or format it; then it either fails if error /// diagnostics were emitted, or compare the formatted code with the original @@ -81,11 +113,10 @@ pub(crate) type FileResult = Result; pub(crate) fn process_file(ctx: &TraversalOptions, path: &Path) -> FileResult { tracing::trace_span!("process_file", path = ?path).in_scope(move || { let rome_path = RomePath::new(path); - let file_features = ctx .workspace .file_features(SupportsFeatureParams { - path: rome_path.clone(), + path: rome_path, feature: FeaturesBuilder::new() .with_formatter() .with_linter() @@ -179,230 +210,22 @@ pub(crate) fn process_file(ctx: &TraversalOptions, path: &Path) -> FileResult { }; } - // NOTE: this is a work in progress that will be refactored over time - // - // With time, we will create a separate file for each traversal mode. Reason to do so - // is to keep the business logics of each traversal separate. Doing so would allow us to - // lower the changes to break the business logic of other traversal. - // - // This would definitely repeat the code, but it's worth the effort in the long run. + let shared_context = &SharedTraversalOptions::new(ctx); + ctx.increment_processed(); match ctx.execution.traversal_mode { TraversalMode::Lint { .. } => { // the unsupported case should be handled already at this point - if file_features.supports_for(&FeatureName::Lint) { - return lint_file(LintFile { ctx, path }); - } + lint(shared_context, path) } TraversalMode::Format { .. } => { // the unsupported case should be handled already at this point - if file_features.supports_for(&FeatureName::Format) { - return format_file(FormatFile { ctx, path }); - } - } - _ => {} - } - - let open_options = OpenOptions::default() - .read(true) - .write(ctx.execution.requires_write_access()); - let mut file = ctx - .fs - .open_with_options(path, open_options) - .with_file_path(path.display().to_string())?; - - let mut input = String::new(); - file.read_to_string(&mut input) - .with_file_path(path.display().to_string())?; - ctx.increment_processed(); - - let file_guard = FileGuard::open( - ctx.workspace, - OpenFileParams { - path: rome_path, - version: 0, - content: input.clone(), - language_hint: Language::default(), - }, - ) - .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?; - - let mut errors = 0; - - if let Some(fix_mode) = ctx.execution.as_fix_file_mode() { - let fixed = file_guard - .fix_file(*fix_mode, file_features.supports_for(&FeatureName::Format)) - .with_file_path_and_code(path.display().to_string(), category!("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_path(path.display().to_string())?; - file_guard.change_file(file.file_version(), fixed.code)?; - } - errors = fixed.errors; - } - if file_features.supports_for(&FeatureName::OrganizeImports) && ctx.execution.is_check() { - let sorted = file_guard.organize_imports().with_file_path_and_code( - path.display().to_string(), - category!("internalError/fs"), - )?; - - if sorted.code != input { - if ctx.execution.is_check_apply_unsafe() { - file.set_content(sorted.code.as_bytes()) - .with_file_path(path.display().to_string())?; - file_guard.change_file(file.file_version(), sorted.code)?; - } else { - errors += 1; - ctx.messages - .send(Message::Diff { - file_name: path.display().to_string(), - old: input.clone(), - new: sorted.code, - diff_kind: DiffKind::OrganizeImports, - }) - .ok(); - } + format(shared_context, path) } - } - - // If we are here, errors were emitted when applying code actions, so checking only for errors should be safe - if errors > 0 { - return Ok(FileStatus::Message(Message::ApplyError( - CliDiagnostic::file_apply_error(path.display().to_string()), - ))); - } else if ctx.execution.is_check_apply() || ctx.execution.is_check_apply_unsafe() { - return Ok(FileStatus::Success); - } - - let categories = - if ctx.execution.is_format() || !file_features.supports_for(&FeatureName::Lint) { - RuleCategories::SYNTAX - } else { - RuleCategories::SYNTAX | RuleCategories::LINT - }; - - let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed); - let result = file_guard - .pull_diagnostics(categories, max_diagnostics.into()) - .with_file_path_and_code(path.display().to_string(), category!("lint"))?; - - // In formatting mode, abort immediately if the file has errors - errors = result.errors; - match ctx.execution.traversal_mode() { - TraversalMode::Format { ignore_errors, .. } if errors > 0 => { - return Err(if *ignore_errors { - Message::from(SkippedDiagnostic.with_file_path(path.display().to_string())) - } else { - Message::Diagnostics { - name: path.display().to_string(), - content: input, - diagnostics: result.diagnostics.into_iter().map(Error::from).collect(), - skipped_diagnostics: result.skipped_diagnostics, - } - }); + TraversalMode::Check { .. } => check_file(shared_context, path, &file_features), + TraversalMode::CI => check_file(shared_context, path, &file_features), + TraversalMode::Migrate { .. } => { + unreachable!("The migration should not be called for this file") } - - _ => {} - } - - // In format mode the diagnostics have already been checked for errors - // at this point, so they can just be dropped now since we don't want - // to print syntax warnings for the format command - let no_diagnostics = result.diagnostics.is_empty() && result.skipped_diagnostics == 0; - let result = if no_diagnostics || ctx.execution.is_format() { - FileStatus::Success - } else { - FileStatus::Message(Message::Diagnostics { - name: path.display().to_string(), - content: input.clone(), - diagnostics: result.diagnostics.into_iter().map(Error::from).collect(), - skipped_diagnostics: result.skipped_diagnostics, - }) - }; - - if errors > 0 { - // Having errors is considered a "success" at this point because - // this is only reachable on the check / CI path (the parser result - // is checked for errors earlier on the format path, and that mode - // doesn't run the analyzer so no new diagnostics could have been - // added), and having errors on these paths still means the file - // was processed (added to the checked files counter) - return Ok(result); } - - if file_features.supports_for(&FeatureName::OrganizeImports) - // we want to print a diff only if we are in CI - // or we are running "check" or "check --apply" - && (ctx.execution.is_ci() || !ctx.execution.is_check_apply_unsafe()) - { - let sorted = file_guard - .organize_imports() - .with_file_path(path.display().to_string())?; - - if sorted.code != input { - ctx.messages - .send(Message::Diff { - file_name: path.display().to_string(), - old: input.clone(), - new: sorted.code, - diff_kind: DiffKind::OrganizeImports, - }) - .ok(); - } - } - - if file_features.supports_for(&FeatureName::Format) { - let should_write = match ctx.execution.traversal_mode() { - // In check mode do not run the formatter and return the result immediately, - // but only if the argument `--apply` is not passed. - TraversalMode::Check { .. } | TraversalMode::Lint { .. } => { - ctx.execution.as_fix_file_mode().is_some() - } - TraversalMode::CI { .. } => false, - TraversalMode::Format { write, .. } => *write, - TraversalMode::Migrate { write: dry_run, .. } => *dry_run, - }; - - let printed = file_guard - .format_file() - .with_file_path_and_code(path.display().to_string(), category!("format"))?; - - let output = printed.into_code(); - if output != input { - if should_write { - file.set_content(output.as_bytes()) - .with_file_path(path.display().to_string())?; - file_guard.change_file(file.file_version(), output)?; - } else { - if !ctx.execution.should_report_to_terminal() { - ctx.push_format_stat( - path.display().to_string(), - FormatterReportFileDetail { - formatted_content: Some(output.clone()), - }, - ) - } - // Returning the diff message will discard the content of - // diagnostics, meaning those would not be printed so they - // have to be manually sent through the console channel - if let FileStatus::Message(msg) = result { - ctx.messages.send(msg).ok(); - } - - return Ok(FileStatus::Message(Message::Diff { - file_name: path.display().to_string(), - old: input, - new: output, - diff_kind: DiffKind::Format, - })); - } - } - } - - Ok(result) }) } diff --git a/crates/rome_cli/src/execute/process_file/check.rs b/crates/rome_cli/src/execute/process_file/check.rs new file mode 100644 index 00000000000..497f9e6d875 --- /dev/null +++ b/crates/rome_cli/src/execute/process_file/check.rs @@ -0,0 +1,84 @@ +use crate::execute::process_file::format::format_with_guard; +use crate::execute::process_file::lint::lint_with_guard; +use crate::execute::process_file::organize_imports::organize_imports_with_guard; +use crate::execute::process_file::workspace_file::WorkspaceFile; +use crate::execute::process_file::{FileResult, FileStatus, Message, SharedTraversalOptions}; +use crate::CliDiagnostic; +use rome_service::workspace::{FeatureName, FileFeaturesResult}; +use std::path::Path; + +pub(crate) fn check_file<'ctx>( + ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + path: &Path, + file_features: &'ctx FileFeaturesResult, +) -> FileResult { + let mut has_errors = false; + let mut workspace_file = WorkspaceFile::new(ctx, path)?; + + if file_features.supports_for(&FeatureName::Lint) { + let lint_result = lint_with_guard(ctx, &mut workspace_file); + match lint_result { + Ok(status) => { + if let FileStatus::Message(msg) = status { + if msg.is_diagnostic() { + has_errors = true + } + ctx.push_message(msg); + } + } + Err(err) => { + ctx.push_message(err); + has_errors = true; + } + } + } + if file_features.supports_for(&FeatureName::OrganizeImports) { + let organize_imports_result = organize_imports_with_guard(ctx, &mut workspace_file); + match organize_imports_result { + Ok(status) => { + if let FileStatus::Message(msg) = status { + if msg.is_diagnostic() { + has_errors = true + } + ctx.push_message(msg); + } + } + Err(err) => { + ctx.push_message(err); + has_errors = true; + } + } + } + + if file_features.supports_for(&FeatureName::Format) { + let format_result = format_with_guard(ctx, &mut workspace_file); + match format_result { + Ok(status) => { + if let FileStatus::Message(msg) = status { + if msg.is_diagnostic() { + has_errors = true + } + ctx.push_message(msg); + } + } + Err(err) => { + ctx.push_message(err); + has_errors = true; + } + } + } + + if has_errors { + if ctx.execution.is_check_apply() || ctx.execution.is_check_apply_unsafe() { + Ok(FileStatus::Message(Message::ApplyError( + CliDiagnostic::file_apply_error(path.display().to_string()), + ))) + } else { + Ok(FileStatus::Message(Message::ApplyError( + CliDiagnostic::check_error(), + ))) + } + } else { + Ok(FileStatus::Success) + } +} diff --git a/crates/rome_cli/src/execute/process_file/format.rs b/crates/rome_cli/src/execute/process_file/format.rs new file mode 100644 index 00000000000..80bd9f52670 --- /dev/null +++ b/crates/rome_cli/src/execute/process_file/format.rs @@ -0,0 +1,101 @@ +use crate::execute::diagnostics::{ResultExt, SkippedDiagnostic}; +use crate::execute::process_file::workspace_file::WorkspaceFile; +use crate::execute::process_file::{ + DiffKind, FileResult, FileStatus, Message, SharedTraversalOptions, +}; +use crate::execute::TraversalMode; +use crate::FormatterReportFileDetail; +use rome_diagnostics::{category, DiagnosticExt, Error}; +use rome_service::workspace::RuleCategories; +use std::path::Path; +use std::sync::atomic::Ordering; + +pub(crate) fn format<'ctx>(ctx: &'ctx SharedTraversalOptions<'ctx, '_>, path: &Path) -> FileResult { + let mut workspace_file = WorkspaceFile::new(ctx, path)?; + format_with_guard(ctx, &mut workspace_file) +} + +pub(crate) fn format_with_guard<'ctx>( + ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + workspace_file: &mut WorkspaceFile, +) -> FileResult { + let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed); + let diagnostics_result = workspace_file + .guard() + .pull_diagnostics(RuleCategories::SYNTAX, max_diagnostics.into()) + .with_file_path_and_code( + workspace_file.path.display().to_string(), + category!("format"), + )?; + + let input = workspace_file.input()?; + let (should_write, ignore_errors) = match ctx.execution.traversal_mode { + TraversalMode::Format { + write, + ignore_errors, + .. + } => (write, ignore_errors), + + _ => ( + ctx.execution.is_check_apply() || ctx.execution.is_check_apply_unsafe(), + false, + ), + }; + + if diagnostics_result.errors > 0 { + return Err(if ignore_errors { + Message::from( + SkippedDiagnostic.with_file_path(workspace_file.path.display().to_string()), + ) + } else { + Message::Diagnostics { + name: workspace_file.path.display().to_string(), + content: input, + diagnostics: diagnostics_result + .diagnostics + .into_iter() + .map(Error::from) + .collect(), + skipped_diagnostics: diagnostics_result.skipped_diagnostics, + } + }); + } + + let printed = workspace_file + .guard() + .format_file() + .with_file_path_and_code( + workspace_file.path.display().to_string(), + category!("format"), + )?; + + let output = printed.into_code(); + + // NOTE: ignoring the + if ignore_errors { + return Ok(FileStatus::Ignored); + } + + if output != input { + if should_write { + workspace_file.update_file(output)?; + } else { + if !ctx.execution.should_report_to_terminal() { + ctx.push_format_stat( + workspace_file.path.display().to_string(), + FormatterReportFileDetail { + formatted_content: Some(output.clone()), + }, + ) + } + + return Ok(FileStatus::Message(Message::Diff { + file_name: workspace_file.path.display().to_string(), + old: input, + new: output, + diff_kind: DiffKind::Format, + })); + } + } + Ok(FileStatus::Success) +} diff --git a/crates/rome_cli/src/execute/process_file/format_file.rs b/crates/rome_cli/src/execute/process_file/format_file.rs deleted file mode 100644 index 96d72763a65..00000000000 --- a/crates/rome_cli/src/execute/process_file/format_file.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::execute::diagnostics::{ResultExt, ResultIoExt}; -use crate::execute::process_file::{DiffKind, FileResult, FileStatus, Message}; -use crate::execute::traverse::TraversalOptions; -use crate::execute::TraversalMode; -use crate::FormatterReportFileDetail; -use rome_diagnostics::category; -use rome_fs::{OpenOptions, RomePath}; -use rome_service::file_handlers::Language; -use rome_service::workspace::{FileGuard, OpenFileParams}; -use std::path::Path; - -pub(crate) struct FormatFile<'ctx, 'app> { - pub(crate) ctx: &'app TraversalOptions<'ctx, 'app>, - pub(crate) path: &'app Path, -} - -pub(crate) fn format_file(payload: FormatFile) -> FileResult { - let FormatFile { ctx, path } = payload; - let rome_path = RomePath::new(path); - let open_options = OpenOptions::default() - .read(true) - .write(ctx.execution.requires_write_access()); - let mut file = ctx - .fs - .open_with_options(path, open_options) - .with_file_path(path.display().to_string())?; - - let mut input = String::new(); - file.read_to_string(&mut input) - .with_file_path(path.display().to_string())?; - - let file_guard = FileGuard::open( - ctx.workspace, - OpenFileParams { - path: rome_path, - version: 0, - content: input.clone(), - language_hint: Language::default(), - }, - ) - .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?; - let printed = file_guard - .format_file() - .with_file_path_and_code(path.display().to_string(), category!("format"))?; - - let output = printed.into_code(); - let should_write = match ctx.execution.traversal_mode { - TraversalMode::Format { write, .. } => write, - _ => false, - }; - ctx.increment_processed(); - if output != input { - if should_write { - file.set_content(output.as_bytes()) - .with_file_path(path.display().to_string())?; - file_guard.change_file(file.file_version(), output)?; - } else { - if !ctx.execution.should_report_to_terminal() { - ctx.push_format_stat( - path.display().to_string(), - FormatterReportFileDetail { - formatted_content: Some(output.clone()), - }, - ) - } - - return Ok(FileStatus::Message(Message::Diff { - file_name: path.display().to_string(), - old: input, - new: output, - diff_kind: DiffKind::Format, - })); - } - } - Ok(FileStatus::Success) -} diff --git a/crates/rome_cli/src/execute/process_file/lint.rs b/crates/rome_cli/src/execute/process_file/lint.rs new file mode 100644 index 00000000000..e735476ca68 --- /dev/null +++ b/crates/rome_cli/src/execute/process_file/lint.rs @@ -0,0 +1,67 @@ +use crate::execute::diagnostics::ResultExt; +use crate::execute::process_file::workspace_file::WorkspaceFile; +use crate::execute::process_file::{FileResult, FileStatus, Message, SharedTraversalOptions}; +use crate::CliDiagnostic; +use rome_diagnostics::{category, Error}; +use rome_service::workspace::RuleCategories; +use std::path::Path; +use std::sync::atomic::Ordering; + +/// Lints a single file and returns a [FileResult] +pub(crate) fn lint<'ctx>(ctx: &'ctx SharedTraversalOptions<'ctx, '_>, path: &Path) -> FileResult { + let mut workspace_file = WorkspaceFile::new(ctx, path)?; + lint_with_guard(ctx, &mut workspace_file) +} + +pub(crate) fn lint_with_guard<'ctx>( + ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + workspace_file: &mut WorkspaceFile, +) -> FileResult { + let mut errors = 0; + let input = workspace_file.input()?; + + if let Some(fix_mode) = ctx.execution.as_fix_file_mode() { + let fixed = workspace_file + .guard() + .fix_file(*fix_mode, false) + .with_file_path_and_code( + workspace_file.path.display().to_string(), + category!("lint"), + )?; + + ctx.push_message(Message::SkippedFixes { + skipped_suggested_fixes: fixed.skipped_suggested_fixes, + }); + + if fixed.code != input { + workspace_file.update_file(fixed.code)?; + } + errors = fixed.errors; + } + + let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed); + let result = workspace_file + .guard() + .pull_diagnostics(RuleCategories::LINT, max_diagnostics.into()) + .with_file_path_and_code(workspace_file.path.display().to_string(), category!("lint"))?; + + let no_diagnostics = result.diagnostics.is_empty() && result.skipped_diagnostics == 0; + let result = if no_diagnostics || ctx.execution.is_format() { + FileStatus::Success + } else { + FileStatus::Message(Message::Diagnostics { + name: workspace_file.path.display().to_string(), + content: input, + diagnostics: result.diagnostics.into_iter().map(Error::from).collect(), + skipped_diagnostics: result.skipped_diagnostics, + }) + }; + + if errors > 0 { + return Ok(FileStatus::Message(Message::ApplyError( + CliDiagnostic::file_apply_error(workspace_file.path.display().to_string()), + ))); + } else { + Ok(result) + } +} diff --git a/crates/rome_cli/src/execute/process_file/lint_file.rs b/crates/rome_cli/src/execute/process_file/lint_file.rs deleted file mode 100644 index a869b61f03d..00000000000 --- a/crates/rome_cli/src/execute/process_file/lint_file.rs +++ /dev/null @@ -1,88 +0,0 @@ -use crate::execute::diagnostics::{ResultExt, ResultIoExt}; -use crate::execute::process_file::{FileResult, FileStatus, Message}; -use crate::execute::traverse::TraversalOptions; -use crate::CliDiagnostic; -use rome_diagnostics::{category, Error}; -use rome_fs::{OpenOptions, RomePath}; -use rome_service::file_handlers::Language; -use rome_service::workspace::{FileGuard, OpenFileParams, RuleCategories}; -use std::path::Path; -use std::sync::atomic::Ordering; - -pub(crate) struct LintFile<'ctx, 'app> { - pub(crate) ctx: &'app TraversalOptions<'ctx, 'app>, - pub(crate) path: &'app Path, -} - -/// Lints a single file and returns a [FileResult] -pub(crate) fn lint_file(payload: LintFile) -> FileResult { - let LintFile { ctx, path } = payload; - let rome_path = RomePath::new(path); - let mut errors = 0; - let open_options = OpenOptions::default() - .read(true) - .write(ctx.execution.requires_write_access()); - let mut file = ctx - .fs - .open_with_options(path, open_options) - .with_file_path(path.display().to_string())?; - - let mut input = String::new(); - file.read_to_string(&mut input) - .with_file_path(path.display().to_string())?; - - let file_guard = FileGuard::open( - ctx.workspace, - OpenFileParams { - path: rome_path, - version: 0, - content: input.clone(), - language_hint: Language::default(), - }, - ) - .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?; - - ctx.increment_processed(); - - if let Some(fix_mode) = ctx.execution.as_fix_file_mode() { - let fixed = file_guard - .fix_file(*fix_mode, false) - .with_file_path_and_code(path.display().to_string(), category!("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_path(path.display().to_string())?; - file_guard.change_file(file.file_version(), fixed.code)?; - } - errors = fixed.errors; - } - - let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed); - let result = file_guard - .pull_diagnostics(RuleCategories::LINT, max_diagnostics.into()) - .with_file_path_and_code(path.display().to_string(), category!("lint"))?; - - let no_diagnostics = result.diagnostics.is_empty() && result.skipped_diagnostics == 0; - let result = if no_diagnostics || ctx.execution.is_format() { - FileStatus::Success - } else { - FileStatus::Message(Message::Diagnostics { - name: path.display().to_string(), - content: input.clone(), - diagnostics: result.diagnostics.into_iter().map(Error::from).collect(), - skipped_diagnostics: result.skipped_diagnostics, - }) - }; - - if errors > 0 { - return Ok(FileStatus::Message(Message::ApplyError( - CliDiagnostic::file_apply_error(path.display().to_string()), - ))); - } else { - Ok(result) - } -} diff --git a/crates/rome_cli/src/execute/process_file/organize_imports.rs b/crates/rome_cli/src/execute/process_file/organize_imports.rs new file mode 100644 index 00000000000..1aa3d8e68c4 --- /dev/null +++ b/crates/rome_cli/src/execute/process_file/organize_imports.rs @@ -0,0 +1,36 @@ +use crate::execute::diagnostics::ResultExt; +use crate::execute::process_file::workspace_file::WorkspaceFile; +use crate::execute::process_file::{ + DiffKind, FileResult, FileStatus, Message, SharedTraversalOptions, +}; +use rome_diagnostics::category; + +/// Lints a single file and returns a [FileResult] +pub(crate) fn organize_imports_with_guard<'ctx>( + ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + workspace_file: &mut WorkspaceFile, +) -> FileResult { + let sorted = workspace_file + .guard() + .organize_imports() + .with_file_path_and_code( + workspace_file.path.display().to_string(), + category!("organizeImports"), + )?; + + let input = workspace_file.input()?; + if sorted.code != input { + if ctx.execution.is_check_apply_unsafe() { + workspace_file.update_file(sorted.code)?; + } else { + return Ok(FileStatus::Message(Message::Diff { + file_name: workspace_file.path.display().to_string(), + old: input, + new: sorted.code, + diff_kind: DiffKind::OrganizeImports, + })); + } + } + + Ok(FileStatus::Success) +} diff --git a/crates/rome_cli/src/execute/process_file/workspace_file.rs b/crates/rome_cli/src/execute/process_file/workspace_file.rs new file mode 100644 index 00000000000..59f63b8b016 --- /dev/null +++ b/crates/rome_cli/src/execute/process_file/workspace_file.rs @@ -0,0 +1,73 @@ +use crate::execute::diagnostics::{ResultExt, ResultIoExt}; +use crate::execute::process_file::SharedTraversalOptions; +use rome_diagnostics::{category, Error}; +use rome_fs::{File, OpenOptions, RomePath}; +use rome_service::file_handlers::Language; +use rome_service::workspace::{FileGuard, OpenFileParams}; +use rome_service::{Workspace, WorkspaceError}; +use std::path::{Path, PathBuf}; + +/// Small wrapper that holds information and operations around the current processed file +pub(crate) struct WorkspaceFile<'ctx, 'app> { + guard: FileGuard<'app, dyn Workspace + 'ctx>, + file: Box, + pub(crate) path: PathBuf, +} + +impl<'ctx, 'app> WorkspaceFile<'ctx, 'app> { + /// It attempts to read the file from disk, creating a [FileGuard] and + /// saving these information internally + pub(crate) fn new( + ctx: &SharedTraversalOptions<'ctx, 'app>, + path: &Path, + ) -> Result { + let rome_path = RomePath::new(path); + let open_options = OpenOptions::default() + .read(true) + .write(ctx.execution.requires_write_access()); + let mut file = ctx + .fs + .open_with_options(path, open_options) + .with_file_path(path.display().to_string())?; + + let mut input = String::new(); + file.read_to_string(&mut input) + .with_file_path(path.display().to_string())?; + + let guard = FileGuard::open( + ctx.workspace, + OpenFileParams { + path: rome_path, + version: 0, + content: input.clone(), + language_hint: Language::default(), + }, + ) + .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?; + + Ok(Self { + file, + guard, + path: PathBuf::from(path), + }) + } + + pub(crate) fn guard(&self) -> &FileGuard<'app, dyn Workspace + 'ctx> { + &self.guard + } + + pub(crate) fn input(&self) -> Result { + self.guard().get_file_content() + } + + /// It updates the workspace file with `new_content` + pub(crate) fn update_file(&mut self, new_content: impl Into) -> Result<(), Error> { + let new_content = new_content.into(); + self.file + .set_content(new_content.as_bytes()) + .with_file_path(self.path.display().to_string())?; + self.guard + .change_file(self.file.file_version(), new_content)?; + Ok(()) + } +} diff --git a/crates/rome_cli/src/execute/std_in.rs b/crates/rome_cli/src/execute/std_in.rs index 94c2d99edf5..9eb35b3fba6 100644 --- a/crates/rome_cli/src/execute/std_in.rs +++ b/crates/rome_cli/src/execute/std_in.rs @@ -127,10 +127,10 @@ pub(crate) fn run<'a>( } } else { let diagnostic = FormatDiffDiagnostic { - file_name: &rome_path.display().to_string(), + file_name: rome_path.display().to_string(), diff: ContentDiffAdvice { - new: printed.as_code(), - old: content, + new: printed.as_code().to_string(), + old: content.to_string(), }, }; diagnostics.push(rome_diagnostics::serde::Diagnostic::new(diagnostic)); diff --git a/crates/rome_cli/src/execute/traverse.rs b/crates/rome_cli/src/execute/traverse.rs index 137056498ae..431f5ce0c2d 100644 --- a/crates/rome_cli/src/execute/traverse.rs +++ b/crates/rome_cli/src/execute/traverse.rs @@ -291,7 +291,7 @@ fn process_messages(options: ProcessMessagesOptions) { let mut is_msg_open = true; let mut is_report_open = true; - + let mut diagnostics_to_print = vec![]; while is_msg_open || is_report_open { let msg = select! { recv(recv_msgs) -> msg => match msg { @@ -334,9 +334,7 @@ fn process_messages(options: ProcessMessagesOptions) { not_printed_diagnostics += 1; } if mode.should_report_to_terminal() && should_print { - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&error) } else { PrintDiagnostic::simple(&error) }} - }); + diagnostics_to_print.push(Error::from(error)); } } @@ -381,9 +379,7 @@ fn process_messages(options: ProcessMessagesOptions) { if mode.should_report_to_terminal() { if should_print { - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&err) } else { PrintDiagnostic::simple(&err) }} - }); + diagnostics_to_print.push(err); } } else { let location = err.location(); @@ -423,9 +419,7 @@ fn process_messages(options: ProcessMessagesOptions) { } let diag = diag.with_file_path(&name).with_file_source_code(&content); - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(diag); } } else { for diag in diagnostics { @@ -449,9 +443,7 @@ fn process_messages(options: ProcessMessagesOptions) { if should_print { let diag = diag.with_file_path(&name).with_file_source_code(&content); - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(diag) } } else { report.push_detail_report(ReportKind::Error( @@ -494,54 +486,46 @@ fn process_messages(options: ProcessMessagesOptions) { match diff_kind { DiffKind::Format => { let diag = CIFormatDiffDiagnostic { - file_name: &file_name, + file_name: file_name.clone(), diff: ContentDiffAdvice { - old: &old, - new: &new, + old: old.clone(), + new: new.clone(), }, }; - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(Error::from(diag)) } DiffKind::OrganizeImports => { let diag = CIOrganizeImportsDiffDiagnostic { - file_name: &file_name, + file_name: file_name.clone(), diff: ContentDiffAdvice { - old: &old, - new: &new, + old: old.clone(), + new: new.clone(), }, }; - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(Error::from(diag)) } }; } else { match diff_kind { DiffKind::Format => { let diag = FormatDiffDiagnostic { - file_name: &file_name, + file_name: file_name.clone(), diff: ContentDiffAdvice { - old: &old, - new: &new, + old: old.clone(), + new: new.clone(), }, }; - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(Error::from(diag)) } DiffKind::OrganizeImports => { let diag = OrganizeImportsDiffDiagnostic { - file_name: &file_name, + file_name: file_name.clone(), diff: ContentDiffAdvice { - old: &old, - new: &new, + old: old.clone(), + new: new.clone(), }, }; - console.error(markup! { - {if verbose { PrintDiagnostic::verbose(&diag) } else { PrintDiagnostic::simple(&diag) }} - }); + diagnostics_to_print.push(Error::from(diag)) } }; } @@ -560,6 +544,12 @@ fn process_messages(options: ProcessMessagesOptions) { } } + for diagnostic in diagnostics_to_print { + console.error(markup! { + {if verbose { PrintDiagnostic::verbose(&diagnostic) } else { PrintDiagnostic::simple(&diagnostic) }} + }); + } + if mode.is_check() && total_skipped_suggested_fixes > 0 { console.log(markup! { "Skipped "{total_skipped_suggested_fixes}" suggested fixes.\n" diff --git a/crates/rome_cli/tests/cases/config_extends.rs b/crates/rome_cli/tests/cases/config_extends.rs index 0796e5d6187..3082291132d 100644 --- a/crates/rome_cli/tests/cases/config_extends.rs +++ b/crates/rome_cli/tests/cases/config_extends.rs @@ -33,7 +33,7 @@ fn extends_config_ok_formatter_no_linter() { Args::from(&[("check"), test_file.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), diff --git a/crates/rome_cli/tests/commands/check.rs b/crates/rome_cli/tests/commands/check.rs index 14416c0e0fb..58812d6243f 100644 --- a/crates/rome_cli/tests/commands/check.rs +++ b/crates/rome_cli/tests/commands/check.rs @@ -39,6 +39,8 @@ const FIX_BEFORE: &str = " "; const FIX_AFTER: &str = "1 >= 0; "; +const CHECK_FORMAT_AFTER: &str = "1 >= -0; +"; const APPLY_SUGGESTED_BEFORE: &str = "let a = 4; debugger; @@ -189,9 +191,10 @@ fn maximum_diagnostics() { .filter(|m| m.level == LogLevel::Log) .any(|m| { let content = format!("{:?}", m.content); + dbg!(&content); content.contains("The number of diagnostics exceeds the number allowed by Rome") && content.contains("Diagnostics not shown") - && content.contains("76") + && content.contains("78") })); assert_cli_snapshot(SnapshotPayload::new( @@ -432,7 +435,7 @@ fn no_lint_if_linter_is_disabled_when_run_apply() { .read_to_string(&mut buffer) .unwrap(); - assert_eq!(buffer, FIX_AFTER); + assert_eq!(buffer, CHECK_FORMAT_AFTER); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -460,7 +463,7 @@ fn no_lint_if_linter_is_disabled() { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); let mut buffer = String::new(); fs.open(file_path) @@ -583,7 +586,7 @@ fn downgrade_severity() { println!("{console:?}"); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); let messages = &console.out_buffer; @@ -676,7 +679,7 @@ fn no_lint_when_file_is_ignored() { ]), ); - assert!(result.is_err(), "run_cli returned {result:?}"); + assert!(result.is_ok(), "run_cli returned {result:?}"); let mut buffer = String::new(); fs.open(file_path) @@ -684,7 +687,7 @@ fn no_lint_when_file_is_ignored() { .read_to_string(&mut buffer) .unwrap(); - assert_eq!(buffer, FIX_BEFORE); + assert_eq!(buffer, CHECK_FORMAT_AFTER); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -720,7 +723,7 @@ fn no_lint_if_files_are_listed_in_ignore_option() { ]), ); - assert!(result.is_err(), "run_cli returned {result:?}"); + assert!(result.is_ok(), "run_cli returned {result:?}"); let mut buffer = String::new(); fs.open(file_path_test1) @@ -736,7 +739,7 @@ fn no_lint_if_files_are_listed_in_ignore_option() { .read_to_string(&mut buffer) .unwrap(); - assert_eq!(buffer, FIX_BEFORE); + assert_eq!(buffer, CHECK_FORMAT_AFTER); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -1174,6 +1177,8 @@ fn max_diagnostics_default() { node.content.contains("useWhile") || node.content.contains("useBlockStatements") || node.content.contains("noConstantCondition") + || node.content.contains("format") + || node.content.contains("internalError/io") }); if is_diagnostic { @@ -1223,9 +1228,12 @@ fn max_diagnostics() { for msg in console.out_buffer { let MarkupBuf(nodes) = &msg.content; let is_diagnostic = nodes.iter().any(|node| { + dbg!(&node.content); node.content.contains("useWhile") || node.content.contains("useBlockStatements") || node.content.contains("noConstantCondition") + || node.content.contains("format") + || node.content.contains("Some errors were emitted while") }); if is_diagnostic { @@ -1288,7 +1296,7 @@ a == b;", Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -1693,7 +1701,7 @@ fn top_level_all_down_level_not_all() { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -1778,7 +1786,7 @@ fn ignore_configured_globals() { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -1899,7 +1907,7 @@ fn ignore_vcs_os_independent_parse() { ]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -2126,7 +2134,7 @@ fn should_apply_correct_file_source() { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); let mut buffer = String::new(); fs.open(file_path) @@ -2222,7 +2230,7 @@ fn should_not_enable_all_recommended_rules() { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -2325,7 +2333,7 @@ if (true) { Args::from(&[("check"), file_path.as_os_str().to_str().unwrap()]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), @@ -2357,7 +2365,7 @@ fn apply_bogus_argument() { ]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), diff --git a/crates/rome_cli/tests/commands/ci.rs b/crates/rome_cli/tests/commands/ci.rs index 608da1882cd..0e5372684a7 100644 --- a/crates/rome_cli/tests/commands/ci.rs +++ b/crates/rome_cli/tests/commands/ci.rs @@ -593,6 +593,8 @@ fn max_diagnostics_default() { let is_diagnostic = nodes.iter().any(|node| { node.content .contains("File content differs from formatting output") + || node.content.contains("format") + || node.content.contains("internalError/io") }); if is_diagnostic { @@ -646,6 +648,8 @@ fn max_diagnostics() { let is_diagnostic = nodes.iter().any(|node| { node.content .contains("File content differs from formatting output") + || node.content.contains("format") + || node.content.contains("internalError/io") }); if is_diagnostic { diff --git a/crates/rome_cli/tests/main.rs b/crates/rome_cli/tests/main.rs index a981854be5a..18940ab92e4 100644 --- a/crates/rome_cli/tests/main.rs +++ b/crates/rome_cli/tests/main.rs @@ -285,7 +285,7 @@ mod configuration { Args::from(&[("check"), ("file.js")]), ); - assert!(result.is_ok(), "run_cli returned {result:?}"); + assert!(result.is_err(), "run_cli returned {result:?}"); } } diff --git a/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap b/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap index c0d0e6440ce..986c4fed9cf 100644 --- a/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap +++ b/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap @@ -24,6 +24,17 @@ expression: content ```js debugger; console.log("string"); +``` + +# Termination Message + +```block +internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Some errors were emitted while running checks + + + ``` # Emitted Messages @@ -39,6 +50,14 @@ test.js format ━━━━━━━━━━━━━━━━━━━━━ 3 │ + +``` + +```block +internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Some errors were emitted while running checks + + ``` ```block diff --git a/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_linter_not_formatter.snap b/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_linter_not_formatter.snap index 8d384428cd3..c52067330b1 100644 --- a/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_linter_not_formatter.snap +++ b/crates/rome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_linter_not_formatter.snap @@ -64,6 +64,27 @@ test.js:1:1 lint/suspicious/noDebugger FIXABLE ━━━━━━━━━━ ``` +```block +test.js format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Formatter would have printed the following content: + + 1 │ - debugger;·console.log("string");· + 1 │ + debugger; + 2 │ + console.log("string"); + 3 │ + + + +``` + +```block +internalError/io ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Some errors were emitted while running checks + + +``` + ```block Checked 1 file(s) in