feat(rome_cli): Add `version` command
MODIFY
.github/workflows/release_lsp.yml
.github/workflows/release_lsp.yml
@@ -14,7 +14,11 @@ jobs:
name: Check version
runs-on: ubuntu-latest
outputs:
+ # LSP Extension Version
version: ${{ env.version }}
+
+ # Version of the Rome binary
+ rome_version: ${{ env.rome_version }}
prerelease: ${{ env.prerelease }}
nightly: ${{ env.nightly }}
version_changed: ${{ steps.version.outputs.changed }}
@@ -34,21 +38,35 @@ jobs:
diff-search: true
file-name: editors/vscode/package.json
+ - name: Check Rome version changes
+ uses: EndBug/version-check@v1
+ if: env.nightly != 'true'
+ id: rome_version
+ with:
+ diff-search: true
+ file-name: npm/rome/package.json
+
- name: Set version name
- run: echo "version=${{ steps.version.outputs.version }}" >> $GITHUB_ENV
+ run: |
+ echo "version=${{ steps.version.outputs.version }}" >> $GITHUB_ENV
+ echo "rome_version=${{ steps.rome_version.outputs.version }}" >> $GITHUB_ENV
- name: Check prerelease status
id: prerelease
if: env.nightly == 'true' || steps.version.outputs.type == 'prerelease' || steps.version.outputs.type == 'prepatch' || steps.version.outputs.type == 'premajor' || steps.version.outputs.type == 'preminor'
- working-directory: editors/vscode
run: |
echo "prerelease=true" >> $GITHUB_ENV
- echo "version=$(node ./scripts/updateVersionForPrerelease.mjs)" >> $GITHUB_ENV
+ echo "version=$(node ./editors/vscode/scripts/updateVersionForPrerelease.mjs)" >> $GITHUB_ENV
+ echo "rome_version=$(node ./npm/rome/scripts/update-nightly-version.mjs)" >> $GITHUB_ENV
- name: Check version status
if: steps.version.outputs.changed == 'true'
run: 'echo "Version change found! New version: ${{ steps.version.outputs.version }} (${{ steps.version.outputs.version_type }})"'
+ - name: Rome Check version status
+ if: steps.rome_version.outputs.changed == 'true'
+ run: 'echo "Rome Version change found! New version: ${{ steps.rome_version.outputs.version }} (${{ steps.rome_version.outputs.version_type }})"'
+
build:
strategy:
matrix:
@@ -107,6 +125,7 @@ jobs:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
# Strip all debug symbols from the resulting binaries
RUSTFLAGS: "-C strip=symbols"
+ ROME_VERSION: ${{ needs.check.outputs.rome_version }}
- name: Copy LSP binary
if: matrix.os == 'windows-2022'

