Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
feat(rome_cli): format code via stdin (#3043)
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico committed Aug 11, 2022
1 parent 2713db0 commit 4611107
Show file tree
Hide file tree
Showing 28 changed files with 522 additions and 205 deletions.
9 changes: 3 additions & 6 deletions crates/rome_cli/src/commands/check.rs
@@ -1,8 +1,5 @@
use crate::commands::format::apply_format_settings_from_cli;
use crate::{
traversal::{traverse, TraversalMode},
CliSession, Termination,
};
use crate::{execute_mode, CliSession, ExecutionMode, Termination};
use rome_diagnostics::MAXIMUM_DISPLAYABLE_DIAGNOSTICS;
use rome_service::load_config;
use rome_service::settings::WorkspaceSettings;
Expand Down Expand Up @@ -63,8 +60,8 @@ pub(crate) fn check(mut session: CliSession) -> Result<(), Termination> {
Some(FixFileMode::SafeAndSuggestedFixes)
};

traverse(
TraversalMode::Check {
execute_mode(
ExecutionMode::Check {
max_diagnostics,
fix_file_mode,
},
Expand Down
7 changes: 2 additions & 5 deletions crates/rome_cli/src/commands/ci.rs
@@ -1,7 +1,4 @@
use crate::{
traversal::{traverse, TraversalMode},
CliSession, Termination,
};
use crate::{execute_mode, CliSession, ExecutionMode, Termination};
use rome_service::load_config;
use rome_service::settings::WorkspaceSettings;
use rome_service::workspace::UpdateSettingsParams;
Expand All @@ -26,5 +23,5 @@ pub(crate) fn ci(mut session: CliSession) -> Result<(), Termination> {
settings: workspace_settings,
})?;

traverse(TraversalMode::CI, session)
execute_mode(ExecutionMode::CI, session)
}
37 changes: 26 additions & 11 deletions crates/rome_cli/src/commands/format.rs
@@ -1,21 +1,14 @@
use rome_formatter::IndentStyle;
use rome_service::{load_config, settings::WorkspaceSettings, workspace::UpdateSettingsParams};
use std::path::PathBuf;

use crate::{
traversal::{traverse, TraversalMode},
CliSession, Termination,
};
use crate::{execute_mode, CliSession, ExecutionMode, Termination};

/// Handler for the "format" command of the Rome CLI
pub(crate) fn format(mut session: CliSession) -> Result<(), Termination> {
let configuration = load_config(&session.app.fs)?;
let mut workspace_settings = WorkspaceSettings::default();

if let Some(configuration) = &configuration {
if configuration.is_formatter_disabled() {
return Ok(());
}
}
if let Some(configuration) = configuration {
workspace_settings.merge_with_configuration(configuration);
}
Expand All @@ -24,6 +17,27 @@ pub(crate) fn format(mut session: CliSession) -> Result<(), Termination> {

let is_write = session.args.contains("--write");
let ignore_errors = session.args.contains("--skip-errors");
let stdin_file_path: Option<String> = session
.args
.opt_value_from_str("--stdin-file-path")
.map_err(|source| Termination::ParseError {
argument: "--stdin-file-path",
source,
})?;

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(Termination::MissingArgument { argument: "stdin" });
}
} else {
None
};

session
.app
Expand All @@ -32,10 +46,11 @@ pub(crate) fn format(mut session: CliSession) -> Result<(), Termination> {
settings: workspace_settings,
})?;

traverse(
TraversalMode::Format {
execute_mode(
ExecutionMode::Format {
ignore_errors,
write: is_write,
stdin,
},
session,
)
Expand Down
1 change: 1 addition & 0 deletions crates/rome_cli/src/commands/help.rs
Expand Up @@ -43,6 +43,7 @@ const FORMAT_OPTIONS: Markup = markup! {
"<Dim>"--indent-size <number>"</Dim>" If the indentation style is set to spaces, determine how many spaces should be used for indentation (default: 2)
"<Dim>"--line-width <number>"</Dim>" Determine how many characters the formatter is allowed to print in a single line (default: 80)
"<Dim>"--quote-style <single|double>"</Dim>" Determine whether the formatter should use single or double quotes for strings (default: double)
"<Dim>"--stdin-file-path <string>"</Dim>" Mandatory argument to use when piping content via standard input, e.g. echo 'let a;' | rome format --stdin-filepath file.js
"
};

Expand Down
119 changes: 119 additions & 0 deletions crates/rome_cli/src/execute.rs
@@ -0,0 +1,119 @@
use crate::traversal::traverse;
use crate::{CliSession, Termination};
use rome_console::{markup, ConsoleExt};
use rome_fs::RomePath;
use rome_service::workspace::{
FeatureName, FixFileMode, FormatFileParams, OpenFileParams, SupportsFeatureParams,
};
use std::path::PathBuf;

#[derive(Clone)]
pub(crate) enum ExecutionMode {
/// 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,

/// 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,
/// This mode is enabled when running the command `rome format`
Format {
/// It ignores parse errors
ignore_errors: bool,
/// It writes the new content on file
write: bool,
/// An optional tuple.
/// 1. The virtual path to the file
/// 2. The content of the file
stdin: Option<(PathBuf, String)>,
},
}

impl ExecutionMode {
pub(crate) fn get_max_diagnostics(&self) -> Option<u16> {
match self {
ExecutionMode::Check {
max_diagnostics, ..
} => Some(*max_diagnostics),
_ => None,
}
}

/// `true` only when running the traversal in [TraversalMode::Check] and `should_fix` is `true`
pub(crate) fn as_fix_file_mode(&self) -> Option<&FixFileMode> {
if let ExecutionMode::Check { fix_file_mode, .. } = self {
fix_file_mode.as_ref()
} else {
None
}
}

pub(crate) fn is_ci(&self) -> bool {
matches!(self, ExecutionMode::CI { .. })
}

pub(crate) fn is_check(&self) -> bool {
matches!(self, ExecutionMode::Check { .. })
}

pub(crate) fn is_format(&self) -> bool {
matches!(self, ExecutionMode::Format { .. })
}

pub(crate) fn as_stdin_file(&self) -> Option<&(PathBuf, String)> {
match self {
ExecutionMode::Format { stdin, .. } => stdin.as_ref(),
_ => None,
}
}
}

/// Based on the [mode](ExecutionMode), the function might launch a traversal of the file system
/// or handles the stdin file.
pub(crate) fn execute_mode(
mode: ExecutionMode,
mut session: CliSession,
) -> Result<(), Termination> {
// don't do any traversal if there's some content coming from stdin
if let Some((path, content)) = mode.as_stdin_file() {
let workspace = &*session.app.workspace;
let console = &mut *session.app.console;
let rome_path = RomePath::new(path, 0);

if mode.is_format() {
let can_format = workspace.supports_feature(SupportsFeatureParams {
path: rome_path.clone(),
feature: FeatureName::Format,
});
if can_format {
workspace.open_file(OpenFileParams {
path: rome_path.clone(),
version: 0,
content: content.into(),
})?;
let printed = workspace.format_file(FormatFileParams { path: rome_path })?;

console.log(markup! {
{printed.as_code()}
});
} else {
console.log(markup! {
{content}
});
console.error(markup!{
<Warn>"The content was not formatted because the formatter is currently disabled."</Warn>
})
}
}

Ok(())
} else {
traverse(mode, session)
}
}
2 changes: 2 additions & 0 deletions crates/rome_cli/src/lib.rs
Expand Up @@ -7,11 +7,13 @@ use rome_flags::FeatureFlags;
use rome_service::App;

mod commands;
mod execute;
mod metrics;
mod panic;
mod termination;
mod traversal;

pub(crate) use execute::{execute_mode, ExecutionMode};
pub use panic::setup_panic_handler;
pub use termination::Termination;

Expand Down

0 comments on commit 4611107

Please sign in to comment.