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

Commit

Permalink
feat(rome_analyze): use serde to deserialize rule settings (#3347)
Browse files Browse the repository at this point in the history
* feat(rome_analyze): use serde to deserialize rule settings

* chore: code suggestions
  • Loading branch information
ematipico authored Oct 10, 2022
1 parent fb5b508 commit 148a539
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 57 deletions.
4 changes: 2 additions & 2 deletions crates/rome_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ rome_console = { path = "../rome_console" }
rome_diagnostics = { path = "../rome_diagnostics" }
bitflags = "1.3.2"
rustc-hash = { workspace = true }
serde = { version = "1.0.136", features = ["derive"], optional = true }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = { version = "1.0.85", features = ["raw_value"]}
schemars = { version = "0.8.10", optional = true }

Expand All @@ -24,4 +24,4 @@ rome_js_syntax = { path = "../rome_js_syntax" }
rome_js_factory = { path = "../rome_js_factory" }

[features]
serde = ["dep:serde", "schemars"]
serde = ["schemars"]
51 changes: 49 additions & 2 deletions crates/rome_analyze/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
registry::RuleRoot, AnalyzerOptions, CannotCreateServicesError, FromServices, Queryable, Rule,
ServiceBag,
RuleKey, ServiceBag,
};
use serde::Deserialize;
use std::ops::Deref;

type RuleQueryResult<R> = <<R as Rule>::Query as Queryable>::Output;
Expand All @@ -19,7 +20,7 @@ where

impl<'a, R> RuleContext<'a, R>
where
R: ?Sized + Rule,
R: Rule + Sized,
{
pub fn new(
query_result: &'a RuleQueryResult<R>,
Expand Down Expand Up @@ -48,6 +49,52 @@ where
pub fn options(&self) -> &AnalyzerOptions {
self.options
}

/// It retrieves the options that belong to a rule, if they exist.
///
/// In order to retrieve a typed data structure, the function has to accept a `FromType`, a
/// `ToType` (this one, inferrable by the compiler) and a closure that does the mapping.
///
/// Usually, options are a `serde::RawValue` and need to be mapped to a sized type.
///
/// ## Examples
///
/// ```rust,ignore
/// use rome_analyze::{declare_rule, Rule, RuleCategory, RuleMeta, RuleMetadata};
/// use rome_analyze::context::RuleContext;
/// use serde::Deserialize;
/// declare_rule! {
/// /// Some doc
/// pub(crate) Name {
/// version: "0.0.0",
/// name: "name",
/// recommended: true,
/// }
/// }
///
/// #[derive(Deserialize)]
/// struct RuleSettings {}
///
/// impl Rule for Name {
/// const CATEGORY: RuleCategory = RuleCategory::Lint;
/// type Query = ();
/// type State = ();
/// type Signals = ();
///
/// fn run(ctx: &RuleContext<Self>) -> Self::Signals {
/// let options = ctx.rule_settings::<RuleSettings>();
/// }
/// }
/// ```
pub fn rule_settings<'de, ToType: Deserialize<'de>>(&'de self) -> Option<ToType> {
self.options
.configuration
.rules
.get_rule(&RuleKey::rule::<R>())
.map(|options| serde_json::from_str::<ToType>(options.value()))
// TODO: ignore the error for now, it should be handled differently https://github.com/rome/tools/issues/3346
.and_then(|result| result.ok())
}
}

impl<'a, R> Deref for RuleContext<'a, R>
Expand Down
53 changes: 6 additions & 47 deletions crates/rome_analyze/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::RuleKey;
use serde::Deserialize;
use serde_json::value::RawValue;
use std::collections::HashMap;

/// A convenient new type data structure to store the options that belong to a rule
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize)]
pub struct RuleOptions(Box<RawValue>);

