Skip to content

Commit 86d928e

Browse files
branchseerclaude
andcommitted
refactor(static-config): use oxc utility methods instead of manual matching
- PropertyKey::static_name() replaces property_key_to_string and property_key_to_json_key - TemplateLiteral::single_quasi() replaces manual quasis/expressions check - Expression::is_specific_id() replaces is_define_config_call helper - ArrayExpressionElement::is_elision()/is_spread() replaces variant matching - ObjectPropertyKind::is_spread() replaces variant matching Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 487f982 commit 86d928e

File tree

1 file changed

+28
-89
lines changed
  • crates/vite_static_config/src

1 file changed

+28
-89
lines changed

crates/vite_static_config/src/lib.rs

Lines changed: 28 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
//! config like `run` without needing a Node.js runtime.
66
77
use oxc::{
8-
ast::ast::{
9-
ArrayExpressionElement, Expression, ObjectPropertyKind, Program, PropertyKey, Statement,
10-
},
8+
ast::ast::{Expression, ObjectPropertyKind, Program, Statement},
119
parser::Parser,
1210
span::SourceType,
1311
};
@@ -137,7 +135,7 @@ fn extract_default_export_fields(program: &Program<'_>) -> StaticConfig {
137135
match expr {
138136
// Pattern: export default defineConfig({ ... })
139137
Expression::CallExpression(call) => {
140-
if !is_define_config_call(&call.callee) {
138+
if !call.callee.is_specific_id("defineConfig") {
141139
// Unknown function call — not analyzable
142140
return None;
143141
}
@@ -162,11 +160,6 @@ fn extract_default_export_fields(program: &Program<'_>) -> StaticConfig {
162160
None
163161
}
164162

165-
/// Check if a callee expression is `defineConfig`.
166-
fn is_define_config_call(callee: &Expression<'_>) -> bool {
167-
matches!(callee, Expression::Identifier(ident) if ident.name == "defineConfig")
168-
}
169-
170163
/// Extract fields from an object expression, converting each value to JSON.
171164
/// Fields whose values cannot be represented as pure JSON are recorded as
172165
/// [`StaticFieldValue::NonStatic`]. Spread elements and computed properties
@@ -177,48 +170,27 @@ fn extract_object_fields(
177170
let mut map = FxHashMap::default();
178171

179172
for prop in &obj.properties {
180-
let ObjectPropertyKind::ObjectProperty(prop) = prop else {
173+
if prop.is_spread() {
181174
// Spread elements — keys are unknown at static analysis time
182175
continue;
183-
};
184-
185-
// Computed properties — keys are unknown at static analysis time
186-
if prop.computed {
187-
continue;
188176
}
177+
let ObjectPropertyKind::ObjectProperty(prop) = prop else {
178+
continue;
179+
};
189180

190-
let Some(key) = property_key_to_string(&prop.key) else {
181+
let Some(key) = prop.key.static_name() else {
182+
// Computed properties — keys are unknown at static analysis time
191183
continue;
192184
};
193185

194-
let value = expr_to_json(&prop.value)
195-
.map_or(StaticFieldValue::NonStatic, StaticFieldValue::Json);
196-
map.insert(key, value);
186+
let value =
187+
expr_to_json(&prop.value).map_or(StaticFieldValue::NonStatic, StaticFieldValue::Json);
188+
map.insert(Box::from(key.as_ref()), value);
197189
}
198190

199191
map
200192
}
201193

202-
/// Convert a property key to a string.
203-
fn property_key_to_string(key: &PropertyKey<'_>) -> Option<Box<str>> {
204-
match key {
205-
PropertyKey::StaticIdentifier(ident) => Some(Box::from(ident.name.as_str())),
206-
PropertyKey::StringLiteral(lit) => Some(Box::from(lit.value.as_str())),
207-
PropertyKey::NumericLiteral(lit) => {
208-
let s = if lit.value.fract() == 0.0 && lit.value.is_finite() {
209-
#[expect(clippy::cast_possible_truncation)]
210-
{
211-
(lit.value as i64).to_string()
212-
}
213-
} else {
214-
lit.value.to_string()
215-
};
216-
Some(Box::from(s.as_str()))
217-
}
218-
_ => None,
219-
}
220-
}
221-
222194
/// Convert an f64 to a JSON value, preserving integers when possible.
223195
#[expect(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
224196
fn f64_to_json_number(value: f64) -> serde_json::Value {
@@ -252,13 +224,8 @@ fn expr_to_json(expr: &Expression<'_>) -> Option<serde_json::Value> {
252224
Expression::StringLiteral(lit) => Some(serde_json::Value::String(lit.value.to_string())),
253225

254226
Expression::TemplateLiteral(lit) => {
255-
// Only convert template literals with no expressions (pure strings)
256-
if lit.expressions.is_empty() && lit.quasis.len() == 1 {
257-
let raw = &lit.quasis[0].value.cooked.as_ref()?;
258-
Some(serde_json::Value::String(raw.to_string()))
259-
} else {
260-
None
261-
}
227+
let quasi = lit.single_quasi()?;
228+
Some(serde_json::Value::String(quasi.to_string()))
262229
}
263230

264231
Expression::UnaryExpression(unary) => {
@@ -274,17 +241,13 @@ fn expr_to_json(expr: &Expression<'_>) -> Option<serde_json::Value> {
274241
Expression::ArrayExpression(arr) => {
275242
let mut values = Vec::with_capacity(arr.elements.len());
276243
for elem in &arr.elements {
277-
match elem {
278-
ArrayExpressionElement::Elision(_) => {
279-
values.push(serde_json::Value::Null);
280-
}
281-
ArrayExpressionElement::SpreadElement(_) => {
282-
return None;
283-
}
284-
_ => {
285-
let elem_expr = elem.as_expression()?;
286-
values.push(expr_to_json(elem_expr)?);
287-
}
244+
if elem.is_elision() {
245+
values.push(serde_json::Value::Null);
246+
} else if elem.is_spread() {
247+
return None;
248+
} else {
249+
let elem_expr = elem.as_expression()?;
250+
values.push(expr_to_json(elem_expr)?);
288251
}
289252
}
290253
Some(serde_json::Value::Array(values))
@@ -293,19 +256,15 @@ fn expr_to_json(expr: &Expression<'_>) -> Option<serde_json::Value> {
293256
Expression::ObjectExpression(obj) => {
294257
let mut map = serde_json::Map::new();
295258
for prop in &obj.properties {
296-
match prop {
297-
ObjectPropertyKind::ObjectProperty(prop) => {
298-
if prop.computed {
299-
return None;
300-
}
301-
let key = property_key_to_json_key(&prop.key)?;
302-
let value = expr_to_json(&prop.value)?;
303-
map.insert(key, value);
304-
}
305-
ObjectPropertyKind::SpreadProperty(_) => {
306-
return None;
307-
}
259+
if prop.is_spread() {
260+
return None;
308261
}
262+
let ObjectPropertyKind::ObjectProperty(prop) = prop else {
263+
continue;
264+
};
265+
let key = prop.key.static_name()?;
266+
let value = expr_to_json(&prop.value)?;
267+
map.insert(key.into_owned(), value);
309268
}
310269
Some(serde_json::Value::Object(map))
311270
}
@@ -314,26 +273,6 @@ fn expr_to_json(expr: &Expression<'_>) -> Option<serde_json::Value> {
314273
}
315274
}
316275

317-
/// Convert a property key to a JSON-compatible string key.
318-
#[expect(clippy::disallowed_types)]
319-
fn property_key_to_json_key(key: &PropertyKey<'_>) -> Option<String> {
320-
match key {
321-
PropertyKey::StaticIdentifier(ident) => Some(ident.name.to_string()),
322-
PropertyKey::StringLiteral(lit) => Some(lit.value.to_string()),
323-
PropertyKey::NumericLiteral(lit) => {
324-
if lit.value.fract() == 0.0 && lit.value.is_finite() {
325-
#[expect(clippy::cast_possible_truncation)]
326-
{
327-
Some((lit.value as i64).to_string())
328-
}
329-
} else {
330-
Some(lit.value.to_string())
331-
}
332-
}
333-
_ => None,
334-
}
335-
}
336-
337276
#[cfg(test)]
338277
mod tests {
339278
use tempfile::TempDir;

0 commit comments

Comments
 (0)