This repository has been archived by the owner on Aug 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 664
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rome_cli): command
rome lint
(#4629)
- Loading branch information
Showing
67 changed files
with
5,644 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use crate::cli_options::CliOptions; | ||
use crate::configuration::{load_configuration, LoadedConfiguration}; | ||
use crate::vcs::store_path_to_ignore_from_vcs; | ||
use crate::{execute_mode, CliDiagnostic, CliSession, Execution, TraversalMode}; | ||
use rome_service::workspace::{FixFileMode, UpdateSettingsParams}; | ||
use rome_service::{Configuration, MergeWith}; | ||
use std::ffi::OsString; | ||
use std::path::PathBuf; | ||
|
||
pub(crate) struct LintCommandPayload { | ||
pub(crate) apply: bool, | ||
pub(crate) apply_unsafe: bool, | ||
pub(crate) cli_options: CliOptions, | ||
pub(crate) configuration: Option<Configuration>, | ||
pub(crate) paths: Vec<OsString>, | ||
pub(crate) stdin_file_path: Option<String>, | ||
} | ||
|
||
/// Handler for the "lint" command of the Rome CLI | ||
pub(crate) fn lint( | ||
mut session: CliSession, | ||
payload: LintCommandPayload, | ||
) -> Result<(), CliDiagnostic> { | ||
let LintCommandPayload { | ||
apply, | ||
apply_unsafe, | ||
cli_options, | ||
configuration, | ||
paths, | ||
stdin_file_path, | ||
} = payload; | ||
|
||
let fix_file_mode = if apply && apply_unsafe { | ||
return Err(CliDiagnostic::incompatible_arguments( | ||
"--apply", | ||
"--apply-unsafe", | ||
)); | ||
} else if !apply && !apply_unsafe { | ||
None | ||
} else if apply && !apply_unsafe { | ||
Some(FixFileMode::SafeFixes) | ||
} else { | ||
Some(FixFileMode::SafeAndUnsafeFixes) | ||
}; | ||
|
||
let LoadedConfiguration { | ||
configuration: mut fs_configuration, | ||
directory_path: configuration_path, | ||
.. | ||
} = load_configuration(&mut session, &cli_options)? | ||
.or_diagnostic(session.app.console, cli_options.verbose)?; | ||
|
||
fs_configuration.merge_with(configuration); | ||
|
||
// check if support of git ignore files is enabled | ||
let vcs_base_path = configuration_path.or(session.app.fs.working_directory()); | ||
store_path_to_ignore_from_vcs( | ||
&mut session, | ||
&mut fs_configuration, | ||
vcs_base_path, | ||
&cli_options, | ||
)?; | ||
|
||
let stdin = if let Some(stdin_file_path) = stdin_file_path { | ||
let console = &mut session.app.console; | ||
let input_code = console.read(); | ||
if let Some(input_code) = input_code { | ||
let path = PathBuf::from(stdin_file_path); | ||
Some((path, input_code)) | ||
} else { | ||
// we provided the argument without a piped stdin, we bail | ||
return Err(CliDiagnostic::missing_argument("stdin", "lint")); | ||
} | ||
} else { | ||
None | ||
}; | ||
|
||
session | ||
.app | ||
.workspace | ||
.update_settings(UpdateSettingsParams { | ||
configuration: fs_configuration, | ||
})?; | ||
|
||
execute_mode( | ||
Execution::new(TraversalMode::Lint { | ||
fix_file_mode, | ||
stdin, | ||
}), | ||
session, | ||
&cli_options, | ||
paths, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
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"))?; | ||
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, | ||
}) | ||
}; | ||
ctx.increment_processed(); | ||
if errors > 0 { | ||
return Ok(FileStatus::Message(Message::ApplyError( | ||
CliDiagnostic::file_apply_error(path.display().to_string()), | ||
))); | ||
} else { | ||
Ok(result) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.