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

Commit feddcc2

Browse files
committed
use oncelock/threadlocal where possible
1 parent 171bc0f commit feddcc2

File tree

1 file changed

+57
-52
lines changed

1 file changed

+57
-52
lines changed

fuzz/fuzz_targets/rome_common.rs

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rome_json_parser::parse_json;
1818
use rome_service::Rules;
1919
use similar::TextDiff;
2020
use std::fmt::{Display, Formatter};
21+
use std::sync::OnceLock;
2122

2223
pub fn fuzz_js_parser_with_source_type(data: &[u8], source: JsFileSource) -> Corpus {
2324
let Ok(code1) = std::str::from_utf8(data) else { return Corpus::Reject; };
@@ -32,9 +33,13 @@ pub fn fuzz_js_parser_with_source_type(data: &[u8], source: JsFileSource) -> Cor
3233
Corpus::Keep
3334
}
3435

35-
static mut ANALYSIS_RULES: Option<Rules> = None;
36-
static mut ANALYSIS_RULE_FILTERS: Option<Vec<RuleFilter>> = None;
37-
static mut ANALYSIS_OPTIONS: Option<AnalyzerOptions> = None;
36+
static ANALYSIS_RULES: OnceLock<Rules> = OnceLock::new();
37+
static ANALYSIS_RULE_FILTERS: OnceLock<Vec<RuleFilter>> = OnceLock::new();
38+
39+
// have to use thread local because AnalyzerOptions contains a Box<dyn Any>, which isn't thread-safe
40+
thread_local! {
41+
static ANALYSIS_OPTIONS: AnalyzerOptions = AnalyzerOptions::default();
42+
}
3843

3944
struct DiagnosticDescriptionExtractor<'a, D> {
4045
diagnostic: &'a D,
@@ -58,43 +63,36 @@ where
5863
pub fn fuzz_js_formatter_with_source_type(data: &[u8], source: JsFileSource) -> Corpus {
5964
let Ok(code1) = std::str::from_utf8(data) else { return Corpus::Reject; };
6065

61-
// TODO: replace with OnceLock when upgrading to 1.70
62-
let rule_filters = if let Some(rules) = unsafe { ANALYSIS_RULE_FILTERS.as_ref() } {
63-
rules
64-
} else {
65-
let rules = unsafe {
66-
ANALYSIS_RULES.get_or_insert_with(|| Rules {
67-
all: Some(true),
68-
..Default::default()
69-
})
70-
};
71-
let rules = rules.as_enabled_rules().into_iter().collect::<Vec<_>>();
72-
unsafe {
73-
ANALYSIS_RULE_FILTERS = Some(rules);
74-
ANALYSIS_RULE_FILTERS.as_ref().unwrap_unchecked()
75-
}
76-
};
77-
let options = unsafe { ANALYSIS_OPTIONS.get_or_insert_with(AnalyzerOptions::default) };
66+
let rules = ANALYSIS_RULES.get_or_init(|| Rules {
67+
all: Some(true),
68+
..Default::default()
69+
});
70+
let rule_filters = ANALYSIS_RULE_FILTERS
71+
.get_or_init(|| rules.as_enabled_rules().into_iter().collect::<Vec<_>>());
7872

7973
let parse1 = parse(code1, source);
8074
if !parse1.has_errors() {
8175
let language = JsFormatLanguage::new(JsFormatOptions::new(source));
8276
let tree1 = parse1.tree();
8377
let mut linter_errors = Vec::new();
84-
let _ = analyze(
85-
&tree1,
86-
AnalysisFilter::from_enabled_rules(Some(rule_filters)),
87-
options,
88-
source,
89-
|e| -> ControlFlow<()> {
90-
if let Some(diagnostic) = e.diagnostic() {
91-
linter_errors
92-
.push(DiagnosticDescriptionExtractor::new(&diagnostic).to_string());
93-
}
78+
let _ = ANALYSIS_OPTIONS
79+
.try_with(|options| {
80+
analyze(
81+
&tree1,
82+
AnalysisFilter::from_enabled_rules(Some(rule_filters)),
83+
options,
84+
source,
85+
|e| -> ControlFlow<()> {
86+
if let Some(diagnostic) = e.diagnostic() {
87+
linter_errors
88+
.push(DiagnosticDescriptionExtractor::new(&diagnostic).to_string());
89+
}
9490

95-
ControlFlow::Continue(())
96-
},
97-
);
91+
ControlFlow::Continue(())
92+
},
93+
)
94+
})
95+
.unwrap();
9896
let syntax1 = parse1.syntax();
9997
if let Ok(formatted1) = format_node(&syntax1, language.clone()) {
10098
if let Ok(printed1) = formatted1.print() {
@@ -108,25 +106,32 @@ pub fn fuzz_js_formatter_with_source_type(data: &[u8], source: JsFileSource) ->
108106
.header("original code", "formatted")
109107
);
110108
let tree2 = parse2.tree();
111-
let (maybe_diagnostic, _) = analyze(
112-
&tree2,
113-
AnalysisFilter::from_enabled_rules(Some(rule_filters)),
114-
options,
115-
source,
116-
|e| {
117-
if let Some(diagnostic) = e.diagnostic() {
118-
let new_error =
119-
DiagnosticDescriptionExtractor::new(&diagnostic).to_string();
120-
if let Some(idx) = linter_errors.iter().position(|e| *e == new_error) {
121-
linter_errors.remove(idx);
122-
} else {
123-
return ControlFlow::Break(new_error);
124-
}
125-
}
126-
127-
ControlFlow::Continue(())
128-
},
129-
);
109+
let (maybe_diagnostic, _) = ANALYSIS_OPTIONS
110+
.try_with(|options| {
111+
analyze(
112+
&tree2,
113+
AnalysisFilter::from_enabled_rules(Some(rule_filters)),
114+
options,
115+
source,
116+
|e| {
117+
if let Some(diagnostic) = e.diagnostic() {
118+
let new_error =
119+
DiagnosticDescriptionExtractor::new(&diagnostic)
120+
.to_string();
121+
if let Some(idx) =
122+
linter_errors.iter().position(|e| *e == new_error)
123+
{
124+
linter_errors.remove(idx);
125+
} else {
126+
return ControlFlow::Break(new_error);
127+
}
128+
}
129+
130+
ControlFlow::Continue(())
131+
},
132+
)
133+
})
134+
.unwrap();
130135
if let Some(diagnostic) = maybe_diagnostic {
131136
panic!(
132137
"formatter introduced linter failure: {} (expected one of: {})\n{}",

0 commit comments

Comments
 (0)