difftreelog
style fix clippy warnings
in: master
19 files changed
bindings/jsonnet/src/import.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/import.rs
+++ b/bindings/jsonnet/src/import.rs
@@ -64,7 +64,7 @@
self.ctx,
base.as_ptr(),
rel.as_ptr(),
- &mut (found_here as *const _),
+ &mut found_here.cast_const(),
&mut buf,
&mut buf_len,
)
@@ -121,7 +121,7 @@
cb,
ctx,
out: RefCell::new(HashMap::new()),
- })
+ });
}
/// # Safety
bindings/jsonnet/src/lib.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -86,7 +86,6 @@
let state = State::default();
state.settings_mut().import_resolver = tb!(FileImportResolver::default());
state.settings_mut().context_initializer = tb!(jrsonnet_stdlib::ContextInitializer::new(
- state.clone(),
PathResolver::new_cwd_fallback(),
));
Box::into_raw(Box::new(VM {
@@ -107,7 +106,7 @@
/// Set the maximum stack depth.
#[no_mangle]
pub extern "C" fn jsonnet_max_stack(_vm: &VM, v: c_uint) {
- set_stack_depth_limit(v as usize)
+ set_stack_depth_limit(v as usize);
}
/// Set the number of objects required before a garbage collection cycle is allowed.
@@ -175,7 +174,7 @@
#[no_mangle]
pub extern "C" fn jsonnet_max_trace(vm: &mut VM, v: c_uint) {
if let Some(format) = vm.trace_format.as_any_mut().downcast_mut::<CompactFormat>() {
- format.max_trace = v as usize
+ format.max_trace = v as usize;
} else {
panic!("max_trace is not supported by current tracing format")
}
@@ -183,7 +182,7 @@
/// Evaluate a file containing Jsonnet code, return a JSON string.
///
-/// The returned string should be cleaned up with jsonnet_realloc.
+/// The returned string should be cleaned up with `jsonnet_realloc`.
///
/// # Safety
///
@@ -216,7 +215,7 @@
/// Evaluate a string containing Jsonnet code, return a JSON string.
///
-/// The returned string should be cleaned up with jsonnet_realloc.
+/// The returned string should be cleaned up with `jsonnet_realloc`.
///
/// # Safety
///
@@ -359,7 +358,7 @@
out.push(0);
let v = out.as_ptr();
std::mem::forget(out);
- v as *const c_char
+ v.cast::<c_char>()
}
/// # Safety
bindings/jsonnet/src/val_extract.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_extract.rs
+++ b/bindings/jsonnet/src/val_extract.rs
@@ -26,7 +26,7 @@
pub extern "C" fn jsonnet_json_extract_number(_vm: &VM, v: &Val, out: &mut c_double) -> c_int {
match v {
Val::Num(n) => {
- *out = *n;
+ *out = n.get();
1
}
_ => 0,
bindings/jsonnet/src/val_make.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_make.rs
+++ b/bindings/jsonnet/src/val_make.rs
@@ -5,7 +5,10 @@
os::raw::{c_char, c_double, c_int},
};
-use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};
+use jrsonnet_evaluator::{
+ val::{ArrValue, NumValue},
+ ObjValue, Val,
+};
use crate::VM;
@@ -24,7 +27,9 @@
/// Convert the given double to a `JsonnetJsonValue`.
#[no_mangle]
pub extern "C" fn jsonnet_json_make_number(_vm: &VM, v: c_double) -> *mut Val {
- Box::into_raw(Box::new(Val::Num(v)))
+ Box::into_raw(Box::new(Val::Num(
+ NumValue::new(v).expect("jsonnet numbers are finite"),
+ )))
}
/// Convert the given `bool` (`1` or `0`) to a `JsonnetJsonValue`.
bindings/jsonnet/src/val_modify.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/val_modify.rs
+++ b/bindings/jsonnet/src/val_modify.rs
@@ -12,7 +12,7 @@
///
/// # Safety
///
-/// `arr` should be a pointer to array value allocated by make_array, or returned by other library call
+/// `arr` should be a pointer to array value allocated by `make_array`, or returned by other library call
/// `val` should be a pointer to value allocated using this library
#[no_mangle]
pub unsafe extern "C" fn jsonnet_json_array_append(_vm: &VM, arr: &mut Val, val: &Val) {
bindings/jsonnet/src/vars_tlas.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/vars_tlas.rs
+++ b/bindings/jsonnet/src/vars_tlas.rs
@@ -27,7 +27,7 @@
.add_ext_str(
name.to_str().expect("name is not utf-8").into(),
value.to_str().expect("value is not utf-8").into(),
- )
+ );
}
/// Binds a Jsonnet external variable to the given code.
@@ -51,7 +51,7 @@
name.to_str().expect("name is not utf-8"),
code.to_str().expect("code is not utf-8"),
)
- .expect("can't parse ext code")
+ .expect("can't parse ext code");
}
/// Binds a top-level string argument for a top-level parameter.
cmds/jrsonnet-fmt/src/children.rsdiffbeforeafterboth--- a/cmds/jrsonnet-fmt/src/children.rs
+++ b/cmds/jrsonnet-fmt/src/children.rs
@@ -28,7 +28,7 @@
TS![, ;].contains(item.kind()),
"silently eaten token: {:?}",
item.kind()
- )
+ );
}
}
out
@@ -48,13 +48,13 @@
if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
out.push(Ok(trivia));
} else if CustomError::can_cast(item.kind()) {
- out.push(Err(item.to_string()))
+ out.push(Err(item.to_string()));
} else {
assert!(
TS![, ;].contains(item.kind()),
"silently eaten token: {:?}",
item.kind()
- )
+ );
}
}
out
@@ -115,11 +115,7 @@
TriviaKind::Whitespace => {
nl_count += t.text().bytes().filter(|b| *b == b'\n').count();
}
- TriviaKind::SingleLineHashComment => {
- nl_count += 1;
- break;
- }
- TriviaKind::SingleLineSlashComment => {
+ TriviaKind::SingleLineHashComment | TriviaKind::SingleLineSlashComment => {
nl_count += 1;
break;
}
@@ -163,7 +159,7 @@
inline_trivia: Vec::new(),
});
if let Some(last_child) = last_child {
- out.push(last_child)
+ out.push(last_child);
}
had_some = true;
started_next = false;
@@ -188,7 +184,7 @@
}
had_some = true;
} else if CustomError::can_cast(item.kind()) {
- next.push(Err(item.to_string()))
+ next.push(Err(item.to_string()));
} else if loose {
if had_some {
break;
@@ -199,7 +195,7 @@
TS![, ;].contains(item.kind()),
"silently eaten token: {:?}",
item.kind()
- )
+ );
}
}
cmds/jrsonnet-fmt/src/comments.rsdiffbeforeafterboth--- a/cmds/jrsonnet-fmt/src/comments.rs
+++ b/cmds/jrsonnet-fmt/src/comments.rs
@@ -1,3 +1,5 @@
+use std::string::String;
+
use dprint_core::formatting::PrintItems;
use jrsonnet_rowan_parser::{nodes::TriviaKind, AstToken};
@@ -12,6 +14,7 @@
EndOfItems,
}
+#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation, out: &mut PrintItems) {
for c in comments {
let Ok(c) = c else {
@@ -62,14 +65,14 @@
}
})
.collect::<Vec<_>>();
- while lines.last().map(|l| l.is_empty()).unwrap_or(false) {
+ while lines.last().is_some_and(String::is_empty) {
lines.pop();
}
if lines.len() == 1 && !doc {
if matches!(loc, CommentLocation::ItemInline) {
p!(out, str(" "));
}
- p!(out, str("/* ") string(lines[0].trim().to_string()) str(" */") nl)
+ p!(out, str("/* ") string(lines[0].trim().to_string()) str(" */") nl);
} else if !lines.is_empty() {
fn common_ws_prefix<'a>(a: &'a str, b: &str) -> &'a str {
let offset = a
@@ -95,7 +98,7 @@
}
for line in lines
.iter_mut()
- .skip(if immediate_start { 1 } else { 0 })
+ .skip(usize::from(immediate_start))
.filter(|l| !l.is_empty())
{
*line = line
@@ -127,13 +130,13 @@
}
line = new_line.to_string();
}
- p!(out, string(line.to_string()) nl)
+ p!(out, string(line.to_string()) nl);
}
}
if doc {
p!(out, str(" "));
}
- p!(out, str("*/") nl)
+ p!(out, str("*/") nl);
}
}
// TODO: Keep common padding for multiple continous lines of single-line comments
@@ -154,20 +157,20 @@
// ```
TriviaKind::SingleLineHashComment => {
if matches!(loc, CommentLocation::ItemInline) {
- p!(out, str(" "))
+ p!(out, str(" "));
}
p!(out, str("# ") string(c.text().strip_prefix('#').expect("hash comment starts with #").trim().to_string()));
if !matches!(loc, CommentLocation::ItemInline) {
- p!(out, nl)
+ p!(out, nl);
}
}
TriviaKind::SingleLineSlashComment => {
if matches!(loc, CommentLocation::ItemInline) {
- p!(out, str(" "))
+ p!(out, str(" "));
}
p!(out, str("// ") string(c.text().strip_prefix("//").expect("comment starts with //").trim().to_string()));
if !matches!(loc, CommentLocation::ItemInline) {
- p!(out, nl)
+ p!(out, nl);
}
}
// Garbage in - garbage out
cmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet-fmt/src/main.rs
+++ b/cmds/jrsonnet-fmt/src/main.rs
@@ -13,6 +13,7 @@
condition_helpers::is_multiple_lines, condition_resolvers::true_resolver,
ConditionResolverContext, LineNumber, PrintItems, PrintOptions,
};
+use hi_doc::Formatting;
use jrsonnet_rowan_parser::{
nodes::{
Arg, ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,
@@ -155,7 +156,7 @@
{
fn print(&self, out: &mut PrintItems) {
if let Some(v) = self {
- v.print(out)
+ v.print(out);
} else {
p!(
out,
@@ -163,31 +164,31 @@
"/*missing {}*/",
type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")
),)
- )
+ );
}
}
}
impl Printable for SyntaxToken {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.to_string()))
+ p!(out, string(self.to_string()));
}
}
impl Printable for Text {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(format!("{}", self)))
+ p!(out, string(format!("{}", self)));
}
}
impl Printable for Number {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(format!("{}", self)))
+ p!(out, string(format!("{}", self)));
}
}
impl Printable for Name {
fn print(&self, out: &mut PrintItems) {
- p!(out, { self.ident_lit() })
+ p!(out, { self.ident_lit() });
}
}
@@ -203,30 +204,30 @@
impl Printable for Destruct {
fn print(&self, out: &mut PrintItems) {
match self {
- Destruct::DestructFull(f) => {
- p!(out, { f.name() })
+ Self::DestructFull(f) => {
+ p!(out, { f.name() });
}
- Destruct::DestructSkip(_) => p!(out, str("?")),
- Destruct::DestructArray(a) => {
+ Self::DestructSkip(_) => p!(out, str("?")),
+ Self::DestructArray(a) => {
p!(out, str("[") >i nl);
for el in a.destruct_array_parts() {
match el {
DestructArrayPart::DestructArrayElement(e) => {
- p!(out, {e.destruct()} str(",") nl)
+ p!(out, {e.destruct()} str(",") nl);
}
DestructArrayPart::DestructRest(d) => {
- p!(out, {d} str(",") nl)
+ p!(out, {d} str(",") nl);
}
}
}
p!(out, <i str("]"));
}
- Destruct::DestructObject(o) => {
+ Self::DestructObject(o) => {
p!(out, str("{") >i nl);
for item in o.destruct_object_fields() {
p!(out, { item.field() });
if let Some(des) = item.destruct() {
- p!(out, str(": ") {des})
+ p!(out, str(": ") {des});
}
if let Some(def) = item.expr() {
p!(out, str(" = ") {def});
@@ -234,7 +235,7 @@
p!(out, str(",") nl);
}
if let Some(rest) = o.destruct_rest() {
- p!(out, {rest} nl)
+ p!(out, {rest} nl);
}
p!(out, <i str("}"));
}
@@ -245,17 +246,17 @@
impl Printable for FieldName {
fn print(&self, out: &mut PrintItems) {
match self {
- FieldName::FieldNameFixed(f) => {
+ Self::FieldNameFixed(f) => {
if let Some(id) = f.id() {
- p!(out, { id })
+ p!(out, { id });
} else if let Some(str) = f.text() {
- p!(out, { str })
+ p!(out, { str });
} else {
- p!(out, str("/*missing FieldName*/"))
+ p!(out, str("/*missing FieldName*/"));
}
}
- FieldName::FieldNameDynamic(d) => {
- p!(out, str("[") {d.expr()} str("]"))
+ Self::FieldNameDynamic(d) => {
+ p!(out, str("[") {d.expr()} str("]"));
}
}
}
@@ -263,13 +264,13 @@
impl Printable for Visibility {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.to_string()))
+ p!(out, string(self.to_string()));
}
}
impl Printable for ObjLocal {
fn print(&self, out: &mut PrintItems) {
- p!(out, str("local ") {self.bind()})
+ p!(out, str("local ") {self.bind()});
}
}
@@ -277,7 +278,7 @@
fn print(&self, out: &mut PrintItems) {
p!(out, str("assert ") {self.condition()});
if self.colon_token().is_some() || self.message().is_some() {
- p!(out, str(": ") {self.message()})
+ p!(out, str(": ") {self.message()});
}
}
}
@@ -288,9 +289,9 @@
for param in self.params() {
p!(out, { param.destruct() });
if param.assign_token().is_some() || param.expr().is_some() {
- p!(out, str(" = ") {param.expr()})
+ p!(out, str(" = ") {param.expr()});
}
- p!(out, str(",") nl)
+ p!(out, str(",") nl);
}
p!(out, <i str(")"));
}
@@ -343,7 +344,7 @@
}
p!(out, str(":"));
if self.end().is_some() {
- p!(out, { self.end().map(|e| e.expr()) })
+ p!(out, { self.end().map(|e| e.expr()) });
}
// Keep only one : in case if we don't need step
if self.step().is_some() {
@@ -357,16 +358,16 @@
fn print(&self, out: &mut PrintItems) {
match self {
Self::MemberBindStmt(b) => {
- p!(out, { b.obj_local() })
+ p!(out, { b.obj_local() });
}
Self::MemberAssertStmt(ass) => {
- p!(out, { ass.assertion() })
+ p!(out, { ass.assertion() });
}
Self::MemberFieldNormal(n) => {
- p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})
+ p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()});
}
Self::MemberFieldMethod(m) => {
- p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})
+ p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()});
}
}
}
@@ -375,7 +376,7 @@
impl Printable for ObjBody {
fn print(&self, out: &mut PrintItems) {
match self {
- ObjBody::ObjBodyComp(l) => {
+ Self::ObjBodyComp(l) => {
let (children, mut end_comments) = children_between::<Member>(
l.syntax().clone(),
l.l_brace_token().map(Into::into).as_ref(),
@@ -391,14 +392,14 @@
);
let trailing_for_comp = end_comments.extract_trailing();
p!(out, str("{") >i nl);
- for mem in children.into_iter() {
+ for mem in children {
if mem.should_start_with_newline {
p!(out, nl);
}
format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);
p!(out, {mem.value} str(","));
format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);
- p!(out, nl)
+ p!(out, nl);
}
if end_comments.should_start_with_newline {
@@ -417,7 +418,7 @@
l.r_brace_token().map(Into::into).as_ref(),
Some(trailing_for_comp),
);
- for mem in compspecs.into_iter() {
+ for mem in compspecs {
if mem.should_start_with_newline {
p!(out, nl);
}
@@ -432,7 +433,7 @@
p!(out, nl <i str("}"));
}
- ObjBody::ObjBodyMemberList(l) => {
+ Self::ObjBodyMemberList(l) => {
let (children, end_comments) = children_between::<Member>(
l.syntax().clone(),
l.l_brace_token().map(Into::into).as_ref(),
@@ -451,7 +452,7 @@
format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);
p!(out, {mem.value} str(","));
format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);
- p!(out, nl)
+ p!(out, nl);
}
if end_comments.should_start_with_newline {
@@ -465,51 +466,51 @@
}
impl Printable for UnaryOperator {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.text().to_string()))
+ p!(out, string(self.text().to_string()));
}
}
impl Printable for BinaryOperator {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.text().to_string()))
+ p!(out, string(self.text().to_string()));
}
}
impl Printable for Bind {
fn print(&self, out: &mut PrintItems) {
match self {
- Bind::BindDestruct(d) => {
- p!(out, {d.into()} str(" = ") {d.value()})
+ Self::BindDestruct(d) => {
+ p!(out, {d.into()} str(" = ") {d.value()});
}
- Bind::BindFunction(f) => {
- p!(out, {f.name()} {f.params()} str(" = ") {f.value()})
+ Self::BindFunction(f) => {
+ p!(out, {f.name()} {f.params()} str(" = ") {f.value()});
}
}
}
}
impl Printable for Literal {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.syntax().to_string()))
+ p!(out, string(self.syntax().to_string()));
}
}
impl Printable for ImportKind {
fn print(&self, out: &mut PrintItems) {
- p!(out, string(self.syntax().to_string()))
+ p!(out, string(self.syntax().to_string()));
}
}
impl Printable for ForSpec {
fn print(&self, out: &mut PrintItems) {
- p!(out, str("for ") {self.bind()} str(" in ") {self.expr()})
+ p!(out, str("for ") {self.bind()} str(" in ") {self.expr()});
}
}
impl Printable for IfSpec {
fn print(&self, out: &mut PrintItems) {
- p!(out, str("if ") {self.expr()})
+ p!(out, str("if ") {self.expr()});
}
}
impl Printable for CompSpec {
fn print(&self, out: &mut PrintItems) {
match self {
- CompSpec::ForSpec(f) => f.print(out),
- CompSpec::IfSpec(i) => i.print(out),
+ Self::ForSpec(f) => f.print(out),
+ Self::IfSpec(i) => i.print(out),
}
}
}
@@ -549,23 +550,23 @@
impl Printable for Suffix {
fn print(&self, out: &mut PrintItems) {
match self {
- Suffix::SuffixIndex(i) => {
+ Self::SuffixIndex(i) => {
if i.question_mark_token().is_some() {
p!(out, str("?"));
}
p!(out, str(".") {i.index()});
}
- Suffix::SuffixIndexExpr(e) => {
+ Self::SuffixIndexExpr(e) => {
if e.question_mark_token().is_some() {
p!(out, str(".?"));
}
- p!(out, str("[") {e.index()} str("]"))
+ p!(out, str("[") {e.index()} str("]"));
}
- Suffix::SuffixSlice(d) => {
- p!(out, { d.slice_desc() })
+ Self::SuffixSlice(d) => {
+ p!(out, { d.slice_desc() });
}
- Suffix::SuffixApply(a) => {
- p!(out, { a.args_desc() })
+ Self::SuffixApply(a) => {
+ p!(out, { a.args_desc() });
}
}
}
@@ -573,7 +574,7 @@
impl Printable for Stmt {
fn print(&self, out: &mut PrintItems) {
match self {
- Stmt::StmtLocal(l) => {
+ Self::StmtLocal(l) => {
let (binds, end_comments) = children_between::<Bind>(
l.syntax().clone(),
l.local_kw_token().map(Into::into).as_ref(),
@@ -594,18 +595,18 @@
format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);
p!(out, {bind.value} str(","));
format_comments(&bind.inline_trivia, CommentLocation::ItemInline, out);
- p!(out, nl)
+ p!(out, nl);
}
if end_comments.should_start_with_newline {
- p!(out, nl)
+ p!(out, nl);
}
format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);
p!(out,<i);
}
p!(out,str(";") nl);
}
- Stmt::StmtAssert(a) => {
- p!(out, {a.assertion()} str(";") nl)
+ Self::StmtAssert(a) => {
+ p!(out, {a.assertion()} str(";") nl);
}
}
}
@@ -614,7 +615,7 @@
fn print(&self, out: &mut PrintItems) {
match self {
Self::ExprBinary(b) => {
- p!(out, {b.lhs_work()} str(" ") {b.binary_operator()} str(" ") {b.rhs_work()})
+ p!(out, {b.lhs_work()} str(" ") {b.binary_operator()} str(" ") {b.rhs_work()});
}
Self::ExprUnary(u) => p!(out, {u.unary_operator()} {u.rhs()}),
// Self::ExprSlice(s) => {
@@ -632,10 +633,10 @@
// pi
// }
Self::ExprObjExtend(ex) => {
- p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()})
+ p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()});
}
Self::ExprParened(p) => {
- p!(out, str("(") {p.expr()} str(")"))
+ p!(out, str("(") {p.expr()} str(")"));
}
Self::ExprString(s) => p!(out, { s.text() }),
Self::ExprNumber(n) => p!(out, { n.number() }),
@@ -647,7 +648,7 @@
p!(out, <i str("]"));
}
Self::ExprObject(obj) => {
- p!(out, { obj.obj_body() })
+ p!(out, { obj.obj_body() });
}
Self::ExprArrayComp(arr) => {
p!(out, str("[") {arr.expr()});
@@ -657,7 +658,7 @@
p!(out, str("]"));
}
Self::ExprImport(v) => {
- p!(out, {v.import_kind()} str(" ") {v.text()})
+ p!(out, {v.import_kind()} str(" ") {v.text()});
}
Self::ExprVar(n) => p!(out, { n.name() }),
// Self::ExprLocal(l) => {
@@ -665,14 +666,14 @@
Self::ExprIfThenElse(ite) => {
p!(out, str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});
if ite.else_kw_token().is_some() || ite.else_().is_some() {
- p!(out, str(" else ") {ite.else_().map(|t| t.expr())})
+ p!(out, str(" else ") {ite.else_().map(|t| t.expr())});
}
}
Self::ExprFunction(f) => p!(out, str("function") {f.params_desc()} nl {f.expr()}),
// Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),
Self::ExprError(e) => p!(out, str("error ") {e.expr()}),
Self::ExprLiteral(l) => {
- p!(out, { l.literal() })
+ p!(out, { l.literal() });
}
}
}
@@ -696,7 +697,7 @@
);
format_comments(&before, CommentLocation::AboveItem, out);
p!(out, {self.expr()} nl);
- format_comments(&after, CommentLocation::EndOfItems, out)
+ format_comments(&after, CommentLocation::EndOfItems, out);
}
}
@@ -712,7 +713,7 @@
builder
.error(hi_doc::Text::single(
format!("{:?}", error.error).chars(),
- Default::default(),
+ Formatting::default(),
))
.range(
error.range.start().into()
@@ -751,6 +752,7 @@
}
#[derive(Parser)]
+#[allow(clippy::struct_excessive_bools)]
struct Opts {
/// Treat input as code, reformat it instead of reading file.
#[clap(long, short = 'e')]
@@ -814,7 +816,7 @@
let mut iteration = 0;
let mut formatted = input.clone();
- let mut tmp;
+ let mut convergence_tmp;
// https://github.com/dprint/dprint/pull/423
loop {
let Some(reformatted) = format(
@@ -829,18 +831,16 @@
) else {
return Err(Error::Parse);
};
- tmp = reformatted.trim().to_owned();
- if formatted == tmp {
+ convergence_tmp = reformatted.trim().to_owned();
+ if formatted == convergence_tmp {
break;
}
- formatted = tmp;
+ formatted = convergence_tmp;
if opts.conv_limit == 0 {
break;
}
iteration += 1;
- if iteration > opts.conv_limit {
- panic!("formatting not converged");
- }
+ assert!(iteration <= opts.conv_limit, "formatting not converged");
}
formatted.push('\n');
if opts.test && formatted != input {
@@ -855,7 +855,7 @@
temp.flush()?;
temp.persist(&path)?;
} else {
- print!("{formatted}")
+ print!("{formatted}");
}
Ok(())
}
crates/jrsonnet-rowan-parser/src/lex.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/lex.rs
+++ b/crates/jrsonnet-rowan-parser/src/lex.rs
@@ -37,9 +37,10 @@
// In kinds, string blocks is parsed at least as `|||`
lexer.bump(3);
let res = lex_str_block(&mut lexer);
- debug_assert!(lexer.next().is_none(), "str_block is lexed");
+ let next = lexer.next();
+ assert!(next.is_none(), "str_block is lexed");
match res {
- Ok(_) => {}
+ Ok(()) => {}
Err(e) => {
kind = Ok(match e {
StringBlockError::UnexpectedEnd => ERROR_STRING_BLOCK_UNEXPECTED_END,
@@ -48,7 +49,7 @@
ERROR_STRING_BLOCK_MISSING_TERMINATION
}
StringBlockError::MissingIndent => ERROR_STRING_BLOCK_MISSING_INDENT,
- })
+ });
}
}
}
crates/jrsonnet-rowan-parser/src/marker.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/marker.rs
+++ b/crates/jrsonnet-rowan-parser/src/marker.rs
@@ -146,7 +146,7 @@
p: &mut Parser,
kind: SyntaxKind,
error: Option<SyntaxError>,
- ) -> CompletedMarker {
+ ) -> Self {
let new_m = p.start();
match &mut p.events[self.start_event_idx] {
Event::Start { forward_parent, .. } => {
@@ -173,10 +173,10 @@
}
completed
}
- pub fn wrap(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
+ pub fn wrap(self, p: &mut Parser, kind: SyntaxKind) -> Self {
self.wrap_raw(p, kind, None)
}
- pub fn wrap_error(self, p: &mut Parser, msg: impl AsRef<str>) -> CompletedMarker {
+ pub fn wrap_error(self, p: &mut Parser, msg: impl AsRef<str>) -> Self {
self.wrap_raw(
p,
SyntaxKind::ERROR_CUSTOM,
crates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/parser.rs
+++ b/crates/jrsonnet-rowan-parser/src/parser.rs
@@ -72,9 +72,9 @@
.rev()
.take_while(|h| h.0 > self.entered)
.count();
- self.hints.truncate(self.hints.len() - amount)
+ self.hints.truncate(self.hints.len() - amount);
}
- fn clear_expected_syntaxes(&mut self) {
+ fn clear_expected_syntaxes(&self) {
self.expected_syntax_tracking_state
.set(ExpectedSyntax::Unnamed(TS![]));
}
@@ -104,7 +104,7 @@
}
pub(crate) fn expect(&mut self, kind: SyntaxKind) {
- self.expect_with_recovery_set(kind, TS![])
+ self.expect_with_recovery_set(kind, TS![]);
}
pub(crate) fn expect_with_recovery_set(
@@ -153,7 +153,7 @@
m
}
fn bump_assert(&mut self, kind: SyntaxKind) {
- assert!(self.at(kind), "expected {:?}", kind);
+ assert!(self.at(kind), "expected {kind:?}");
self.bump_remap(self.current());
}
fn bump(&mut self) {
@@ -168,11 +168,11 @@
fn step(&self) {
use std::fmt::Write;
let steps = self.steps.get();
- if steps >= 15000000 {
+ if steps >= 15_000_000 {
let mut out = "seems like parsing is stuck".to_owned();
{
let last = 20;
- write!(out, "\n\nLast {} events:", last).unwrap();
+ write!(out, "\n\nLast {last} events:").unwrap();
for (i, event) in self
.events
.iter()
@@ -205,38 +205,38 @@
self.nth(0)
}
#[must_use]
- pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {
+ pub(crate) fn expected_syntax_name(&self, name: &'static str) -> ExpectedSyntaxGuard {
self.expected_syntax_tracking_state
.set(ExpectedSyntax::Named(name));
ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))
}
- pub fn at(&mut self, kind: SyntaxKind) -> bool {
+ pub fn at(&self, kind: SyntaxKind) -> bool {
self.nth_at(0, kind)
}
- pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {
+ pub fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
if n == 0 {
if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {
let kinds = kinds.with(kind);
self.expected_syntax_tracking_state
- .set(ExpectedSyntax::Unnamed(kinds))
+ .set(ExpectedSyntax::Unnamed(kinds));
}
}
self.nth(n) == kind
}
- pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {
+ pub fn at_ts(&self, set: SyntaxKindSet) -> bool {
if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {
let kinds = kinds.union(set);
self.expected_syntax_tracking_state
- .set(ExpectedSyntax::Unnamed(kinds))
+ .set(ExpectedSyntax::Unnamed(kinds));
}
set.contains(self.current())
}
- pub fn at_end(&mut self) -> bool {
+ pub fn at_end(&self) -> bool {
self.at(EOF)
}
}
-pub(crate) struct ExpectedSyntaxGuard {
+pub struct ExpectedSyntaxGuard {
expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,
}
@@ -263,8 +263,8 @@
impl fmt::Display for ExpectedSyntax {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- ExpectedSyntax::Named(name) => write!(f, "{name}"),
- ExpectedSyntax::Unnamed(set) => write!(f, "{set}"),
+ Self::Named(name) => write!(f, "{name}"),
+ Self::Unnamed(set) => write!(f, "{set}"),
}
}
}
@@ -298,8 +298,7 @@
}
}
match expr_binding_power(p, 0) {
- Ok(m) => m,
- Err(m) => m,
+ Ok(m) | Err(m) => m,
};
m.complete(p, EXPR)
}
@@ -399,7 +398,7 @@
}
fn visibility(p: &mut Parser) {
if p.at_ts(TS![: :: :::]) {
- p.bump()
+ p.bump();
} else {
p.error_with_recovery_set(TS![=]);
}
@@ -556,7 +555,7 @@
expr(p);
let arg = m.complete(p, ARG);
if started_named.get() {
- unnamed_after_named.push(arg)
+ unnamed_after_named.push(arg);
}
}
if comma(p) {
@@ -566,7 +565,7 @@
}
p.expect(T![')']);
if p.at(T![tailstrict]) {
- p.bump()
+ p.bump();
}
for errored in unnamed_after_named {
@@ -719,7 +718,7 @@
let m = p.start();
p.bump_assert(T![...]);
if p.at(IDENT) {
- p.bump()
+ p.bump();
}
m.complete(p, DESTRUCT_REST);
}
crates/jrsonnet-rowan-parser/src/precedence.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/precedence.rs
+++ b/crates/jrsonnet-rowan-parser/src/precedence.rs
@@ -13,8 +13,7 @@
Self::BitXor => (8, 9),
Self::BitOr => (6, 7),
Self::And => (4, 5),
- Self::NullCoaelse => (2, 3),
- Self::Or => (2, 3),
+ Self::NullCoaelse | Self::Or => (2, 3),
Self::ErrorNoOperator => (0, 1),
}
}
@@ -23,9 +22,7 @@
impl UnaryOperatorKind {
pub fn binding_power(&self) -> ((), u8) {
match self {
- Self::Minus => ((), 20),
- Self::Not => ((), 20),
- Self::BitNot => ((), 20),
+ Self::Minus | Self::Not | Self::BitNot => ((), 20),
}
}
}
crates/jrsonnet-rowan-parser/src/string_block.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/string_block.rs
+++ b/crates/jrsonnet-rowan-parser/src/string_block.rs
@@ -17,6 +17,7 @@
let _ = lex_str_block(lex);
}
+#[allow(clippy::too_many_lines)]
pub fn lex_str_block(lex: &mut Lexer<SyntaxKind>) -> Result<(), StringBlockError> {
struct Context<'a> {
source: &'a str,
@@ -78,6 +79,7 @@
};
}
+ #[allow(clippy::range_plus_one)]
fn pos(&self) -> Range<usize> {
if self.index == self.source.len() {
self.offset + self.index..self.offset + self.index
@@ -120,8 +122,7 @@
let end_index = ctx
.rest()
.find("|||")
- .map(|v| v + 3)
- .unwrap_or_else(|| ctx.rest().len());
+ .map_or_else(|| ctx.rest().len(), |v| v + 3);
lex.bump(ctx.index + end_index);
}
@@ -150,7 +151,7 @@
}
// Process leading blank lines before calculating string block indent
- while let Some('\n') = ctx.peek() {
+ while ctx.peek() == Some('\n') {
ctx.next();
}
@@ -179,7 +180,7 @@
}
// Skip any blank lines
- while let Some('\n') = ctx.peek() {
+ while ctx.peek() == Some('\n') {
ctx.next();
}
@@ -187,9 +188,11 @@
num_whitespace = check_whitespace(str_block_indent, ctx.rest());
if num_whitespace == 0 {
// End of the text block
- let mut term_indent = String::with_capacity(num_whitespace);
+ // let mut term_indent = String::with_capacity(num_whitespace);
while let Some(' ' | '\t') = ctx.peek() {
- term_indent.push(ctx.next().unwrap());
+ // term_indent.push(
+ ctx.next().unwrap();
+ // );
}
if !ctx.rest().starts_with("|||") {
crates/jrsonnet-rowan-parser/src/token_set.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/token_set.rs
+++ b/crates/jrsonnet-rowan-parser/src/token_set.rs
@@ -10,21 +10,23 @@
pub const EMPTY: Self = Self(0);
pub const ALL: Self = Self(u128::MAX);
- pub const fn new(kinds: &[SyntaxKind]) -> SyntaxKindSet {
+ pub const fn new(kinds: &[SyntaxKind]) -> Self {
let mut res = 0u128;
let mut i = 0;
while i < kinds.len() {
res |= mask(kinds[i]);
- i += 1
+ i += 1;
}
- SyntaxKindSet(res)
+ Self(res)
}
- pub const fn union(self, other: SyntaxKindSet) -> SyntaxKindSet {
- SyntaxKindSet(self.0 | other.0)
+ #[must_use]
+ pub const fn union(self, other: Self) -> Self {
+ Self(self.0 | other.0)
}
- pub const fn with(self, kind: SyntaxKind) -> SyntaxKindSet {
- SyntaxKindSet(self.0 | mask(kind))
+ #[must_use]
+ pub const fn with(self, kind: SyntaxKind) -> Self {
+ Self(self.0 | mask(kind))
}
pub fn contains(&self, kind: SyntaxKind) -> bool {
@@ -40,7 +42,7 @@
let mut variants = <Vec<SyntaxKind>>::new();
for i in 0..128 {
if v & 1 == 1 {
- variants.push(SyntaxKind::from_raw(i))
+ variants.push(SyntaxKind::from_raw(i));
}
v >>= 1;
if v == 0 {
@@ -65,7 +67,7 @@
let mut variants = <Vec<SyntaxKind>>::new();
for i in 0..128 {
if v & 1 == 1 {
- variants.push(SyntaxKind::from_raw(i))
+ variants.push(SyntaxKind::from_raw(i));
}
v >>= 1;
if v == 0 {
@@ -77,9 +79,7 @@
}
const fn mask(kind: SyntaxKind) -> u128 {
- if kind as u32 > 128 {
- panic!("mask for not a token kind")
- }
+ assert!(kind as u32 <= 128, "mask for not a token kind");
1u128 << (kind as u128)
}
xtask/src/sourcegen/ast.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/ast.rs
+++ b/xtask/src/sourcegen/ast.rs
@@ -72,7 +72,7 @@
pub fn is_many(&self) -> bool {
matches!(
self,
- Field::Node {
+ Self::Node {
cardinality: Cardinality::Many,
..
}
@@ -81,44 +81,41 @@
pub fn token_name(&self) -> Option<String> {
match self {
- Field::Token(token) => Some(token.clone()),
- _ => None,
+ Self::Token(token) => Some(token.clone()),
+ Self::Node { .. } => None,
}
}
pub fn token_kind(&self, kinds: &KindsSrc) -> Option<TokenStream> {
match self {
- Field::Token(token) => Some(kinds.token(token).expect("token exists").reference()),
- _ => None,
+ Self::Token(token) => Some(kinds.token(token).expect("token exists").reference()),
+ Self::Node { .. } => None,
}
}
pub fn is_token_enum(&self, grammar: &AstSrc) -> bool {
match self {
- Field::Node { ty, .. } => grammar.token_enums.iter().any(|e| &e.name == ty),
- _ => false,
+ Self::Node { ty, .. } => grammar.token_enums.iter().any(|e| &e.name == ty),
+ Self::Token(_) => false,
}
}
pub fn method_name(&self, kinds: &KindsSrc) -> proc_macro2::Ident {
match self {
- Field::Token(name) => kinds.token(name).expect("token exists").method_name(),
- Field::Node { name, .. } => {
+ Self::Token(name) => kinds.token(name).expect("token exists").method_name(),
+ Self::Node { name, .. } => {
format_ident!("{}", name)
}
}
}
pub fn ty(&self) -> proc_macro2::Ident {
match self {
- Field::Token(_) => format_ident!("SyntaxToken"),
- Field::Node { ty, .. } => format_ident!("{}", ty),
+ Self::Token(_) => format_ident!("SyntaxToken"),
+ Self::Node { ty, .. } => format_ident!("{}", ty),
}
}
}
pub fn lower(kinds: &KindsSrc, grammar: &Grammar) -> AstSrc {
- let mut res = AstSrc {
- // tokens,
- ..Default::default()
- };
+ let mut res = AstSrc::default();
let nodes = grammar.iter().collect::<Vec<_>>();
@@ -135,16 +132,15 @@
};
res.enums.push(enum_src);
}
- None => match lower_token_enum(grammar, rule) {
- Some(variants) => {
+ None => {
+ if let Some(variants) = lower_token_enum(grammar, rule) {
let tokens_enum_src = AstTokenEnumSrc {
doc: Vec::new(),
name,
variants,
};
res.token_enums.push(tokens_enum_src);
- }
- None => {
+ } else {
let mut fields = Vec::new();
lower_rule(&mut fields, grammar, None, rule, false);
let mut types = HashMap::new();
@@ -173,7 +169,7 @@
fields,
});
}
- },
+ }
}
}
@@ -240,7 +236,7 @@
acc.push(field);
}
Rule::Token(token) => {
- assert!(label.is_none(), "uexpected label: {:?}", label);
+ assert!(label.is_none(), "uexpected label: {label:?}");
let name = grammar[*token].name.clone();
let field = Field::Token(name);
acc.push(field);
@@ -267,7 +263,7 @@
}
Rule::Seq(rules) | Rule::Alt(rules) => {
for rule in rules {
- lower_rule(acc, grammar, label, rule, in_optional)
+ lower_rule(acc, grammar, label, rule, in_optional);
}
}
Rule::Opt(rule) => lower_rule(acc, grammar, label, rule, true),
xtask/src/sourcegen/kinds.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/kinds.rs
+++ b/xtask/src/sourcegen/kinds.rs
@@ -41,33 +41,33 @@
impl TokenKind {
pub fn grammar_name(&self) -> &str {
match self {
- TokenKind::Keyword { code, .. } => code,
- TokenKind::Literal { grammar_name, .. } => grammar_name,
- TokenKind::Meta { grammar_name, .. } => grammar_name,
- TokenKind::Error { grammar_name, .. } => grammar_name,
+ Self::Keyword { code, .. } => code,
+ Self::Literal { grammar_name, .. }
+ | Self::Meta { grammar_name, .. }
+ | Self::Error { grammar_name, .. } => grammar_name,
}
}
/// How this keyword should appear in kinds enum, screaming snake cased
pub fn name(&self) -> &str {
match self {
- TokenKind::Keyword { name, .. } => name,
- TokenKind::Literal { name, .. } => name,
- TokenKind::Meta { name, .. } => name,
- TokenKind::Error { name, .. } => name,
+ Self::Keyword { name, .. }
+ | Self::Literal { name, .. }
+ | Self::Meta { name, .. }
+ | Self::Error { name, .. } => name,
}
}
pub fn expand_kind(&self) -> TokenStream {
let name = format_ident!("{}", self.name());
let attr = match self {
- TokenKind::Keyword { code, .. } => quote! {#[token(#code)]},
- TokenKind::Literal { regex, lexer, .. } => {
+ Self::Keyword { code, .. } => quote! {#[token(#code)]},
+ Self::Literal { regex, lexer, .. } => {
let lexer = lexer
.as_deref()
.map(TokenStream::from_str)
.map(|r| r.expect("path is correct"));
quote! {#[regex(#regex, #lexer)]}
}
- TokenKind::Error {
+ Self::Error {
regex, priority, ..
} if regex.is_some() => {
let priority = priority.map(|p| quote! {, priority = #p});
@@ -82,7 +82,7 @@
}
pub fn expand_t_macros(&self) -> Option<TokenStream> {
match self {
- TokenKind::Keyword { code, name } => {
+ Self::Keyword { code, name } => {
let code = escape_token_macro(code);
let name = format_ident!("{name}");
Some(quote! {
@@ -98,29 +98,26 @@
/// Keywords are referenced with `T![_]` macro,
/// and literals are referenced directly by name
pub fn reference(&self) -> TokenStream {
- match self {
- TokenKind::Keyword { code, .. } => {
- let code = escape_token_macro(code);
- quote! {T![#code]}
- }
- _ => {
- let name = self.name();
- let ident = format_ident!("{name}");
- quote! {#ident}
- }
+ if let Self::Keyword { code, .. } = self {
+ let code = escape_token_macro(code);
+ quote! {T![#code]}
+ } else {
+ let name = self.name();
+ let ident = format_ident!("{name}");
+ quote! {#ident}
}
}
pub fn method_name(&self) -> Ident {
match self {
- TokenKind::Keyword { name, .. } => {
+ Self::Keyword { name, .. } => {
format_ident!("{}_token", name.to_lowercase())
}
- TokenKind::Literal { name, .. } => {
+ Self::Literal { name, .. } => {
format_ident!("{}_lit", name.to_lowercase())
}
- TokenKind::Meta { name, .. } => format_ident!("{}_meta", name.to_lowercase()),
- TokenKind::Error { name, .. } => format_ident!("{}_error", name.to_lowercase()),
+ Self::Meta { name, .. } => format_ident!("{}_meta", name.to_lowercase()),
+ Self::Error { name, .. } => format_ident!("{}_error", name.to_lowercase()),
}
}
}
@@ -188,15 +185,14 @@
.is_none(),
"token already defined: {}",
token.grammar_name()
- )
+ );
}
pub fn define_node(&mut self, node: &str) {
assert!(
self.defined_node_names.insert(node.to_owned()),
- "node name already defined: {}",
- node
+ "node name already defined: {node}"
);
- self.nodes.push(node.to_string())
+ self.nodes.push(node.to_string());
}
pub fn token(&self, tok: &str) -> Option<&TokenKind> {
self.defined_tokens.get(tok)
xtask/src/sourcegen/mod.rsdiffbeforeafterboth1use std::path::PathBuf;23use anyhow::Result;4use ast::{lower, AstSrc};5use itertools::Itertools;6use kinds::{KindsSrc, TokenKind};7use proc_macro2::{Punct, Spacing, TokenStream};8use quote::{format_ident, quote};9use ungrammar::Grammar;10use util::{ensure_file_contents, reformat, to_pascal_case, to_upper_snake_case};1112mod ast;13mod kinds;14mod util;1516enum SpecialName {17 Literal,18 Meta,19 Error,20}21fn classify_special(name: &str) -> Option<(SpecialName, &str)> {22 let name = name.strip_suffix('!')?;23 Some(if let Some(name) = name.strip_prefix("LIT_") {24 (SpecialName::Literal, name)25 } else if let Some(name) = name.strip_prefix("META_") {26 (SpecialName::Meta, name)27 } else if let Some(name) = name.strip_prefix("ERROR_") {28 (SpecialName::Error, name)29 } else {30 return None;31 })32}3334pub fn generate_ungrammar() -> Result<()> {35 let grammar: Grammar = include_str!(concat!(36 env!("CARGO_MANIFEST_DIR"),37 "/../crates/jrsonnet-rowan-parser/jsonnet.ungram"38 ))39 .parse()?;4041 let mut kinds = kinds::jsonnet_kinds();42 let ast = lower(&kinds, &grammar);4344 for token in grammar.tokens() {45 let token = &grammar[token];46 let token = &token.name.clone();47 if !kinds.is_token(token) {48 if let Some((special, name)) = classify_special(token) {49 match special {50 SpecialName::Literal => panic!("literal is not defined: {name}"),51 SpecialName::Meta => {52 eprintln!("implicit meta: {}", name);53 kinds.define_token(TokenKind::Meta {54 grammar_name: token.to_owned(),55 name: format!("META_{}", name),56 })57 }58 SpecialName::Error => {59 eprintln!("implicit error: {}", name);60 kinds.define_token(TokenKind::Error {61 grammar_name: token.to_owned(),62 name: format!("ERROR_{}", name),63 regex: None,64 priority: None,65 is_lexer_error: true,66 })67 }68 };69 continue;70 };71 let name = to_upper_snake_case(token);72 eprintln!("implicit kw: {}", token);73 kinds.define_token(TokenKind::Keyword {74 code: token.to_owned(),75 name: format!("{name}_KW"),76 });77 }78 }79 for node in &ast.nodes {80 let name = to_upper_snake_case(&node.name);81 kinds.define_node(&name);82 }83 for enum_ in &ast.enums {84 let name = to_upper_snake_case(&enum_.name);85 kinds.define_node(&name);86 }87 for token_enum in &ast.token_enums {88 let name = to_upper_snake_case(&token_enum.name);89 kinds.define_node(&name);90 }9192 let syntax_kinds = generate_syntax_kinds(&kinds, &ast)?;9394 let nodes = generate_nodes(&kinds, &ast)?;95 ensure_file_contents(96 &PathBuf::from(concat!(97 env!("CARGO_MANIFEST_DIR"),98 "/../crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs",99 )),100 &syntax_kinds,101 )?;102 ensure_file_contents(103 &PathBuf::from(concat!(104 env!("CARGO_MANIFEST_DIR"),105 "/../crates/jrsonnet-rowan-parser/src/generated/nodes.rs",106 )),107 &nodes,108 )?;109 Ok(())110}111112fn generate_syntax_kinds(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {113 let t_macros = kinds.tokens().filter_map(TokenKind::expand_t_macros);114 let token_kinds = kinds.tokens().map(TokenKind::expand_kind);115116 let keywords = kinds117 .tokens()118 .filter(|k| matches!(k, TokenKind::Keyword { .. }))119 .map(TokenKind::name)120 .map(|n| format_ident!("{n}"));121122 let nodes = kinds123 .nodes124 .iter()125 .map(|name| format_ident!("{}", name))126 .collect::<Vec<_>>();127128 let enums = grammar129 .enums130 .iter()131 .map(|e| format_ident!("{}", to_upper_snake_case(&e.name)))132 .chain(133 grammar134 .token_enums135 .iter()136 .map(|e| format_ident!("{}", to_upper_snake_case(&e.name))),137 );138139 let ast = quote! {140 #![allow(bad_style, missing_docs, unreachable_pub, clippy::manual_non_exhaustive, clippy::match_like_matches_macro)]141 use logos::Logos;142143 /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.144 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Logos)]145 #[repr(u16)]146 pub enum SyntaxKind {147 #[doc(hidden)]148 TOMBSTONE,149 #[doc(hidden)]150 EOF,151 #(#token_kinds,)*152 LEXING_ERROR,153 __LAST_TOKEN,154 #(#nodes,)*155 #[doc(hidden)]156 __LAST,157 }158 use self::SyntaxKind::*;159160 impl SyntaxKind {161 pub fn is_keyword(self) -> bool {162 match self {163 #(#keywords)|* => true,164 _ => false,165 }166 }167 pub fn is_enum(self) -> bool {168 match self {169 #(#enums)|* => true,170 _ => false,171 }172 }173174 pub fn from_raw(r: u16) -> Self {175 assert!(r < Self::__LAST as u16);176 unsafe { std::mem::transmute(r) }177 }178 pub fn into_raw(self) -> u16 {179 self as u16180 }181 }182183 #[macro_export]184 macro_rules! T {#(#t_macros);*}185 #[allow(unused_imports)]186 pub use T;187 };188189 reformat(&ast.to_string())190}191192fn generate_nodes(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {193 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar194 .nodes195 .iter()196 .map(|node| {197 let name = format_ident!("{}", node.name);198 let kind = format_ident!("{}", to_upper_snake_case(&node.name));199 let traits = node.traits.iter().map(|trait_name| {200 let trait_name = format_ident!("{}", trait_name);201 quote!(impl ast::#trait_name for #name {})202 });203204 let methods = node.fields.iter().map(|field| {205 let method_name = field.method_name(kinds);206 let ty = field.ty();207208 if field.is_many() {209 quote! {210 pub fn #method_name(&self) -> AstChildren<#ty> {211 support::children(&self.syntax)212 }213 }214 } else if let Some(token_kind) = field.token_kind(kinds) {215 quote! {216 pub fn #method_name(&self) -> Option<#ty> {217 support::token(&self.syntax, #token_kind)218 }219 }220 } else if field.is_token_enum(grammar) {221 quote! {222 pub fn #method_name(&self) -> Option<#ty> {223 support::token_child(&self.syntax)224 }225 }226 } else {227 quote! {228 pub fn #method_name(&self) -> Option<#ty> {229 support::child(&self.syntax)230 }231 }232 }233 });234 (235 quote! {236 #[pretty_doc_comment_placeholder_workaround]237 #[derive(Debug, Clone, PartialEq, Eq, Hash)]238 pub struct #name {239 pub(crate) syntax: SyntaxNode,240 }241242 #(#traits)*243244 impl #name {245 #(#methods)*246 }247 },248 quote! {249 impl AstNode for #name {250 fn can_cast(kind: SyntaxKind) -> bool {251 kind == #kind252 }253 fn cast(syntax: SyntaxNode) -> Option<Self> {254 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }255 }256 fn syntax(&self) -> &SyntaxNode { &self.syntax }257 }258 },259 )260 })261 .unzip();262263 let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar264 .enums265 .iter()266 .map(|en| {267 let variants: Vec<_> = en268 .variants269 .iter()270 .map(|var| format_ident!("{}", var))271 .collect();272 let name = format_ident!("{}", en.name);273 let kinds: Vec<_> = variants274 .iter()275 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))276 .collect();277 let traits = en.traits.iter().map(|trait_name| {278 let trait_name = format_ident!("{}", trait_name);279 quote!(impl ast::#trait_name for #name {})280 });281282 let ast_node = quote! {283 impl AstNode for #name {284 fn can_cast(kind: SyntaxKind) -> bool {285 match kind {286 #(#kinds)|* => true,287 _ => false,288 }289 }290 fn cast(syntax: SyntaxNode) -> Option<Self> {291 let res = match syntax.kind() {292 #(293 #kinds => #name::#variants(#variants { syntax }),294 )*295 _ => return None,296 };297 Some(res)298 }299 fn syntax(&self) -> &SyntaxNode {300 match self {301 #(302 #name::#variants(it) => &it.syntax,303 )*304 }305 }306 }307 };308309 (310 quote! {311 #[pretty_doc_comment_placeholder_workaround]312 #[derive(Debug, Clone, PartialEq, Eq, Hash)]313 pub enum #name {314 #(#variants(#variants),)*315 }316317 #(#traits)*318 },319 quote! {320 #(321 impl From<#variants> for #name {322 fn from(node: #variants) -> #name {323 #name::#variants(node)324 }325 }326 )*327 #ast_node328 },329 )330 })331 .unzip();332333 let (token_enum_defs, token_enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar334 .token_enums335 .iter()336 .map(|en| {337 let variants: Vec<_> = en338 .variants339 .iter()340 .map(|token| {341 format_ident!(342 "{}",343 to_pascal_case(kinds.token(token).expect("token exists").name())344 )345 })346 .collect();347 let name = format_ident!("{}", en.name);348 let kind_name = format_ident!("{}Kind", en.name);349 let kinds: Vec<_> = variants350 .iter()351 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))352 .collect();353354 let ast_node = quote! {355 impl AstToken for #name {356 fn can_cast(kind: SyntaxKind) -> bool {357 #kind_name::can_cast(kind)358 }359 fn cast(syntax: SyntaxToken) -> Option<Self> {360 let kind = #kind_name::cast(syntax.kind())?;361 Some(#name { syntax, kind })362 }363 fn syntax(&self) -> &SyntaxToken {364 &self.syntax365 }366 }367368 impl #kind_name {369 fn can_cast(kind: SyntaxKind) -> bool {370 match kind {371 #(#kinds)|* => true,372 _ => false,373 }374 }375 pub fn cast(kind: SyntaxKind) -> Option<Self> {376 let res = match kind {377 #(#kinds => Self::#variants,)*378 _ => return None,379 };380 Some(res)381 }382 }383 };384385 (386 quote! {387 #[pretty_doc_comment_placeholder_workaround]388 #[derive(Debug, Clone, PartialEq, Eq, Hash)]389 pub struct #name { syntax: SyntaxToken, kind: #kind_name }390391 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]392 pub enum #kind_name {393 #(#variants,)*394 }395 },396 quote! {397 #ast_node398399 impl #name {400 pub fn kind(&self) -> #kind_name {401 self.kind402 }403 }404405 impl std::fmt::Display for #name {406 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {407 std::fmt::Display::fmt(self.syntax(), f)408 }409 }410 },411 )412 })413 .unzip();414415 let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar416 .nodes417 .iter()418 .flat_map(|node| node.traits.iter().map(move |t| (t, node)))419 .into_group_map()420 .into_iter()421 .sorted_by_key(|(k, _)| *k)422 .map(|(trait_name, nodes)| {423 let name = format_ident!("Any{}", trait_name);424 let trait_name = format_ident!("{}", trait_name);425 let kinds: Vec<_> = nodes426 .iter()427 .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))428 .collect();429430 (431 quote! {432 #[pretty_doc_comment_placeholder_workaround]433 #[derive(Debug, Clone, PartialEq, Eq, Hash)]434 pub struct #name {435 pub(crate) syntax: SyntaxNode,436 }437 impl ast::#trait_name for #name {}438 },439 quote! {440 impl #name {441 #[inline]442 pub fn new<T: ast::#trait_name>(node: T) -> #name {443 #name {444 syntax: node.syntax().clone()445 }446 }447 }448 impl AstNode for #name {449 fn can_cast(kind: SyntaxKind) -> bool {450 match kind {451 #(#kinds)|* => true,452 _ => false,453 }454 }455 fn cast(syntax: SyntaxNode) -> Option<Self> {456 Self::can_cast(syntax.kind()).then(|| #name { syntax })457 }458 fn syntax(&self) -> &SyntaxNode {459 &self.syntax460 }461 }462 },463 )464 })465 .unzip();466467 let enum_names = grammar.enums.iter().map(|it| &it.name);468 let node_names = grammar.nodes.iter().map(|it| &it.name);469470 let display_impls = enum_names471 .chain(node_names.clone())472 .map(|it| format_ident!("{}", it))473 .map(|name| {474 quote! {475 impl std::fmt::Display for #name {476 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {477 std::fmt::Display::fmt(self.syntax(), f)478 }479 }480 }481 });482483 let ast = quote! {484 #![allow(non_snake_case, clippy::match_like_matches_macro)]485486 use crate::{487 SyntaxNode, SyntaxToken, SyntaxKind::{self, *},488 ast::{AstNode, AstToken, AstChildren, support},489 T,490 };491492 #(#node_defs)*493 #(#enum_defs)*494 #(#token_enum_defs)*495 #(#any_node_defs)*496 #(#node_boilerplate_impls)*497 #(#enum_boilerplate_impls)*498 #(#token_enum_boilerplate_impls)*499 #(#any_node_boilerplate_impls)*500 #(#display_impls)*501 };502503 let ast = ast.to_string().replace("T ! [", "T![");504505 let mut res = String::with_capacity(ast.len() * 2);506507 let mut docs = grammar508 .nodes509 .iter()510 .map(|it| &it.doc)511 .chain(grammar.enums.iter().map(|it| &it.doc));512513 for chunk in ast.split("# [pretty_doc_comment_placeholder_workaround] ") {514 res.push_str(chunk);515 if let Some(doc) = docs.next() {516 write_doc_comment(doc, &mut res);517 }518 }519520 let res = reformat(&res)?;521 Ok(res.replace("#[derive", "\n#[derive"))522}523524fn write_doc_comment(contents: &[String], dest: &mut String) {525 use std::fmt::Write;526 for line in contents {527 writeln!(dest, "///{}", line).unwrap();528 }529}530531pub fn escape_token_macro(token: &str) -> TokenStream {532 if "{}[]()$".contains(token) {533 let c = token.chars().next().unwrap();534 quote! { #c }535 } else if token.contains('$') {536 quote! { #token }537 } else {538 let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));539 quote! { #(#cs)* }540 }541}1use std::path::PathBuf;23use anyhow::Result;4use ast::{lower, AstSrc};5use itertools::Itertools;6use kinds::{KindsSrc, TokenKind};7use proc_macro2::{Punct, Spacing, TokenStream};8use quote::{format_ident, quote};9use ungrammar::Grammar;10use util::{ensure_file_contents, reformat, to_pascal_case, to_upper_snake_case};1112mod ast;13mod kinds;14mod util;1516enum SpecialName {17 Literal,18 Meta,19 Error,20}21fn classify_special(name: &str) -> Option<(SpecialName, &str)> {22 let name = name.strip_suffix('!')?;23 Some(if let Some(name) = name.strip_prefix("LIT_") {24 (SpecialName::Literal, name)25 } else if let Some(name) = name.strip_prefix("META_") {26 (SpecialName::Meta, name)27 } else if let Some(name) = name.strip_prefix("ERROR_") {28 (SpecialName::Error, name)29 } else {30 return None;31 })32}3334pub fn generate_ungrammar() -> Result<()> {35 let grammar: Grammar = include_str!(concat!(36 env!("CARGO_MANIFEST_DIR"),37 "/../crates/jrsonnet-rowan-parser/jsonnet.ungram"38 ))39 .parse()?;4041 let mut kinds = kinds::jsonnet_kinds();42 let ast = lower(&kinds, &grammar);4344 for token in grammar.tokens() {45 let token = &grammar[token];46 let token = &token.name.clone();47 if !kinds.is_token(token) {48 if let Some((special, name)) = classify_special(token) {49 match special {50 SpecialName::Literal => panic!("literal is not defined: {name}"),51 SpecialName::Meta => {52 eprintln!("implicit meta: {name}");53 kinds.define_token(TokenKind::Meta {54 grammar_name: token.to_owned(),55 name: format!("META_{name}"),56 });57 }58 SpecialName::Error => {59 eprintln!("implicit error: {name}");60 kinds.define_token(TokenKind::Error {61 grammar_name: token.to_owned(),62 name: format!("ERROR_{name}"),63 regex: None,64 priority: None,65 is_lexer_error: true,66 });67 }68 };69 continue;70 };71 let name = to_upper_snake_case(token);72 eprintln!("implicit kw: {token}");73 kinds.define_token(TokenKind::Keyword {74 code: token.to_owned(),75 name: format!("{name}_KW"),76 });77 }78 }79 for node in &ast.nodes {80 let name = to_upper_snake_case(&node.name);81 kinds.define_node(&name);82 }83 for enum_ in &ast.enums {84 let name = to_upper_snake_case(&enum_.name);85 kinds.define_node(&name);86 }87 for token_enum in &ast.token_enums {88 let name = to_upper_snake_case(&token_enum.name);89 kinds.define_node(&name);90 }9192 let syntax_kinds = generate_syntax_kinds(&kinds, &ast)?;9394 let nodes = generate_nodes(&kinds, &ast)?;95 ensure_file_contents(96 &PathBuf::from(concat!(97 env!("CARGO_MANIFEST_DIR"),98 "/../crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs",99 )),100 &syntax_kinds,101 );102 ensure_file_contents(103 &PathBuf::from(concat!(104 env!("CARGO_MANIFEST_DIR"),105 "/../crates/jrsonnet-rowan-parser/src/generated/nodes.rs",106 )),107 &nodes,108 );109 Ok(())110}111112fn generate_syntax_kinds(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {113 let t_macros = kinds.tokens().filter_map(TokenKind::expand_t_macros);114 let token_kinds = kinds.tokens().map(TokenKind::expand_kind);115116 let keywords = kinds117 .tokens()118 .filter(|k| matches!(k, TokenKind::Keyword { .. }))119 .map(TokenKind::name)120 .map(|n| format_ident!("{n}"));121122 let nodes = kinds123 .nodes124 .iter()125 .map(|name| format_ident!("{}", name))126 .collect::<Vec<_>>();127128 let enums = grammar129 .enums130 .iter()131 .map(|e| format_ident!("{}", to_upper_snake_case(&e.name)))132 .chain(133 grammar134 .token_enums135 .iter()136 .map(|e| format_ident!("{}", to_upper_snake_case(&e.name))),137 );138139 let ast = quote! {140 #![allow(bad_style, missing_docs, unreachable_pub, clippy::manual_non_exhaustive, clippy::match_like_matches_macro)]141 use logos::Logos;142143 /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.144 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Logos)]145 #[repr(u16)]146 pub enum SyntaxKind {147 #[doc(hidden)]148 TOMBSTONE,149 #[doc(hidden)]150 EOF,151 #(#token_kinds,)*152 LEXING_ERROR,153 __LAST_TOKEN,154 #(#nodes,)*155 #[doc(hidden)]156 __LAST,157 }158 use self::SyntaxKind::*;159160 impl SyntaxKind {161 pub fn is_keyword(self) -> bool {162 match self {163 #(#keywords)|* => true,164 _ => false,165 }166 }167 pub fn is_enum(self) -> bool {168 match self {169 #(#enums)|* => true,170 _ => false,171 }172 }173174 pub fn from_raw(r: u16) -> Self {175 assert!(r < Self::__LAST as u16);176 unsafe { std::mem::transmute(r) }177 }178 pub fn into_raw(self) -> u16 {179 self as u16180 }181 }182183 #[macro_export]184 macro_rules! T {#(#t_macros);*}185 #[allow(unused_imports)]186 pub use T;187 };188189 reformat(&ast.to_string())190}191192#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]193fn generate_nodes(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {194 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar195 .nodes196 .iter()197 .map(|node| {198 let name = format_ident!("{}", node.name);199 let kind = format_ident!("{}", to_upper_snake_case(&node.name));200 let traits = node.traits.iter().map(|trait_name| {201 let trait_name = format_ident!("{}", trait_name);202 quote!(impl ast::#trait_name for #name {})203 });204205 let methods = node.fields.iter().map(|field| {206 let method_name = field.method_name(kinds);207 let ty = field.ty();208209 if field.is_many() {210 quote! {211 pub fn #method_name(&self) -> AstChildren<#ty> {212 support::children(&self.syntax)213 }214 }215 } else if let Some(token_kind) = field.token_kind(kinds) {216 quote! {217 pub fn #method_name(&self) -> Option<#ty> {218 support::token(&self.syntax, #token_kind)219 }220 }221 } else if field.is_token_enum(grammar) {222 quote! {223 pub fn #method_name(&self) -> Option<#ty> {224 support::token_child(&self.syntax)225 }226 }227 } else {228 quote! {229 pub fn #method_name(&self) -> Option<#ty> {230 support::child(&self.syntax)231 }232 }233 }234 });235 (236 quote! {237 #[pretty_doc_comment_placeholder_workaround]238 #[derive(Debug, Clone, PartialEq, Eq, Hash)]239 pub struct #name {240 pub(crate) syntax: SyntaxNode,241 }242243 #(#traits)*244245 impl #name {246 #(#methods)*247 }248 },249 quote! {250 impl AstNode for #name {251 fn can_cast(kind: SyntaxKind) -> bool {252 kind == #kind253 }254 fn cast(syntax: SyntaxNode) -> Option<Self> {255 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }256 }257 fn syntax(&self) -> &SyntaxNode { &self.syntax }258 }259 },260 )261 })262 .unzip();263264 let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar265 .enums266 .iter()267 .map(|en| {268 let variants: Vec<_> = en269 .variants270 .iter()271 .map(|var| format_ident!("{}", var))272 .collect();273 let name = format_ident!("{}", en.name);274 let kinds: Vec<_> = variants275 .iter()276 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))277 .collect();278 let traits = en.traits.iter().map(|trait_name| {279 let trait_name = format_ident!("{}", trait_name);280 quote!(impl ast::#trait_name for #name {})281 });282283 let ast_node = quote! {284 impl AstNode for #name {285 fn can_cast(kind: SyntaxKind) -> bool {286 match kind {287 #(#kinds)|* => true,288 _ => false,289 }290 }291 fn cast(syntax: SyntaxNode) -> Option<Self> {292 let res = match syntax.kind() {293 #(294 #kinds => #name::#variants(#variants { syntax }),295 )*296 _ => return None,297 };298 Some(res)299 }300 fn syntax(&self) -> &SyntaxNode {301 match self {302 #(303 #name::#variants(it) => &it.syntax,304 )*305 }306 }307 }308 };309310 (311 quote! {312 #[pretty_doc_comment_placeholder_workaround]313 #[derive(Debug, Clone, PartialEq, Eq, Hash)]314 pub enum #name {315 #(#variants(#variants),)*316 }317318 #(#traits)*319 },320 quote! {321 #(322 impl From<#variants> for #name {323 fn from(node: #variants) -> #name {324 #name::#variants(node)325 }326 }327 )*328 #ast_node329 },330 )331 })332 .unzip();333334 let (token_enum_defs, token_enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar335 .token_enums336 .iter()337 .map(|en| {338 let variants: Vec<_> = en339 .variants340 .iter()341 .map(|token| {342 format_ident!(343 "{}",344 to_pascal_case(kinds.token(token).expect("token exists").name())345 )346 })347 .collect();348 let name = format_ident!("{}", en.name);349 let kind_name = format_ident!("{}Kind", en.name);350 let kinds: Vec<_> = variants351 .iter()352 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))353 .collect();354355 let ast_node = quote! {356 impl AstToken for #name {357 fn can_cast(kind: SyntaxKind) -> bool {358 #kind_name::can_cast(kind)359 }360 fn cast(syntax: SyntaxToken) -> Option<Self> {361 let kind = #kind_name::cast(syntax.kind())?;362 Some(#name { syntax, kind })363 }364 fn syntax(&self) -> &SyntaxToken {365 &self.syntax366 }367 }368369 impl #kind_name {370 fn can_cast(kind: SyntaxKind) -> bool {371 match kind {372 #(#kinds)|* => true,373 _ => false,374 }375 }376 pub fn cast(kind: SyntaxKind) -> Option<Self> {377 let res = match kind {378 #(#kinds => Self::#variants,)*379 _ => return None,380 };381 Some(res)382 }383 }384 };385386 (387 quote! {388 #[pretty_doc_comment_placeholder_workaround]389 #[derive(Debug, Clone, PartialEq, Eq, Hash)]390 pub struct #name { syntax: SyntaxToken, kind: #kind_name }391392 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]393 pub enum #kind_name {394 #(#variants,)*395 }396 },397 quote! {398 #ast_node399400 impl #name {401 pub fn kind(&self) -> #kind_name {402 self.kind403 }404 }405406 impl std::fmt::Display for #name {407 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {408 std::fmt::Display::fmt(self.syntax(), f)409 }410 }411 },412 )413 })414 .unzip();415416 let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar417 .nodes418 .iter()419 .flat_map(|node| node.traits.iter().map(move |t| (t, node)))420 .into_group_map()421 .into_iter()422 .sorted_by_key(|(k, _)| *k)423 .map(|(trait_name, nodes)| {424 let name = format_ident!("Any{}", trait_name);425 let trait_name = format_ident!("{}", trait_name);426 let kinds: Vec<_> = nodes427 .iter()428 .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))429 .collect();430431 (432 quote! {433 #[pretty_doc_comment_placeholder_workaround]434 #[derive(Debug, Clone, PartialEq, Eq, Hash)]435 pub struct #name {436 pub(crate) syntax: SyntaxNode,437 }438 impl ast::#trait_name for #name {}439 },440 quote! {441 impl #name {442 #[inline]443 pub fn new<T: ast::#trait_name>(node: T) -> #name {444 #name {445 syntax: node.syntax().clone()446 }447 }448 }449 impl AstNode for #name {450 fn can_cast(kind: SyntaxKind) -> bool {451 match kind {452 #(#kinds)|* => true,453 _ => false,454 }455 }456 fn cast(syntax: SyntaxNode) -> Option<Self> {457 Self::can_cast(syntax.kind()).then(|| #name { syntax })458 }459 fn syntax(&self) -> &SyntaxNode {460 &self.syntax461 }462 }463 },464 )465 })466 .unzip();467468 let enum_names = grammar.enums.iter().map(|it| &it.name);469 let node_names = grammar.nodes.iter().map(|it| &it.name);470471 let display_impls = enum_names472 .chain(node_names.clone())473 .map(|it| format_ident!("{}", it))474 .map(|name| {475 quote! {476 impl std::fmt::Display for #name {477 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {478 std::fmt::Display::fmt(self.syntax(), f)479 }480 }481 }482 });483484 let ast = quote! {485 #![allow(non_snake_case, clippy::match_like_matches_macro)]486487 use crate::{488 SyntaxNode, SyntaxToken, SyntaxKind::{self, *},489 ast::{AstNode, AstToken, AstChildren, support},490 T,491 };492493 #(#node_defs)*494 #(#enum_defs)*495 #(#token_enum_defs)*496 #(#any_node_defs)*497 #(#node_boilerplate_impls)*498 #(#enum_boilerplate_impls)*499 #(#token_enum_boilerplate_impls)*500 #(#any_node_boilerplate_impls)*501 #(#display_impls)*502 };503504 let ast = ast.to_string().replace("T ! [", "T![");505506 let mut res = String::with_capacity(ast.len() * 2);507508 let mut docs = grammar509 .nodes510 .iter()511 .map(|it| &it.doc)512 .chain(grammar.enums.iter().map(|it| &it.doc));513514 for chunk in ast.split("# [pretty_doc_comment_placeholder_workaround] ") {515 res.push_str(chunk);516 if let Some(doc) = docs.next() {517 write_doc_comment(doc, &mut res);518 }519 }520521 let res = reformat(&res)?;522 Ok(res.replace("#[derive", "\n#[derive"))523}524525fn write_doc_comment(contents: &[String], dest: &mut String) {526 use std::fmt::Write;527 for line in contents {528 writeln!(dest, "///{line}").unwrap();529 }530}531532pub fn escape_token_macro(token: &str) -> TokenStream {533 if "{}[]()$".contains(token) {534 let c = token.chars().next().unwrap();535 quote! { #c }536 } else if token.contains('$') {537 quote! { #token }538 } else {539 let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));540 quote! { #(#cs)* }541 }542}xtask/src/sourcegen/util.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/util.rs
+++ b/xtask/src/sourcegen/util.rs
@@ -1,3 +1,5 @@
+// FIXME: Replace various helper here with inflector?
+
use std::{fs, path::Path};
use anyhow::Result;
@@ -5,11 +7,11 @@
/// Checks that the `file` has the specified `contents`. If that is not the
/// case, updates the file and then fails the test.
-pub fn ensure_file_contents(file: &Path, contents: &str) -> Result<()> {
+pub fn ensure_file_contents(file: &Path, contents: &str) {
if let Ok(old_contents) = fs::read_to_string(file) {
if normalize_newlines(&old_contents) == normalize_newlines(contents) {
// File is already up to date.
- return Ok(());
+ return;
}
}
@@ -18,7 +20,6 @@
let _ = fs::create_dir_all(parent);
}
fs::write(file, contents).unwrap();
- Ok(())
}
// Eww, someone configured git to use crlf?
@@ -26,8 +27,9 @@
s.replace("\r\n", "\n")
}
-pub(crate) fn pluralize(s: &str) -> String {
- format!("{}s", s)
+pub fn pluralize(s: &str) -> String {
+ // FIXME: Inflector?
+ format!("{s}s")
}
pub fn to_upper_snake_case(s: &str) -> String {
@@ -35,7 +37,7 @@
let mut prev = false;
for c in s.chars() {
if c.is_ascii_uppercase() && prev {
- buf.push('_')
+ buf.push('_');
}
prev = true;
@@ -48,7 +50,7 @@
let mut prev = false;
for c in s.chars() {
if c.is_ascii_uppercase() && prev {
- buf.push('_')
+ buf.push('_');
}
prev = true;