MODIFY
crates/rome_cli/src/commands/help.rs
crates/rome_cli/src/commands/help.rs
use rome_console::{markup, ConsoleExt, Markup};
-use crate::{CliSession, Termination};
-
-const VERSION: &str = match option_env!("ROME_VERSION") {
- Some(version) => version,
- None => env!("CARGO_PKG_VERSION"),
-};
+use crate::{CliSession, Termination, VERSION};
const MAIN: Markup = markup! {
"Rome CLI v"{VERSION}"
@@ -18,10 +13,12 @@ const MAIN: Markup = markup! {
- "<Emphasis>"init"</Emphasis>" Bootstraps a new rome project
- "<Emphasis>"start"</Emphasis>" Start the Rome daemon server process
- "<Emphasis>"stop"</Emphasis>" Stop the Rome daemon server process
+ - "<Emphasis>"version"</Emphasis>" Shows the Rome version information and quit
"<Emphasis>"OPTIONS:"</Emphasis>"
"<Dim>"--no-colors"</Dim>" Disable the formatting of markup (print everything as plain text)
"<Dim>"--use-server"</Dim>" Connect to a running instance of the Rome daemon server
+ "<Dim>"--version"</Dim>" Show the Rome version information and quit
"
};
@@ -96,39 +93,31 @@ const STOP: Markup = markup! {
rome stop"
};
-pub(crate) fn help(mut session: CliSession, command: Option<&str>) -> Result<(), Termination> {
- match command {
- Some("help") | None => {
- session.app.console.log(MAIN);
- Ok(())
- }
- Some("check") => {
- session.app.console.log(CHECK);
- Ok(())
- }
- Some("ci") => {
- session.app.console.log(CI);
- Ok(())
- }
- Some("format") => {
- session.app.console.log(FORMAT);
- Ok(())
- }
- Some("init") => {
- session.app.console.log(INIT);
- Ok(())
- }
- Some("start") => {
- session.app.console.log(START);
- Ok(())
- }
- Some("stop") => {
- session.app.console.log(STOP);
- Ok(())
- }
+const VERSION_HELP_TEXT: Markup = markup! {
+"Rome version: Show the Rome version information
+
+"<Emphasis>"USAGE:"</Emphasis>"
+ rome version"
+};
- Some(cmd) => Err(Termination::UnknownCommandHelp {
+pub(crate) fn help(mut session: CliSession, command: Option<&str>) -> Result<(), Termination> {
+ let help_text = match command {
+ Some("help") | None => MAIN,
+ Some("check") => CHECK,
+ Some("ci") => CI,
+ Some("format") => FORMAT,
+ Some("init") => INIT,
+ Some("start") => START,
+ Some("stop") => STOP,
+ Some("version") => VERSION_HELP_TEXT,
+
+ Some(cmd) => {
+ return Err(Termination::UnknownCommandHelp {
command: cmd.into(),
- }),
+ })
}
+ };
+
+ session.app.console.log(help_text);
+ Ok(())
}

MODIFY
crates/rome_cli/src/commands/mod.rs
crates/rome_cli/src/commands/mod.rs
@@ -4,3 +4,4 @@ pub(crate) mod daemon;
pub(crate) mod format;
pub(crate) mod help;
pub(crate) mod init;
+pub(crate) mod version;

ADD
crates/rome_cli/src/commands/version.rs
+use rome_console::{markup, ConsoleExt};
+
+use crate::{CliSession, Termination, VERSION};
+
+/// Handler for the `--version` argument. Prints a brief rome version.
+pub(crate) fn brief_version(mut session: CliSession) -> Result<(), Termination> {
+ session
+ .app
+ .console
+ .log(markup!("Rome CLI version "{VERSION}));
+
+ Ok(())
+}
+
+/// Handle of the `version` command. Prints a more in detail version of rome.
+pub(crate) fn full_version(mut session: CliSession) -> Result<(), Termination> {
+ session.app.console.log(markup! {
+ "CLI: "{VERSION}
+ });
+
+ match session.app.workspace.server_info() {
+ None => {
+ session.app.console.log(markup! {
+ "Server: "<Dim>"not connected"</Dim>
+ });
+ }
+ Some(info) => {
+ let version = info.version.as_deref().unwrap_or("-");
+
+ session.app.console.log(markup! {
+"Server:
+ Name: "{info.name}"
+ Version: "{version}
+ });
+ }
+ };
+
+ Ok(())
+}

MODIFY
crates/rome_cli/src/lib.rs
crates/rome_cli/src/lib.rs
@@ -30,6 +30,11 @@ pub use reports::{
pub use service::{open_transport, SocketTransport};
pub use termination::Termination;
+pub(crate) const VERSION: &str = match option_env!("ROME_VERSION") {
+ Some(version) => version,
+ None => env!("CARGO_PKG_VERSION"),
+};
+
/// Global context for an execution of the CLI
pub struct CliSession<'app> {
/// Instance of [App] used by this run of the CLI
@@ -76,29 +81,32 @@ impl<'app> CliSession<'app> {
let result = match subcommand.as_deref() {
// Print the help for the subcommand if it was called with `--help`
- Some(cmd) if has_help => crate::commands::help::help(self, Some(cmd)),
+ Some(cmd) if has_help => commands::help::help(self, Some(cmd)),
- Some("check") if !is_empty => crate::commands::check::check(self),
- Some("ci") if !is_empty => crate::commands::ci::ci(self),
- Some("format") if !is_empty => crate::commands::format::format(self),
+ Some("check") if !is_empty => commands::check::check(self),
+ Some("ci") if !is_empty => commands::ci::ci(self),
+ Some("format") if !is_empty => commands::format::format(self),
- Some("start") => crate::commands::daemon::start(self),
- Some("stop") => crate::commands::daemon::stop(self),
+ Some("start") => commands::daemon::start(self),
+ Some("stop") => commands::daemon::stop(self),
// Internal commands
- Some("__run_server") => crate::commands::daemon::run_server(),
- Some("__print_socket") => crate::commands::daemon::print_socket(),
+ Some("__run_server") => commands::daemon::run_server(),
+ Some("__print_socket") => commands::daemon::print_socket(),
// Print the help for known commands called without any arguments, and exit with an error
Some(cmd @ ("check" | "ci" | "format")) => {
- crate::commands::help::help(self, Some(cmd))?;
+ commands::help::help(self, Some(cmd))?;
Err(Termination::EmptyArguments)
}
- Some("init") => crate::commands::init::init(self),
+ Some("init") => commands::init::init(self),
+
+ Some("version") => commands::version::full_version(self),
+ None if self.args.contains("--version") => commands::version::brief_version(self),
// Print the general help if no subcommand was specified / the subcommand is `help`
- None | Some("help") => crate::commands::help::help(self, None),
+ None | Some("help") => commands::help::help(self, None),
Some(cmd) => Err(Termination::UnknownCommand {
command: cmd.into(),
@@ -106,7 +114,7 @@ impl<'app> CliSession<'app> {
};
if has_metrics {
- crate::metrics::print_metrics();
+ metrics::print_metrics();
}
result

MODIFY
crates/rome_cli/tests/commands/mod.rs
crates/rome_cli/tests/commands/mod.rs
mod check;
mod ci;
mod format;
+mod version;

ADD
crates/rome_cli/tests/commands/version.rs
+use crate::snap_test::SnapshotPayload;
+use crate::{assert_cli_snapshot, run_cli};
+use pico_args::Arguments;
+use rome_console::BufferConsole;
+use rome_fs::MemoryFileSystem;
+use rome_service::DynRef;
+use std::ffi::OsString;
+
+#[test]
+fn ok() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let result = run_cli(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ Arguments::from_vec(vec![OsString::from("--version")]),
+ );
+
+ assert!(result.is_ok(), "run_cli returned {result:?}");
+
+ assert_cli_snapshot(SnapshotPayload::new(
+ module_path!(),
+ "version_ok",
+ fs,
+ console,
+ result,
+ ));
+}
+
+#[test]
+fn full() {
+ let mut fs = MemoryFileSystem::default();
+ let mut console = BufferConsole::default();
+
+ let result = run_cli(
+ DynRef::Borrowed(&mut fs),
+ DynRef::Borrowed(&mut console),
+ Arguments::from_vec(vec![OsString::from("version")]),
+ );
+
+ assert!(result.is_ok(), "run_cli returned {result:?}");
+
+ assert_cli_snapshot(SnapshotPayload::new(
+ module_path!(),
+ "version_full",
+ fs,
+ console,
+ result,
+ ));
+}

ADD
crates/rome_cli/tests/snapshots/main_commands_version/version_full.snap
+---
+source: crates/rome_cli/tests/snap_test.rs
+expression: content
+---
+# Emitted Messages
+
+```block
+CLI: 0.0.0
+```
+
+```block
+Server:
+ Name: rome_lsp
+ Version: 0.0.0
+```
+
+

ADD
crates/rome_cli/tests/snapshots/main_commands_version/version_ok.snap
+---
+source: crates/rome_cli/tests/snap_test.rs
+expression: content
+---
+# Emitted Messages
+
+```block
+Rome CLI version 0.0.0
+```
+
+

MODIFY
crates/rome_lsp/src/server.rs
crates/rome_lsp/src/server.rs
@@ -59,7 +59,7 @@ impl LanguageServer for LSPServer {
capabilities: server_capabilities(),
server_info: Some(ServerInfo {
name: String::from(env!("CARGO_PKG_NAME")),
- version: Some(String::from(env!("CARGO_PKG_VERSION"))),
+ version: Some(rome_service::VERSION.to_string()),
}),
};
@@ -163,7 +163,7 @@ impl LanguageServer for LSPServer {
/// for each incoming connection accepted by the server
#[derive(Default)]
pub struct ServerFactory {
- /// Synchronisation primitve used to broadcast a shutdown signal to all
+ /// Synchronisation primitive used to broadcast a shutdown signal to all
/// active connections
cancellation: Arc<Notify>,
/// Optional [Workspace] instance shared between all clients. Currently

MODIFY
crates/rome_service/src/lib.rs
crates/rome_service/src/lib.rs
@@ -33,6 +33,11 @@ pub use crate::workspace::Workspace;
/// Exports only for this crate
pub(crate) use crate::configuration::{deserialize_set_of_strings, serialize_set_of_strings};
+pub const VERSION: &str = match option_env!("ROME_VERSION") {
+ Some(version) => version,
+ None => env!("CARGO_PKG_VERSION"),
+};
+
/// This is the main entrypoint of the application.
pub struct App<'app> {
/// A reference to the internal virtual file system

MODIFY
crates/rome_service/src/workspace.rs
crates/rome_service/src/workspace.rs
//! document does not implement the required capability: for instance trying to
//! format a file with a language that does not have a formatter
-use crate::{Configuration, RomeError};
+use crate::{Configuration, Deserialize, RomeError, Serialize};
use rome_analyze::ActionCategory;
pub use rome_analyze::RuleCategories;
use rome_diagnostics::{v2, CodeSuggestion};
@@ -280,6 +280,16 @@ pub struct RenameResult {
pub indels: TextEdit,
}
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct ServerInfo {
+ /// The name of the server as defined by the server.
+ pub name: String,
+
+ /// The server's version as defined by the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
+
pub trait Workspace: Send + Sync + RefUnwindSafe {
/// Checks whether a certain feature is supported. There are different conditions:
/// - Rome doesn't recognize a file, so it can't provide the feature;
@@ -343,6 +353,9 @@ pub trait Workspace: Send + Sync + RefUnwindSafe {
/// Return the content of the file after renaming a symbol
fn rename(&self, params: RenameParams) -> Result<RenameResult, RomeError>;
+
+ /// Returns information about the server this workspace is connected to or `None` if the workspace isn't connected to a server.
+ fn server_info(&self) -> Option<&ServerInfo>;
}
/// Convenience function for constructing a server instance of [Workspace]

MODIFY
crates/rome_service/src/workspace/client.rs
crates/rome_service/src/workspace/client.rs
@@ -7,7 +7,7 @@ use rome_formatter::Printed;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::json;
-use crate::workspace::SupportsFeatureResult;
+use crate::workspace::{ServerInfo, SupportsFeatureResult};
use crate::{RomeError, TransportError, Workspace};
use super::{
@@ -21,6 +21,7 @@ use super::{
pub struct WorkspaceClient<T> {
transport: T,
request_id: AtomicU64,
+ server_info: Option<ServerInfo>,
}
pub trait WorkspaceTransport {
@@ -37,34 +38,42 @@ pub struct TransportRequest<P> {
pub params: P,
}
-#[derive(Debug, Deserialize)]
-struct InitializeResult {}
+#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InitializeResult {
+ /// Information about the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub server_info: Option<ServerInfo>,
+}
impl<T> WorkspaceClient<T>
where
T: WorkspaceTransport + RefUnwindSafe + Send + Sync,
{
pub fn new(transport: T) -> Result<Self, RomeError> {
- let client = Self {
+ let mut client = Self {
transport,
request_id: AtomicU64::new(0),
+ server_info: None,
};
// TODO: The current implementation of the JSON-RPC protocol in
// tower_lsp doesn't allow any request to be sent before a call to
// initialize, this is something we could be able to lift by using our
// own RPC protocol implementation
- let _value: InitializeResult = client.request(
+ let value: InitializeResult = client.request(
"initialize",
json!({
"capabilities": {},
"client_info": {
"name": "rome_service",
- "version": env!("CARGO_PKG_VERSION")
+ "version": crate::VERSION
},
}),
)?;
+ client.server_info = value.server_info;
+
Ok(client)
}
@@ -161,4 +170,8 @@ where
fn rename(&self, params: RenameParams) -> Result<RenameResult, RomeError> {
self.request("rome/rename", params)
}
+
+ fn server_info(&self) -> Option<&ServerInfo> {
+ self.server_info.as_ref()
+ }
}

MODIFY
crates/rome_service/src/workspace/server.rs
crates/rome_service/src/workspace/server.rs
@@ -6,7 +6,7 @@ use super::{
UpdateSettingsParams,
};
use crate::file_handlers::{Capabilities, FixAllParams, Language};
-use crate::workspace::SupportsFeatureResult;
+use crate::workspace::{ServerInfo, SupportsFeatureResult};
use crate::{
file_handlers::Features,
settings::{SettingsHandle, WorkspaceSettings},
@@ -503,4 +503,8 @@ impl Workspace for WorkspaceServer {
Ok(result)
}
+
+ fn server_info(&self) -> Option<&ServerInfo> {
+ None
+ }
}

feat(rome_cli): Add `version` command (#3421)