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

feat(rome_cli): Add rage command #3436

Merged
merged 6 commits into from
Oct 18, 2022
Merged

feat(rome_cli): Add rage command #3436

merged 6 commits into from
Oct 18, 2022

Conversation

MichaReiser
Copy link
Contributor

@MichaReiser MichaReiser commented Oct 17, 2022

Summary

This PR adds a rage command to Rome's CLI.

The rage command aims to print useful information about the status of Rome and the project to help debug issues with Rome or the setup of a project.

This PR implements a "basic" rage command that

  • Prints information about the CLI, architecture, and some environment variables
  • Prints information about the workspace (limited to open documents)
  • Prints information about the configuration
  • Prints information about the LSP version and the connected
  • Tries to connect to an existing Rome server and prints the version as well as information about all connected clients.

This PR does not yet implement a way to retrieve the logs I'll give it a short try as a separate PR.

Architecture

I considered three different designs on how to model the result of the rome/rage LSP command and went for the second option. I would be interested to hear your thoughts.

Structured type

Make RageResult a structured type with fields for every single value that we expect to be returned

struct RageResult {
  workspace_info: WorkspaceRage,
  lsp_info: Option<LspRage>
}

struct WorkspaceRage {
  open_documents: usize
}

struct LspRage {
  name: String,
  version: String,
  workspaces: Vec<Result<WorkspaceRage, RomeError>>
}
...

The upside of this approach is that it gives the client the most flexibility when it comes to layouting the rage output.

I decided against this approach because I fear that adding or removing fields otherwise risks a version mismatch between client and LSP results in

  • Client either crashing or rejecting the result if a mandatory field is missing (can be worked around by making all fields optional but requires extra care)
  • Client omitting information returned by the LSP: An older client not supporting a new field omits information returned by the LSP if the client doesn't support that field yet, resulting in an information loss.

Partially structured

This is the approach implemented by this PR. The idea is to generally encode enough information to enable the client to nicely print the rage output but without enforcing an overly strict data layout.

RageResult is defined as:

struct RageResult {
  entries: Vec<RageEntry>
}

enum RageEntry {
  Section(String),
  // A key value pair
  Pair(String, MarkupBuf),
  Markup(MarkupBuf)
}

Where Markup is an escape hatch for all cases where neither Section nor Pair are applicable.

The upside is that this should be a loose enough format where the LSP can add new fields but have enough information to layout the data on the client.

The main downside is that while this approach gives the impression that the client display and LSP logic are independent this isn't entirely true because the order in which the entries are returned does matter for a logical structured output in the CLI.

Unstructured

The third Option would be to change RageResult to return a json bag, giving full flexibility to the LSP. We may be able to format such content nicely in the future when our JSON formatter is ready but it significantly increases the complexity in the CLI to show a nice rage output.

Diagnostics

I didn't fully explore this option and maybe @leops may share his thoughts if it may be a good use case. The idea would be that RageResult returns a Diagnostic that could even be nested inside each other (to achieve the same level of nesting as the current solution).

The reason why I didn't further investigate this approach is because I don't consider rage itself as a Diagnostic and using a purpose-built data structure yields additional flexibility.

Test Plan

image

No running server

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               loaded
  Formatter disabled:   false
  Linter disabled:      false

Workspace:
  Open Documents:       0

Discovering running Rome servers...

Server:
  Status:               stopped

