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

Commit

Permalink
feat(rome_service): deserialize configuration using internal parser (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico authored Feb 3, 2023
1 parent ced6f5b commit 5ef7a1d
Show file tree
Hide file tree
Showing 68 changed files with 6,457 additions and 1,929 deletions.
39 changes: 30 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/rome_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ license = "MIT"
rome_rowan = { path = "../rome_rowan" }
rome_console = { path = "../rome_console" }
rome_diagnostics = { path = "../rome_diagnostics" }
rome_json_parser = { path = "../rome_json_parser" }
rome_deserialize = { path = "../rome_deserialize"}
bitflags = "1.3.2"
rustc-hash = { workspace = true }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = { version = "1.0.85", features = ["raw_value"]}
schemars = { version = "0.8.10", optional = true }
tracing = { workspace = true }

Expand Down
4 changes: 4 additions & 0 deletions crates/rome_analyze/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ impl AnalyzerDiagnostic {
self.code_suggestion_list.push(suggestion);
self
}

pub const fn is_raw(&self) -> bool {
matches!(self.kind, DiagnosticKind::Raw(_))
}
}

#[derive(Debug, Diagnostic)]
Expand Down
3 changes: 1 addition & 2 deletions crates/rome_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ pub use crate::rule::{
RuleMeta, RuleMetadata, SuppressAction,
};
pub use crate::services::{FromServices, MissingServicesDiagnostic, ServiceBag};
use crate::signals::DiagnosticSignal;
pub use crate::signals::{AnalyzerAction, AnalyzerSignal};
pub use crate::signals::{AnalyzerAction, AnalyzerSignal, DiagnosticSignal};
pub use crate::syntax::{Ast, SyntaxVisitor};
pub use crate::visitor::{NodeVisitor, Visitor, VisitorContext, VisitorFinishContext};
pub use rule::DeserializableRuleOptions;
Expand Down
75 changes: 5 additions & 70 deletions crates/rome_analyze/src/options.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
use crate::signals::AnalyzerActionIter;
use crate::AnalyzerSignal;
use crate::{RuleKey, TextRange, TextSize};
use rome_diagnostics::{Diagnostic, LineIndexBuf, Resource, SourceCode};
use rome_rowan::Language;
use crate::RuleKey;
use serde::Deserialize;
use serde_json::Error;
use serde_json::Value;
use std::collections::HashMap;

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