impl RuleOptions {
/// It returns the [RawValue] for the relative rule
pub fn value(&self) -> &RawValue {
&self.0
/// It returns the string contained in [RawValue], for the relative rule
pub fn value(&self) -> &str {
self.0.get()
}

/// Creates a new [RuleOptions]
Expand Down Expand Up @@ -50,47 +51,5 @@ pub struct AnalyzerConfiguration {
#[derive(Debug, Clone, Default)]
pub struct AnalyzerOptions {
/// A data structured derived from the [`rome.json`] file
configuration: AnalyzerConfiguration,
}

impl AnalyzerOptions {
/// It retrieves the options that belong to a rule, if they exist.
///
/// In order to retrieve a typed data structure, the function has to accept a `FromType`, a
/// `ToType` (this one, inferrable by the compiler) and a closure that does the mapping.
///
/// Usually, options are a `serde::RawValue` and need to be mapped to a sized type.
///
/// ## Examples
///
/// ```rust,ignore
/// use rome_analyze::{declare_rule, Rule, RuleCategory, RuleMeta, RuleMetadata};
/// use rome_analyze::context::RuleContext;
/// declare_rule! {
/// /// Some doc
/// pub(crate) Name {
/// version: "0.0.0",
/// name: "name",
/// recommended: true,
/// }
/// }
///
/// impl Rule for Name {
/// const CATEGORY: RuleCategory = RuleCategory::Lint;
/// type Query = ();
/// type State = ();
/// type Signals = ();
///
/// fn run(ctx: &RuleContext<Self>) -> Self::Signals {
/// let options = ctx.options();
/// }
/// }
/// ```
pub fn rule_options<F: FnOnce(&RuleOptions) -> ToType, ToType>(
&self,
rule_key: &RuleKey,
mapper: F,
) -> Option<ToType> {
self.configuration.rules.get_rule(rule_key).map(mapper)
}
pub configuration: AnalyzerConfiguration,
}
1 change: 0 additions & 1 deletion crates/rome_analyze/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ impl<L: Language + Default> RegistryRule<L> {
// if the query doesn't match
let query_result =
<R::Query as Queryable>::unwrap_match(params.services, &params.query);

let ctx =
match RuleContext::new(&query_result, params.root, params.services, params.options)
{
Expand Down
1 change: 1 addition & 0 deletions crates/rome_analyze/src/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ where
fn diagnostic(&self) -> Option<AnalyzerDiagnostic> {
let ctx =
RuleContext::new(&self.query_result, self.root, self.services, &self.options).ok()?;

R::diagnostic(&ctx, &self.state).map(|diag| diag.into_analyzer_diagnostic(self.file_id))
}

Expand Down
2 changes: 1 addition & 1 deletion crates/rome_js_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rome_console = { path = "../rome_console" }
rome_diagnostics = { path = "../rome_diagnostics" }
roaring = "0.9.0"
rustc-hash = { workspace = true }
serde = { version = "1.0.136", features = ["derive"], optional = true }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = { version = "1.0.74", features = ["raw_value"] }

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions crates/rome_js_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rome_js_syntax::{
suppression::{parse_suppression_comment, SuppressionCategory},
JsLanguage,
};
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, error::Error};

mod analyzers;
Expand Down Expand Up @@ -210,8 +211,7 @@ mod tests {
}

/// Series of errors encountered when running rules on a file
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum RuleError {
/// The rule with the specified name replaced the root of the file with a node that is not a valid root for that language.
ReplacedRootWithNonRootError { rule_name: Cow<'static, str> },
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_js_analyze/src/utils/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rome_js_syntax::{
JsSyntaxNode, JsSyntaxToken,
};
use rome_rowan::{AstNode, BatchMutation, SyntaxNodeCast, TriviaPiece};
use serde::{Deserialize, Serialize};

pub trait RenamableNode {
fn declaration(&self, model: &SemanticModel) -> Option<JsSyntaxNode>;
Expand Down Expand Up @@ -49,7 +50,7 @@ impl RenamableNode for JsAnyRenamableDeclaration {
}
}

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Deserialize, Serialize)]
pub enum RenameError {
CannotFindDeclaration,
CannotBeRenamed {
Expand Down
2 changes: 1 addition & 1 deletion crates/rome_service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rome_console = { path = "../rome_console" }
rome_diagnostics = { path = "../rome_diagnostics" }
rome_formatter = { path = "../rome_formatter", features = ["serde"] }
rome_fs = { path = "../rome_fs", features = ["serde"] }
rome_js_analyze = { path = "../rome_js_analyze", features = ["serde"] }
rome_js_analyze = { path = "../rome_js_analyze" }
rome_js_syntax = { path = "../rome_js_syntax", features = ["serde"] }
rome_js_parser = { path = "../rome_js_parser" }
rome_js_factory = { path = "../rome_js_factory", optional = true }
Expand Down

0 comments on commit 148a539

Please sign in to comment.