Running server but without `--use-server

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               loaded
  Formatter disabled:   false
  Linter disabled:      false

Workspace:
  Open Documents:       0

Discovering running Rome servers...

Running Rome Server: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ The client isn't connected to any server but rage discovered this running Rome server.

Server:
  Version:              0.0.0
  Name:                 rome_lsp
  CPU Architecture:     x86_64
  OS:                   linux

Workspace:
  Open Documents:       0

Other Active Server Workspaces:

Workspace:
  Open Documents:       2
  Client Name:          Code - OSS
  Client Version:       1.72.0

With --use-server

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               loaded
  Formatter disabled:   false
  Linter disabled:      false

Server:
  Version:              0.0.0
  Name:                 rome_lsp
  CPU Architecture:     x86_64
  OS:                   linux

Workspace:
  Open Documents:       0

Other Active Server Workspaces:

Workspace:
  Open Documents:       2
  Client Name:          Code - OSS
  Client Version:       1.72.0

With old LSP server

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               loaded
  Formatter disabled:   false
  Linter disabled:      false

✖ Workspace rage failed: Method not found

Malformed Configuration

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               Failed to load
  Error:                Rome couldn't load the configuration file, here's why: 
key must be a string at line 11 column 30

Workspace:
  Open Documents:       0

Discovering running Rome servers...

Server:
  Status:               stopped

No configuration

CLI:
  Version:              0.0.0
  Color support:        true

Platform:
  CPU Architecture:     x86_64
  OS:                   linux

Environment:
  NO_COLOR:             unset
  TERM:                 "xterm-256color"

Rome Configuration:
  Status:               unset

Workspace:
  Open Documents:       0

Discovering running Rome servers...

Server:
  Status:               stopped

@netlify
Copy link

netlify bot commented Oct 17, 2022

Deploy Preview for rometools canceled.

Name Link
🔨 Latest commit f01d921
🔍 Latest deploy log https://app.netlify.com/sites/rometools/deploys/634e4327015b3d00077c59fe

@MichaReiser MichaReiser linked an issue Oct 17, 2022 that may be closed by this pull request
1 task
@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 09:31 Inactive
@github-actions
Copy link

github-actions bot commented Oct 17, 2022

@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 09:52 Inactive
@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 09:54 Inactive
@MichaReiser MichaReiser marked this pull request as ready for review October 17, 2022 09:55
@MichaReiser MichaReiser requested a review from a team October 17, 2022 09:55
@calibre-analytics
Copy link

calibre-analytics bot commented Oct 17, 2022

Comparing feat(rome_cli): Add rage command Snapshot #9 to median since last deploy of rome.tools.

LCP? CLS? TBT?
Overall
Median across all pages and test profiles
3.08s
from 556ms
0.0
no change
325ms
from 45ms
Chrome Desktop
Chrome Desktop • Cable
3.08s
from 572ms
0.0
no change
515ms
from 227ms
iPhone, 4G LTE
iPhone 12 • 4G LTE
942ms
from 218ms
0.0
no change
12ms
from 6ms
Motorola Moto G Power, 3G connection
Motorola Moto G Power • Regular 3G
13.7s
from 556ms
0.0
no change
325ms
from 45ms

1 page tested

 Home

Browser previews

Chrome Desktop iPhone, 4G LTE Motorola Moto G Power, 3G connection
Chrome Desktop iPhone, 4G LTE Motorola Moto G Power, 3G connection

Most significant changes

Value Budget
JS Parse & Compile
Motorola Moto G Power, 3G connection
2.18s
from 26ms
Total JavaScript Size in Bytes
iPhone, 4G LTE
4.32 MB
from 86.8 KB
Total JavaScript Size in Bytes
Chrome Desktop
4.32 MB
from 86.8 KB
Total JavaScript Size in Bytes
Motorola Moto G Power, 3G connection
4.32 MB
from 86.8 KB
JS Parse & Compile
Chrome Desktop
3.14s
from 65ms

28 other significant changes: JS Parse & Compile on iPhone, 4G LTE, First Contentful Paint on Motorola Moto G Power, 3G connection, Largest Contentful Paint on Motorola Moto G Power, 3G connection, Speed Index on Motorola Moto G Power, 3G connection, First Contentful Paint on Chrome Desktop, Total Page Size in Bytes on iPhone, 4G LTE, Total Page Size in Bytes on Chrome Desktop, Total Page Size in Bytes on Motorola Moto G Power, 3G connection, Number of Requests on Chrome Desktop, Number of Requests on iPhone, 4G LTE, Number of Requests on Motorola Moto G Power, 3G connection, Time to Interactive on Motorola Moto G Power, 3G connection, Time to Interactive on Chrome Desktop, Speed Index on Chrome Desktop, First Contentful Paint on iPhone, 4G LTE, Total Blocking Time on Motorola Moto G Power, 3G connection, Largest Contentful Paint on Chrome Desktop, Speed Index on iPhone, 4G LTE, Largest Contentful Paint on iPhone, 4G LTE, Time to Interactive on iPhone, 4G LTE, Total Image Size in Bytes on Chrome Desktop, Total Image Size in Bytes on iPhone, 4G LTE, Total Image Size in Bytes on Motorola Moto G Power, 3G connection, Total HTML Size in Bytes on Chrome Desktop, Total HTML Size in Bytes on iPhone, 4G LTE, Total HTML Size in Bytes on Motorola Moto G Power, 3G connection, Lighthouse Performance Score on Motorola Moto G Power, 3G connection, Lighthouse Performance Score on Chrome Desktop

Calibre: Site dashboard | View this PR | Edit settings | View documentation

@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 11:23 Inactive
@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 11:34 Inactive
@MichaReiser MichaReiser temporarily deployed to netlify-playground October 17, 2022 11:42 Inactive
Copy link
Contributor

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's some feedback based on the snapshot/examples given:

  • Discovering running Rome servers..., this doesn't seem to be an useful information for us... can we omit it?
  • ✖ Workspace rage failed: Method not found. If this information is useful for us, then it should contain more details... what does that mean? If it's not useful for us, can we omit it?
  • What's the objective of the configuration part? At the moment it only shows if linter/formatter are disabled. Do we show all options? If so, would it be possible to see how - for example - options around rules are rendered? Or even the formatter.. just to have a look and feel of the final result.
     Rome Configuration:
    Status:               loaded
    Formatter disabled:   false
    Linter disabled:      false
    

}
}

struct KeyValuePair<'a>(&'a str, Markup<'a>);
Copy link
Contributor

@ematipico ematipico Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think KeyValuePair could be a trait or have a new trait RageDisplay that writes into a buffer, this would allow us to print sections of the configuration as we go, here's some meta code:

trait RageDisplay {
	fn display(&self,  fmt: &mut rome_console::fmt::Formatter) -> io::Result<()> {}
}

impl RageDisplay for  JavascriptFormatter {
	fn display(&self, fmt) -> {
		fmt.write_markup(buffer, markup!{ KeyValuePair("Quote style", markup!{}) })?;
		fmt.write_markup(markup!{ KeyValuePair("Quote properties", markup!{}) })?;
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intentional that we write the whole markup in one go and it is already writing into whatever Buffer console.log uses.

It would also be possible to write the output as multiple separate logs if this is what we want (all of the implementations gracefully handle errors which is why I think this isn't necessary) by simply calling console.log(markup) multiple times.

@MichaReiser
Copy link
Contributor Author

Here's some feedback based on the snapshot/examples given:

* `Discovering running Rome servers...`, this doesn't seem to be an useful information for us... can we omit it?

The intention here is to print some output in case the Rome server is stuck, and in turn, open_transport may "hang" (until it times out). If that happens, then we at least know why rage is hanging compared to not having a message where it may be less clear.

* `✖ Workspace rage failed: Method not found`. If this information is useful for us, then it should contain more details... what does that mean? If it's not useful for us, can we omit it?

Having more information would be useful but I can't emit more than RomeError provides. Having the output is useful, e.g. seeing it tells us that the Rome server instance doesn't support the rage command yet. It, therefore, must be an older version.

* What's the objective of the configuration part? At the moment it only shows if linter/formatter are disabled. Do we show **all options**? If so, would it be possible to see how - for example - options around rules are rendered? Or even the formatter.. just to have a look and feel of the final result.

I don't know. I considered printing the full configuration but that may not be safe because it may contain path information. I then opted to print some basic information.

One option could be to print the full configuration in the future as JSON and print "set"/"unset" for all values except for keys that are on an allowlist.

@MichaReiser MichaReiser temporarily deployed to netlify-playground October 18, 2022 06:09 Inactive
@MichaReiser MichaReiser merged commit 69ae1db into main Oct 18, 2022
@MichaReiser MichaReiser deleted the feat/rage-2 branch October 18, 2022 10:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

📎 Add rage command
3 participants
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载