impl RuleOptions {
/// It returns the deserialized rule option
pub fn value(&self) -> &Value {
pub fn value(&self) -> &String {
&self.0
}

/// Creates a new [RuleOptions]
pub fn new(options: Value) -> Self {
pub fn new(options: String) -> Self {
Self(options)
}
}
Expand All @@ -30,7 +24,7 @@ pub struct AnalyzerRules(HashMap<RuleKey, RuleOptions>);

impl AnalyzerRules {
/// It tracks the options of a specific rule
pub fn push_rule(&mut self, rule_key: RuleKey, options: Value) {
pub fn push_rule(&mut self, rule_key: RuleKey, options: String) {
self.0.insert(rule_key, RuleOptions::new(options));
}

Expand Down Expand Up @@ -58,62 +52,3 @@ pub struct AnalyzerOptions {
/// A data structured derived from the [`rome.json`] file
pub configuration: AnalyzerConfiguration,
}

#[derive(Debug, Clone, Diagnostic)]
#[diagnostic(category = "lint/configuration")]
pub struct OptionsDeserializationDiagnostic {
#[message]
message: String,
#[description]
description: String,
#[location(resource)]
path: Resource<&'static str>,
#[location(span)]
span: Option<TextRange>,
#[location(source_code)]
source_code: Option<SourceCode<String, LineIndexBuf>>,
}

impl OptionsDeserializationDiagnostic {
pub fn new(rule_name: &str, input: String, error: Error) -> Self {
let line_starts = LineIndexBuf::from_source_text(&input);

let line_index = error.line().checked_sub(1);
let span = line_index.and_then(|line_index| {
let line_start = line_starts.get(line_index)?;

let column_index = error.column().checked_sub(1)?;
let column_offset = TextSize::try_from(column_index).ok()?;

let span_start = line_start + column_offset;
Some(TextRange::at(span_start, TextSize::from(0)))
});

let message = format!(
"Errors while reading options for rule {rule_name}: \n {}",
error
);

Self {
message: message.clone(),
description: message,
path: Resource::Memory,
span,
source_code: Some(SourceCode {
text: input,
line_starts: Some(line_starts),
}),
}
}
}

impl<L: Language> AnalyzerSignal<L> for OptionsDeserializationDiagnostic {
fn diagnostic(&self) -> Option<crate::AnalyzerDiagnostic> {
let error = rome_diagnostics::Error::from(self.clone());
Some(crate::AnalyzerDiagnostic::from_error(error))
}

fn actions(&self) -> AnalyzerActionIter<L> {
AnalyzerActionIter::default()
}
}
49 changes: 23 additions & 26 deletions crates/rome_analyze/src/registry.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
use std::{
any::TypeId,
borrow,
collections::{BTreeMap, BTreeSet},
};

use crate::{
context::{RuleContext, ServiceBagRuleOptionsWrapper},
matcher::{GroupKey, MatchQueryParams},
options::OptionsDeserializationDiagnostic,
query::{QueryKey, Queryable},
signals::RuleSignal,
AddVisitor, AnalysisFilter, AnalyzerOptions, DeserializableRuleOptions, GroupCategory,
QueryMatcher, Rule, RuleGroup, RuleKey, RuleMetadata, ServiceBag, SignalEntry, Visitor,
};
use rome_deserialize::Deserialized;
use rome_diagnostics::Error;
use rome_rowan::{AstNode, Language, RawSyntaxKind, SyntaxKind, SyntaxNode};
use rustc_hash::{FxHashMap, FxHashSet};
use std::{
any::TypeId,
borrow,
collections::{BTreeMap, BTreeSet},
};

/// Defines all the phases that the [RuleRegistry] supports.
#[repr(usize)]
Expand Down Expand Up @@ -151,7 +150,7 @@ pub struct RuleRegistryBuilder<'a, L: Language> {
visitors: BTreeMap<(Phases, TypeId), Box<dyn Visitor<Language = L>>>,
// Service Bag
services: ServiceBag,
diagnostics: Vec<OptionsDeserializationDiagnostic>,
diagnostics: Vec<Error>,
}

impl<L: Language + Default + 'static> RegistryVisitor<L> for RuleRegistryBuilder<'_, L> {
Expand Down Expand Up @@ -224,25 +223,23 @@ impl<L: Language + Default + 'static> RegistryVisitor<L> for RuleRegistryBuilder
phase.rule_states.push(RuleState::default());

let rule_key = RuleKey::rule::<R>();
let options = if let Some(options) = self.options.configuration.rules.get_rule(&rule_key) {
let value = options.value();
match <R::Options as DeserializableRuleOptions>::try_from(value.clone()) {
Ok(result) => Ok(result),
Err(error) => Err(OptionsDeserializationDiagnostic::new(
rule_key.rule_name(),
value.to_string(),
error,
)),
let deserialized =
if let Some(options) = self.options.configuration.rules.get_rule(&rule_key) {
let value = options.value();
<R::Options as DeserializableRuleOptions>::from(value.to_string())
} else {
Deserialized::new(<R::Options as Default>::default(), vec![])
};

if deserialized.has_errors() {
for error in deserialized.into_diagnostics() {
self.diagnostics.push(error)
}
} else {
Ok(<R::Options as Default>::default())
};

match options {
Ok(options) => self
.services
.insert_service(ServiceBagRuleOptionsWrapper::<R>(options)),
Err(err) => self.diagnostics.push(err),
self.services
.insert_service(ServiceBagRuleOptionsWrapper::<R>(
deserialized.into_deserialized(),
))
}

<R::Query as Queryable>::build_visitor(&mut self.visitors, self.root);
Expand All @@ -263,7 +260,7 @@ impl<L: Language> AddVisitor<L> for BTreeMap<(Phases, TypeId), Box<dyn Visitor<L
type BuilderResult<L> = (
RuleRegistry<L>,
ServiceBag,
Vec<OptionsDeserializationDiagnostic>,
Vec<Error>,
BTreeMap<(Phases, TypeId), Box<dyn Visitor<Language = L>>>,
);

Expand Down
21 changes: 16 additions & 5 deletions crates/rome_analyze/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::{
};
use rome_console::fmt::Display;
use rome_console::{markup, MarkupBuf};
use rome_deserialize::json::{deserialize_from_json, JsonDeserialize, VisitJsonNode};
use rome_deserialize::Deserialized;
use rome_diagnostics::advice::CodeSuggestionAdvice;
use rome_diagnostics::location::AsSpan;
use rome_diagnostics::Applicability;
Expand All @@ -14,7 +16,6 @@ use rome_diagnostics::{
Visit,
};
use rome_rowan::{AstNode, BatchMutation, BatchMutationExt, Language, TextRange};
use serde::de::DeserializeOwned;

/// Static metadata containing information about a rule
pub struct RuleMetadata {
Expand Down Expand Up @@ -234,13 +235,23 @@ impl_group_language!(
T57, T58, T59
);

pub trait DeserializableRuleOptions: Default + DeserializeOwned + Sized {
fn try_from(value: serde_json::Value) -> Result<Self, serde_json::Error> {
serde_json::from_value(value)
// pub trait DeserializableRuleOptions: Default + DeserializeOwned + Sized {
// fn try_from(value: String) -> Result<Self, AnalyzerDiagnostic> {
// // parse_json();
// }
// }

pub trait DeserializableRuleOptions: Default + Sized + JsonDeserialize + VisitJsonNode {
fn from(value: String) -> Deserialized<Self> {
deserialize_from_json(&value)
}
}

impl DeserializableRuleOptions for () {}
impl DeserializableRuleOptions for () {
fn from(_value: String) -> Deserialized<Self> {
Deserialized::new((), vec![])
}
}

/// Trait implemented by all analysis rules: declares interest to a certain AstNode type,
/// and a callback function to be executed on all nodes matching the query to possibly
Expand Down
Loading

0 comments on commit 5ef7a1d

Please sign in to comment.