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.rsdiffbeforeafterboth1use std::{cell::Cell, fmt, rc::Rc};23use rowan::{GreenNode, TextRange};45use crate::{6 event::Event,7 marker::{CompletedMarker, Marker},8 nodes::{BinaryOperatorKind, Literal, Number, Text, UnaryOperatorKind},9 token_set::SyntaxKindSet,10 AstToken, SyntaxKind,11 SyntaxKind::*,12 SyntaxNode, T, TS,13};1415pub struct Parse {16 pub green_node: GreenNode,17 pub errors: Vec<LocatedSyntaxError>,18}1920pub struct Parser {21 // TODO: remove all trivia before feeding to parser?22 kinds: Vec<SyntaxKind>,23 pub offset: usize,24 pub events: Vec<Event>,25 pub entered: u32,26 pub hints: Vec<(u32, TextRange, String)>,27 pub last_error_token: usize,28 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,29 steps: Cell<u64>,30}3132#[derive(Clone, Debug)]33pub enum SyntaxError {34 Unexpected {35 expected: ExpectedSyntax,36 found: SyntaxKind,37 },38 Missing {39 expected: ExpectedSyntax,40 },41 Custom {42 error: String,43 },44 Hint {45 error: String,46 },47}4849#[derive(Debug)]50pub struct LocatedSyntaxError {51 pub error: SyntaxError,52 pub range: TextRange,53}5455impl Parser {56 pub fn new(kinds: Vec<SyntaxKind>) -> Self {57 Self {58 kinds,59 offset: 0,60 events: vec![],61 entered: 0,62 last_error_token: 0,63 hints: vec![],64 expected_syntax_tracking_state: Rc::new(Cell::new(ExpectedSyntax::Unnamed(TS![]))),65 steps: Cell::new(0),66 }67 }68 pub fn clear_outdated_hints(&mut self) {69 let amount = self70 .hints71 .iter()72 .rev()73 .take_while(|h| h.0 > self.entered)74 .count();75 self.hints.truncate(self.hints.len() - amount)76 }77 fn clear_expected_syntaxes(&mut self) {78 self.expected_syntax_tracking_state79 .set(ExpectedSyntax::Unnamed(TS![]));80 }81 pub fn start(&mut self) -> Marker {82 let start_event_idx = self.events.len();83 self.events.push(Event::Pending);84 self.entered += 1;85 Marker::new(start_event_idx)86 }87 // pub fn start_ranger(&mut self) -> Ranger {88 // let pos = self.offset;89 // Ranger { pos }90 // }91 pub fn parse(mut self) -> Vec<Event> {92 let m = self.start();93 expr(&mut self);94 if !self.at(EOF) {95 let m = self.start();96 while !self.at(EOF) {97 self.bump();98 }99 m.complete_error(&mut self, "unexpected tokens after end");100 }101 m.complete(&mut self, SOURCE_FILE);102103 self.events104 }105106 pub(crate) fn expect(&mut self, kind: SyntaxKind) {107 self.expect_with_recovery_set(kind, TS![])108 }109110 pub(crate) fn expect_with_recovery_set(111 &mut self,112 kind: SyntaxKind,113 recovery_set: SyntaxKindSet,114 ) {115 if self.at(kind) {116 if kind != EOF {117 self.bump();118 }119 } else {120 self.error_with_recovery_set(recovery_set);121 }122 }123124 // pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {125 // if self.at(kind) {126 // self.bump();127 // } else {128 // self.error_with_no_skip();129 // }130 // }131 pub fn error_with_no_skip(&mut self) -> CompletedMarker {132 self.error_with_recovery_set(SyntaxKindSet::ALL)133 }134135 pub fn error_with_recovery_set(&mut self, recovery_set: SyntaxKindSet) -> CompletedMarker {136 let expected = self.expected_syntax_tracking_state.get();137 self.expected_syntax_tracking_state138 .set(ExpectedSyntax::Unnamed(TS![]));139140 if self.at_end() || self.at_ts(recovery_set) {141 let m = self.start();142 return m.complete_missing(self, expected);143 }144145 let current_token = self.current();146147 self.last_error_token = self.offset;148149 let m = self.start();150 self.bump();151 let m = m.complete_unexpected(self, expected, current_token);152 self.clear_expected_syntaxes();153 m154 }155 fn bump_assert(&mut self, kind: SyntaxKind) {156 assert!(self.at(kind), "expected {:?}", kind);157 self.bump_remap(self.current());158 }159 fn bump(&mut self) {160 self.bump_remap(self.current());161 }162 fn bump_remap(&mut self, kind: SyntaxKind) {163 assert_ne!(self.offset, self.kinds.len(), "already at end");164 self.events.push(Event::Token { kind });165 self.offset += 1;166 self.clear_expected_syntaxes();167 }168 fn step(&self) {169 use std::fmt::Write;170 let steps = self.steps.get();171 if steps >= 15000000 {172 let mut out = "seems like parsing is stuck".to_owned();173 {174 let last = 20;175 write!(out, "\n\nLast {} events:", last).unwrap();176 for (i, event) in self177 .events178 .iter()179 .skip(self.events.len().saturating_sub(last))180 .enumerate()181 {182 write!(out, "\n{i}. {event:?}").unwrap();183 }184 }185 {186 let next = 20;187 write!(out, "\n\nNext {next} tokens:").unwrap();188 for (i, tok) in self.kinds.iter().skip(self.offset).take(next).enumerate() {189 write!(out, "\n{i}. {tok:?}").unwrap();190 }191 }192 panic!("{out}")193 }194 self.steps.set(steps + 1);195 }196 fn nth(&self, i: usize) -> SyntaxKind {197 self.step();198 let mut offset = self.offset;199 for _ in 0..i {200 offset += 1;201 }202 self.kinds.get(offset).copied().unwrap_or(EOF)203 }204 fn current(&self) -> SyntaxKind {205 self.nth(0)206 }207 #[must_use]208 pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {209 self.expected_syntax_tracking_state210 .set(ExpectedSyntax::Named(name));211212 ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))213 }214 pub fn at(&mut self, kind: SyntaxKind) -> bool {215 self.nth_at(0, kind)216 }217 pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {218 if n == 0 {219 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {220 let kinds = kinds.with(kind);221 self.expected_syntax_tracking_state222 .set(ExpectedSyntax::Unnamed(kinds))223 }224 }225 self.nth(n) == kind226 }227 pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {228 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {229 let kinds = kinds.union(set);230 self.expected_syntax_tracking_state231 .set(ExpectedSyntax::Unnamed(kinds))232 }233 set.contains(self.current())234 }235 pub fn at_end(&mut self) -> bool {236 self.at(EOF)237 }238}239pub(crate) struct ExpectedSyntaxGuard {240 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,241}242243impl ExpectedSyntaxGuard {244 fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>) -> Self {245 Self {246 expected_syntax_tracking_state,247 }248 }249}250251impl Drop for ExpectedSyntaxGuard {252 fn drop(&mut self) {253 self.expected_syntax_tracking_state254 .set(ExpectedSyntax::Unnamed(TS![]));255 }256}257258#[derive(Clone, Debug, Copy)]259pub enum ExpectedSyntax {260 Named(&'static str),261 Unnamed(SyntaxKindSet),262}263impl fmt::Display for ExpectedSyntax {264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {265 match self {266 ExpectedSyntax::Named(name) => write!(f, "{name}"),267 ExpectedSyntax::Unnamed(set) => write!(f, "{set}"),268 }269 }270}271272fn expr(p: &mut Parser) -> CompletedMarker {273 let m = p.start();274 while p.at(T![local]) || p.at(T![assert]) {275 let m = p.start();276277 if p.at(T![local]) {278 p.bump();279 loop {280 if p.at(T![;]) {281 p.bump();282 break;283 }284 bind(p);285286 if p.at(T![,]) {287 p.bump();288 continue;289 }290 p.expect(T![;]);291 break;292 }293 m.complete(p, STMT_LOCAL);294 } else {295 assertion(p);296 p.expect(T![;]);297 m.complete(p, STMT_ASSERT);298 }299 }300 match expr_binding_power(p, 0) {301 Ok(m) => m,302 Err(m) => m,303 };304 m.complete(p, EXPR)305}306fn expr_binding_power(307 p: &mut Parser,308 minimum_binding_power: u8,309) -> Result<CompletedMarker, CompletedMarker> {310 let mut lhs = lhs(p)?;311312 while let Some(op) = BinaryOperatorKind::cast(p.current())313 .or_else(|| p.at(T!['{']).then_some(BinaryOperatorKind::MetaObjectApply))314 {315 let (left_binding_power, right_binding_power) = op.binding_power();316 if left_binding_power < minimum_binding_power {317 break;318 }319320 // Object apply is not a real operator, we dont have something to bump321 if op != BinaryOperatorKind::MetaObjectApply {322 p.bump();323 }324325 let m = lhs.wrap(p, EXPR).precede(p);326 let parsed_rhs = expr_binding_power(p, right_binding_power)327 .map(|v| v.precede(p).complete(p, EXPR))328 .is_ok();329 lhs = m.complete(330 p,331 if op == BinaryOperatorKind::MetaObjectApply {332 EXPR_OBJ_EXTEND333 } else {334 EXPR_BINARY335 },336 );337338 if !parsed_rhs {339 break;340 }341 }342 Ok(lhs)343}344345const COMPSPEC: SyntaxKindSet = TS![for if];346fn compspec(p: &mut Parser) -> CompletedMarker {347 assert!(p.at_ts(COMPSPEC));348 if p.at(T![for]) {349 let m = p.start();350 p.bump();351 destruct(p);352 p.expect(T![in]);353 expr(p);354 m.complete(p, FOR_SPEC)355 } else if p.at(T![if]) {356 let m = p.start();357 p.bump();358 expr(p);359 m.complete(p, IF_SPEC)360 } else {361 unreachable!()362 }363}364365fn comma(p: &mut Parser) -> bool {366 comma_with_alternatives(p, TS![])367}368fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {369 if p.at(T![,]) {370 p.bump();371 true372 } else if p.at_ts(set) {373 let _ex = p.expected_syntax_name("comma");374 p.expect_with_recovery_set(T![,], TS![]);375 true376 } else {377 false378 }379}380381fn field_name(p: &mut Parser) {382 let _e = p.expected_syntax_name("field name");383 let m = p.start();384 if p.at(T!['[']) {385 p.bump();386 expr(p);387 p.expect(T![']']);388 m.complete(p, FIELD_NAME_DYNAMIC);389 } else if p.at(IDENT) {390 name(p);391 m.complete(p, FIELD_NAME_FIXED);392 } else if Text::can_cast(p.current()) {393 text(p);394 m.complete(p, FIELD_NAME_FIXED);395 } else {396 m.forget(p);397 p.error_with_recovery_set(TS![; : :: ::: '(']);398 }399}400fn visibility(p: &mut Parser) {401 if p.at_ts(TS![: :: :::]) {402 p.bump()403 } else {404 p.error_with_recovery_set(TS![=]);405 }406}407fn assertion(p: &mut Parser) {408 let m = p.start();409 p.bump_assert(T![assert]);410 expr(p);411 if p.at(T![:]) {412 p.bump();413 expr(p);414 }415 m.complete(p, ASSERTION);416}417fn object(p: &mut Parser) -> CompletedMarker {418 let m_t = p.start();419 let m = p.start();420 p.bump_assert(T!['{']);421422 let mut elems = 0;423 let mut compspecs = Vec::new();424 let mut asserts = Vec::new();425 loop {426 if p.at(T!['}']) {427 p.bump();428 break;429 }430 if p.at_ts(TS![for]) {431 if elems == 0 {432 let m = p.start();433 m.complete_missing(p, ExpectedSyntax::Named("field definition"));434 }435 while p.at_ts(COMPSPEC) {436 compspecs.push(compspec(p));437 }438 if comma_with_alternatives(p, TS![;]) {439 continue;440 }441 p.expect(R_BRACE);442 break;443 }444 let m = p.start();445 if p.at(T![local]) {446 obj_local(p);447 m.complete(p, MEMBER_BIND_STMT);448 } else if p.at(T![assert]) {449 assertion(p);450 asserts.push(m.complete(p, MEMBER_ASSERT_STMT));451 } else {452 field_name(p);453 if p.at(T![+]) {454 p.bump();455 }456 let params = if p.at(T!['(']) {457 params_desc(p);458 visibility(p);459 expr(p);460 true461 } else if p.at_ts(TS![: :: :::]) && p.nth_at(1, T![function]) {462 visibility(p);463 p.bump_assert(T![function]);464 params_desc(p);465 expr(p);466 true467 } else {468 visibility(p);469 expr(p);470 false471 };472 elems += 1;473474 if params {475 m.complete(p, MEMBER_FIELD_METHOD)476 } else {477 m.complete(p, MEMBER_FIELD_NORMAL)478 };479 };480 while p.at_ts(COMPSPEC) {481 compspecs.push(compspec(p));482 }483 if comma_with_alternatives(p, TS![;]) {484 continue;485 }486 p.expect(R_BRACE);487 break;488 }489490 if elems > 1 && !compspecs.is_empty() {491 for errored in compspecs {492 errored.wrap_error(493 p,494 "compspec may only be used if there is only one object element",495 );496 }497 m.complete(p, OBJ_BODY_MEMBER_LIST);498 } else if !compspecs.is_empty() {499 for errored in asserts {500 errored.wrap_error(p, "asserts can't be used in object comprehensions");501 }502 m.complete(p, OBJ_BODY_COMP);503 } else {504 m.complete(p, OBJ_BODY_MEMBER_LIST);505 }506 m_t.complete(p, EXPR_OBJECT)507}508fn param(p: &mut Parser) {509 let m = p.start();510 destruct(p);511 if p.at(T![=]) {512 p.bump();513 expr(p);514 }515 m.complete(p, PARAM);516}517fn params_desc(p: &mut Parser) -> CompletedMarker {518 let m = p.start();519 p.bump_assert(T!['(']);520521 loop {522 if p.at(T![')']) {523 p.bump();524 break;525 }526 param(p);527 if comma(p) {528 continue;529 }530 p.expect(T![')']);531 break;532 }533534 m.complete(p, PARAMS_DESC)535}536fn args_desc(p: &mut Parser) {537 let m = p.start();538 p.bump_assert(T!['(']);539540 let started_named = Cell::new(false);541 let mut unnamed_after_named = Vec::new();542543 loop {544 if p.at(T![')']) {545 break;546 }547548 let m = p.start();549 if p.at(IDENT) && p.nth_at(1, T![=]) {550 name(p);551 p.bump();552 expr(p);553 m.complete(p, ARG);554 started_named.set(true);555 } else {556 expr(p);557 let arg = m.complete(p, ARG);558 if started_named.get() {559 unnamed_after_named.push(arg)560 }561 }562 if comma(p) {563 continue;564 }565 break;566 }567 p.expect(T![')']);568 if p.at(T![tailstrict]) {569 p.bump()570 }571572 for errored in unnamed_after_named {573 errored.wrap_error(p, "can't use positional arguments after named");574 }575576 m.complete(p, ARGS_DESC);577}578579fn array(p: &mut Parser) -> CompletedMarker {580 // Start the list node581 let m = p.start();582 p.bump_assert(T!['[']);583584 let mut compspecs = Vec::new();585 let mut elems = 0;586587 loop {588 if p.at(T![']']) {589 p.bump();590 break;591 }592 if elems != 0 && p.at_ts(TS![for]) {593 while p.at_ts(COMPSPEC) {594 compspecs.push(compspec(p));595 }596 if comma(p) {597 continue;598 }599 p.expect(T![']']);600 break;601 }602 expr(p);603 elems += 1;604 while p.at_ts(COMPSPEC) {605 compspecs.push(compspec(p));606 }607 if comma(p) {608 continue;609 }610 p.expect(T![']']);611 break;612 }613614 if elems > 1 && !compspecs.is_empty() {615 for spec in compspecs {616 spec.wrap_error(617 p,618 "compspec may only be used if there is only one array element",619 );620 }621622 m.complete(p, EXPR_ARRAY)623 } else if !compspecs.is_empty() {624 m.complete(p, EXPR_ARRAY_COMP)625 } else {626 m.complete(p, EXPR_ARRAY)627 }628}629/// Returns true if it was slice, false if just index630#[must_use]631fn slice_desc_or_index(p: &mut Parser) -> bool {632 let m = p.start();633 p.bump();634 // TODO: do not treat :, ::, ::: as full tokens?635 // Start636 if !p.at(T![:]) && !p.at(T![::]) {637 expr(p);638 }639 if p.at(T![:]) {640 p.bump();641 // End642 if !p.at(T![']']) {643 expr(p).wrap(p, SLICE_DESC_END);644 }645 if p.at(T![:]) {646 p.bump();647 // Step648 if !p.at(T![']']) {649 expr(p).wrap(p, SLICE_DESC_STEP);650 }651 }652 } else if p.at(T![::]) {653 p.bump();654 // End655 if !p.at(T![']']) {656 expr(p).wrap(p, SLICE_DESC_END);657 }658 } else {659 // It was not a slice660 p.expect(T![']']);661 m.forget(p);662 return false;663 }664 p.expect(T![']']);665 m.complete(p, SLICE_DESC);666 true667}668669fn suffix(p: &mut Parser) {670 loop {671 let start = p.start();672 let _marker: CompletedMarker = if p.at(T![?]) {673 p.bump();674 p.expect(T![.]);675 if p.at(IDENT) {676 name(p);677 start.complete(p, SUFFIX_INDEX)678 } else if p.at(T!['[']) {679 p.bump();680 expr(p);681 p.expect(T![']']);682 start.complete(p, SUFFIX_INDEX_EXPR)683 } else {684 start.complete_missing(p, ExpectedSyntax::Named("index"))685 }686 } else if p.at(T![.]) {687 p.bump();688 name(p);689 start.complete(p, SUFFIX_INDEX)690 } else if p.at(T!['[']) {691 if slice_desc_or_index(p) {692 start.complete(p, SUFFIX_SLICE)693 } else {694 start.complete(p, SUFFIX_INDEX_EXPR)695 }696 } else if p.at(T!['(']) {697 args_desc(p);698 start.complete(p, SUFFIX_APPLY)699 } else {700 start.forget(p);701 break;702 };703 }704}705706fn lhs(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {707 let lhs = lhs_basic(p)?;708709 suffix(p);710711 Ok(lhs)712}713fn name(p: &mut Parser) {714 let m = p.start();715 p.expect(IDENT);716 m.complete(p, NAME);717}718fn destruct_rest(p: &mut Parser) {719 let m = p.start();720 p.bump_assert(T![...]);721 if p.at(IDENT) {722 p.bump()723 }724 m.complete(p, DESTRUCT_REST);725}726fn destruct_object_field(p: &mut Parser) {727 let m = p.start();728 name(p);729 if p.at(T![:]) {730 p.bump();731 destruct(p);732 };733 if p.at(T![=]) {734 p.bump();735 expr(p);736 }737 m.complete(p, DESTRUCT_OBJECT_FIELD);738}739fn obj_local(p: &mut Parser) {740 let m = p.start();741 p.bump_assert(T![local]);742 bind(p);743 m.complete(p, OBJ_LOCAL);744}745fn destruct(p: &mut Parser) -> CompletedMarker {746 let m = p.start();747 let _ex = p.expected_syntax_name("destruction specifier");748 if p.at(T![?]) {749 p.bump();750 m.complete(p, DESTRUCT_SKIP)751 } else if p.at(T!['[']) {752 p.bump();753 // let mut had_rest = false;754 loop {755 if p.at(T![']']) {756 p.bump();757 break;758 } else if p.at(T![...]) {759 // let m_err = p.start_ranger();760 destruct_rest(p);761 // if had_rest {762 // p.custom_error(m_err.finish(p), "only one rest can be present in array");763 // }764 // had_rest = true;765 } else {766 destruct(p);767 }768 if p.at(T![,]) {769 p.bump();770 continue;771 }772 p.expect(T![']']);773 break;774 }775 m.complete(p, DESTRUCT_ARRAY)776 } else if p.at(T!['{']) {777 p.bump();778 let mut had_rest = false;779 loop {780 if p.at(T!['}']) {781 p.bump();782 break;783 } else if p.at(T![...]) {784 // let m_err = p.start_ranger();785 destruct_rest(p);786 // if had_rest {787 // p.custom_error(m_err.finish(p), "only one rest can be present in object");788 // }789 had_rest = true;790 } else {791 if had_rest {792 p.error_with_recovery_set(TS![]);793 }794 destruct_object_field(p);795 }796 if p.at(T![,]) {797 p.bump();798 continue;799 }800 p.expect(T!['}']);801 break;802 }803 m.complete(p, DESTRUCT_OBJECT)804 } else if p.at(IDENT) {805 name(p);806 m.complete(p, DESTRUCT_FULL)807 } else {808 m.forget(p);809 p.error_with_recovery_set(TS![; , '}', '(', :])810 }811}812fn bind(p: &mut Parser) {813 let m = p.start();814 if p.at(IDENT) && p.nth_at(1, T!['(']) {815 name(p);816 params_desc(p);817 p.expect(T![=]);818 expr(p);819 m.complete(p, BIND_FUNCTION)820 } else if p.at(IDENT) && p.nth_at(1, T![=]) && p.nth_at(2, T![function]) {821 name(p);822 p.expect(T![=]);823 p.expect(T![function]);824 params_desc(p);825 expr(p);826 m.complete(p, BIND_FUNCTION)827 } else {828 destruct(p);829 p.expect(T![=]);830 expr(p);831 m.complete(p, BIND_DESTRUCT)832 };833}834fn text(p: &mut Parser) {835 assert!(Text::can_cast(p.current()));836 p.bump();837}838fn number(p: &mut Parser) {839 assert!(Number::can_cast(p.current()));840 p.bump();841}842fn literal(p: &mut Parser) {843 assert!(Literal::can_cast(p.current()));844 p.bump();845}846fn lhs_basic(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {847 let _e = p.expected_syntax_name("expression");848 Ok(if Literal::can_cast(p.current()) {849 let m = p.start();850 literal(p);851 m.complete(p, EXPR_LITERAL)852 } else if Text::can_cast(p.current()) {853 let m = p.start();854 text(p);855 m.complete(p, EXPR_STRING)856 } else if Number::can_cast(p.current()) {857 let m = p.start();858 number(p);859 m.complete(p, EXPR_NUMBER)860 } else if p.at(IDENT) {861 let m = p.start();862 name(p);863 m.complete(p, EXPR_VAR)864 } else if p.at(T![if]) {865 let m = p.start();866 p.bump();867 expr(p);868 p.expect(T![then]);869 expr(p).wrap(p, TRUE_EXPR);870 if p.at(T![else]) {871 p.bump();872 expr(p).wrap(p, FALSE_EXPR);873 }874 m.complete(p, EXPR_IF_THEN_ELSE)875 } else if p.at(T!['[']) {876 array(p)877 } else if p.at(T!['{']) {878 object(p)879 } else if p.at(T![function]) {880 let m = p.start();881 p.bump();882 params_desc(p);883 expr(p);884 m.complete(p, EXPR_FUNCTION)885 } else if p.at(T![error]) {886 let m = p.start();887 p.bump();888 expr(p);889 m.complete(p, EXPR_ERROR)890 } else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {891 let m = p.start();892 p.bump();893 text(p);894 m.complete(p, EXPR_IMPORT)895 } else if let Some(op) = UnaryOperatorKind::cast(p.current()) {896 let ((), right_binding_power) = op.binding_power();897898 let m = p.start();899 p.bump();900 let _ = expr_binding_power(p, right_binding_power);901 m.complete(p, EXPR_UNARY)902 } else if p.at(T!['(']) {903 let m = p.start();904 p.bump();905 expr(p);906 p.expect(T![')']);907 m.complete(p, EXPR_PARENED)908 } else {909 return Err(p.error_with_no_skip());910 })911}912913impl Parse {914 pub fn syntax(&self) -> SyntaxNode {915 SyntaxNode::new_root(self.green_node.clone())916 }917}1use std::{cell::Cell, fmt, rc::Rc};23use rowan::{GreenNode, TextRange};45use crate::{6 event::Event,7 marker::{CompletedMarker, Marker},8 nodes::{BinaryOperatorKind, Literal, Number, Text, UnaryOperatorKind},9 token_set::SyntaxKindSet,10 AstToken, SyntaxKind,11 SyntaxKind::*,12 SyntaxNode, T, TS,13};1415pub struct Parse {16 pub green_node: GreenNode,17 pub errors: Vec<LocatedSyntaxError>,18}1920pub struct Parser {21 // TODO: remove all trivia before feeding to parser?22 kinds: Vec<SyntaxKind>,23 pub offset: usize,24 pub events: Vec<Event>,25 pub entered: u32,26 pub hints: Vec<(u32, TextRange, String)>,27 pub last_error_token: usize,28 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,29 steps: Cell<u64>,30}3132#[derive(Clone, Debug)]33pub enum SyntaxError {34 Unexpected {35 expected: ExpectedSyntax,36 found: SyntaxKind,37 },38 Missing {39 expected: ExpectedSyntax,40 },41 Custom {42 error: String,43 },44 Hint {45 error: String,46 },47}4849#[derive(Debug)]50pub struct LocatedSyntaxError {51 pub error: SyntaxError,52 pub range: TextRange,53}5455impl Parser {56 pub fn new(kinds: Vec<SyntaxKind>) -> Self {57 Self {58 kinds,59 offset: 0,60 events: vec![],61 entered: 0,62 last_error_token: 0,63 hints: vec![],64 expected_syntax_tracking_state: Rc::new(Cell::new(ExpectedSyntax::Unnamed(TS![]))),65 steps: Cell::new(0),66 }67 }68 pub fn clear_outdated_hints(&mut self) {69 let amount = self70 .hints71 .iter()72 .rev()73 .take_while(|h| h.0 > self.entered)74 .count();75 self.hints.truncate(self.hints.len() - amount);76 }77 fn clear_expected_syntaxes(&self) {78 self.expected_syntax_tracking_state79 .set(ExpectedSyntax::Unnamed(TS![]));80 }81 pub fn start(&mut self) -> Marker {82 let start_event_idx = self.events.len();83 self.events.push(Event::Pending);84 self.entered += 1;85 Marker::new(start_event_idx)86 }87 // pub fn start_ranger(&mut self) -> Ranger {88 // let pos = self.offset;89 // Ranger { pos }90 // }91 pub fn parse(mut self) -> Vec<Event> {92 let m = self.start();93 expr(&mut self);94 if !self.at(EOF) {95 let m = self.start();96 while !self.at(EOF) {97 self.bump();98 }99 m.complete_error(&mut self, "unexpected tokens after end");100 }101 m.complete(&mut self, SOURCE_FILE);102103 self.events104 }105106 pub(crate) fn expect(&mut self, kind: SyntaxKind) {107 self.expect_with_recovery_set(kind, TS![]);108 }109110 pub(crate) fn expect_with_recovery_set(111 &mut self,112 kind: SyntaxKind,113 recovery_set: SyntaxKindSet,114 ) {115 if self.at(kind) {116 if kind != EOF {117 self.bump();118 }119 } else {120 self.error_with_recovery_set(recovery_set);121 }122 }123124 // pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {125 // if self.at(kind) {126 // self.bump();127 // } else {128 // self.error_with_no_skip();129 // }130 // }131 pub fn error_with_no_skip(&mut self) -> CompletedMarker {132 self.error_with_recovery_set(SyntaxKindSet::ALL)133 }134135 pub fn error_with_recovery_set(&mut self, recovery_set: SyntaxKindSet) -> CompletedMarker {136 let expected = self.expected_syntax_tracking_state.get();137 self.expected_syntax_tracking_state138 .set(ExpectedSyntax::Unnamed(TS![]));139140 if self.at_end() || self.at_ts(recovery_set) {141 let m = self.start();142 return m.complete_missing(self, expected);143 }144145 let current_token = self.current();146147 self.last_error_token = self.offset;148149 let m = self.start();150 self.bump();151 let m = m.complete_unexpected(self, expected, current_token);152 self.clear_expected_syntaxes();153 m154 }155 fn bump_assert(&mut self, kind: SyntaxKind) {156 assert!(self.at(kind), "expected {kind:?}");157 self.bump_remap(self.current());158 }159 fn bump(&mut self) {160 self.bump_remap(self.current());161 }162 fn bump_remap(&mut self, kind: SyntaxKind) {163 assert_ne!(self.offset, self.kinds.len(), "already at end");164 self.events.push(Event::Token { kind });165 self.offset += 1;166 self.clear_expected_syntaxes();167 }168 fn step(&self) {169 use std::fmt::Write;170 let steps = self.steps.get();171 if steps >= 15_000_000 {172 let mut out = "seems like parsing is stuck".to_owned();173 {174 let last = 20;175 write!(out, "\n\nLast {last} events:").unwrap();176 for (i, event) in self177 .events178 .iter()179 .skip(self.events.len().saturating_sub(last))180 .enumerate()181 {182 write!(out, "\n{i}. {event:?}").unwrap();183 }184 }185 {186 let next = 20;187 write!(out, "\n\nNext {next} tokens:").unwrap();188 for (i, tok) in self.kinds.iter().skip(self.offset).take(next).enumerate() {189 write!(out, "\n{i}. {tok:?}").unwrap();190 }191 }192 panic!("{out}")193 }194 self.steps.set(steps + 1);195 }196 fn nth(&self, i: usize) -> SyntaxKind {197 self.step();198 let mut offset = self.offset;199 for _ in 0..i {200 offset += 1;201 }202 self.kinds.get(offset).copied().unwrap_or(EOF)203 }204 fn current(&self) -> SyntaxKind {205 self.nth(0)206 }207 #[must_use]208 pub(crate) fn expected_syntax_name(&self, name: &'static str) -> ExpectedSyntaxGuard {209 self.expected_syntax_tracking_state210 .set(ExpectedSyntax::Named(name));211212 ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))213 }214 pub fn at(&self, kind: SyntaxKind) -> bool {215 self.nth_at(0, kind)216 }217 pub fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {218 if n == 0 {219 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {220 let kinds = kinds.with(kind);221 self.expected_syntax_tracking_state222 .set(ExpectedSyntax::Unnamed(kinds));223 }224 }225 self.nth(n) == kind226 }227 pub fn at_ts(&self, set: SyntaxKindSet) -> bool {228 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {229 let kinds = kinds.union(set);230 self.expected_syntax_tracking_state231 .set(ExpectedSyntax::Unnamed(kinds));232 }233 set.contains(self.current())234 }235 pub fn at_end(&self) -> bool {236 self.at(EOF)237 }238}239pub struct ExpectedSyntaxGuard {240 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,241}242243impl ExpectedSyntaxGuard {244 fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>) -> Self {245 Self {246 expected_syntax_tracking_state,247 }248 }249}250251impl Drop for ExpectedSyntaxGuard {252 fn drop(&mut self) {253 self.expected_syntax_tracking_state254 .set(ExpectedSyntax::Unnamed(TS![]));255 }256}257258#[derive(Clone, Debug, Copy)]259pub enum ExpectedSyntax {260 Named(&'static str),261 Unnamed(SyntaxKindSet),262}263impl fmt::Display for ExpectedSyntax {264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {265 match self {266 Self::Named(name) => write!(f, "{name}"),267 Self::Unnamed(set) => write!(f, "{set}"),268 }269 }270}271272fn expr(p: &mut Parser) -> CompletedMarker {273 let m = p.start();274 while p.at(T![local]) || p.at(T![assert]) {275 let m = p.start();276277 if p.at(T![local]) {278 p.bump();279 loop {280 if p.at(T![;]) {281 p.bump();282 break;283 }284 bind(p);285286 if p.at(T![,]) {287 p.bump();288 continue;289 }290 p.expect(T![;]);291 break;292 }293 m.complete(p, STMT_LOCAL);294 } else {295 assertion(p);296 p.expect(T![;]);297 m.complete(p, STMT_ASSERT);298 }299 }300 match expr_binding_power(p, 0) {301 Ok(m) | Err(m) => m,302 };303 m.complete(p, EXPR)304}305fn expr_binding_power(306 p: &mut Parser,307 minimum_binding_power: u8,308) -> Result<CompletedMarker, CompletedMarker> {309 let mut lhs = lhs(p)?;310311 while let Some(op) = BinaryOperatorKind::cast(p.current())312 .or_else(|| p.at(T!['{']).then_some(BinaryOperatorKind::MetaObjectApply))313 {314 let (left_binding_power, right_binding_power) = op.binding_power();315 if left_binding_power < minimum_binding_power {316 break;317 }318319 // Object apply is not a real operator, we dont have something to bump320 if op != BinaryOperatorKind::MetaObjectApply {321 p.bump();322 }323324 let m = lhs.wrap(p, EXPR).precede(p);325 let parsed_rhs = expr_binding_power(p, right_binding_power)326 .map(|v| v.precede(p).complete(p, EXPR))327 .is_ok();328 lhs = m.complete(329 p,330 if op == BinaryOperatorKind::MetaObjectApply {331 EXPR_OBJ_EXTEND332 } else {333 EXPR_BINARY334 },335 );336337 if !parsed_rhs {338 break;339 }340 }341 Ok(lhs)342}343344const COMPSPEC: SyntaxKindSet = TS![for if];345fn compspec(p: &mut Parser) -> CompletedMarker {346 assert!(p.at_ts(COMPSPEC));347 if p.at(T![for]) {348 let m = p.start();349 p.bump();350 destruct(p);351 p.expect(T![in]);352 expr(p);353 m.complete(p, FOR_SPEC)354 } else if p.at(T![if]) {355 let m = p.start();356 p.bump();357 expr(p);358 m.complete(p, IF_SPEC)359 } else {360 unreachable!()361 }362}363364fn comma(p: &mut Parser) -> bool {365 comma_with_alternatives(p, TS![])366}367fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {368 if p.at(T![,]) {369 p.bump();370 true371 } else if p.at_ts(set) {372 let _ex = p.expected_syntax_name("comma");373 p.expect_with_recovery_set(T![,], TS![]);374 true375 } else {376 false377 }378}379380fn field_name(p: &mut Parser) {381 let _e = p.expected_syntax_name("field name");382 let m = p.start();383 if p.at(T!['[']) {384 p.bump();385 expr(p);386 p.expect(T![']']);387 m.complete(p, FIELD_NAME_DYNAMIC);388 } else if p.at(IDENT) {389 name(p);390 m.complete(p, FIELD_NAME_FIXED);391 } else if Text::can_cast(p.current()) {392 text(p);393 m.complete(p, FIELD_NAME_FIXED);394 } else {395 m.forget(p);396 p.error_with_recovery_set(TS![; : :: ::: '(']);397 }398}399fn visibility(p: &mut Parser) {400 if p.at_ts(TS![: :: :::]) {401 p.bump();402 } else {403 p.error_with_recovery_set(TS![=]);404 }405}406fn assertion(p: &mut Parser) {407 let m = p.start();408 p.bump_assert(T![assert]);409 expr(p);410 if p.at(T![:]) {411 p.bump();412 expr(p);413 }414 m.complete(p, ASSERTION);415}416fn object(p: &mut Parser) -> CompletedMarker {417 let m_t = p.start();418 let m = p.start();419 p.bump_assert(T!['{']);420421 let mut elems = 0;422 let mut compspecs = Vec::new();423 let mut asserts = Vec::new();424 loop {425 if p.at(T!['}']) {426 p.bump();427 break;428 }429 if p.at_ts(TS![for]) {430 if elems == 0 {431 let m = p.start();432 m.complete_missing(p, ExpectedSyntax::Named("field definition"));433 }434 while p.at_ts(COMPSPEC) {435 compspecs.push(compspec(p));436 }437 if comma_with_alternatives(p, TS![;]) {438 continue;439 }440 p.expect(R_BRACE);441 break;442 }443 let m = p.start();444 if p.at(T![local]) {445 obj_local(p);446 m.complete(p, MEMBER_BIND_STMT);447 } else if p.at(T![assert]) {448 assertion(p);449 asserts.push(m.complete(p, MEMBER_ASSERT_STMT));450 } else {451 field_name(p);452 if p.at(T![+]) {453 p.bump();454 }455 let params = if p.at(T!['(']) {456 params_desc(p);457 visibility(p);458 expr(p);459 true460 } else if p.at_ts(TS![: :: :::]) && p.nth_at(1, T![function]) {461 visibility(p);462 p.bump_assert(T![function]);463 params_desc(p);464 expr(p);465 true466 } else {467 visibility(p);468 expr(p);469 false470 };471 elems += 1;472473 if params {474 m.complete(p, MEMBER_FIELD_METHOD)475 } else {476 m.complete(p, MEMBER_FIELD_NORMAL)477 };478 };479 while p.at_ts(COMPSPEC) {480 compspecs.push(compspec(p));481 }482 if comma_with_alternatives(p, TS![;]) {483 continue;484 }485 p.expect(R_BRACE);486 break;487 }488489 if elems > 1 && !compspecs.is_empty() {490 for errored in compspecs {491 errored.wrap_error(492 p,493 "compspec may only be used if there is only one object element",494 );495 }496 m.complete(p, OBJ_BODY_MEMBER_LIST);497 } else if !compspecs.is_empty() {498 for errored in asserts {499 errored.wrap_error(p, "asserts can't be used in object comprehensions");500 }501 m.complete(p, OBJ_BODY_COMP);502 } else {503 m.complete(p, OBJ_BODY_MEMBER_LIST);504 }505 m_t.complete(p, EXPR_OBJECT)506}507fn param(p: &mut Parser) {508 let m = p.start();509 destruct(p);510 if p.at(T![=]) {511 p.bump();512 expr(p);513 }514 m.complete(p, PARAM);515}516fn params_desc(p: &mut Parser) -> CompletedMarker {517 let m = p.start();518 p.bump_assert(T!['(']);519520 loop {521 if p.at(T![')']) {522 p.bump();523 break;524 }525 param(p);526 if comma(p) {527 continue;528 }529 p.expect(T![')']);530 break;531 }532533 m.complete(p, PARAMS_DESC)534}535fn args_desc(p: &mut Parser) {536 let m = p.start();537 p.bump_assert(T!['(']);538539 let started_named = Cell::new(false);540 let mut unnamed_after_named = Vec::new();541542 loop {543 if p.at(T![')']) {544 break;545 }546547 let m = p.start();548 if p.at(IDENT) && p.nth_at(1, T![=]) {549 name(p);550 p.bump();551 expr(p);552 m.complete(p, ARG);553 started_named.set(true);554 } else {555 expr(p);556 let arg = m.complete(p, ARG);557 if started_named.get() {558 unnamed_after_named.push(arg);559 }560 }561 if comma(p) {562 continue;563 }564 break;565 }566 p.expect(T![')']);567 if p.at(T![tailstrict]) {568 p.bump();569 }570571 for errored in unnamed_after_named {572 errored.wrap_error(p, "can't use positional arguments after named");573 }574575 m.complete(p, ARGS_DESC);576}577578fn array(p: &mut Parser) -> CompletedMarker {579 // Start the list node580 let m = p.start();581 p.bump_assert(T!['[']);582583 let mut compspecs = Vec::new();584 let mut elems = 0;585586 loop {587 if p.at(T![']']) {588 p.bump();589 break;590 }591 if elems != 0 && p.at_ts(TS![for]) {592 while p.at_ts(COMPSPEC) {593 compspecs.push(compspec(p));594 }595 if comma(p) {596 continue;597 }598 p.expect(T![']']);599 break;600 }601 expr(p);602 elems += 1;603 while p.at_ts(COMPSPEC) {604 compspecs.push(compspec(p));605 }606 if comma(p) {607 continue;608 }609 p.expect(T![']']);610 break;611 }612613 if elems > 1 && !compspecs.is_empty() {614 for spec in compspecs {615 spec.wrap_error(616 p,617 "compspec may only be used if there is only one array element",618 );619 }620621 m.complete(p, EXPR_ARRAY)622 } else if !compspecs.is_empty() {623 m.complete(p, EXPR_ARRAY_COMP)624 } else {625 m.complete(p, EXPR_ARRAY)626 }627}628/// Returns true if it was slice, false if just index629#[must_use]630fn slice_desc_or_index(p: &mut Parser) -> bool {631 let m = p.start();632 p.bump();633 // TODO: do not treat :, ::, ::: as full tokens?634 // Start635 if !p.at(T![:]) && !p.at(T![::]) {636 expr(p);637 }638 if p.at(T![:]) {639 p.bump();640 // End641 if !p.at(T![']']) {642 expr(p).wrap(p, SLICE_DESC_END);643 }644 if p.at(T![:]) {645 p.bump();646 // Step647 if !p.at(T![']']) {648 expr(p).wrap(p, SLICE_DESC_STEP);649 }650 }651 } else if p.at(T![::]) {652 p.bump();653 // End654 if !p.at(T![']']) {655 expr(p).wrap(p, SLICE_DESC_END);656 }657 } else {658 // It was not a slice659 p.expect(T![']']);660 m.forget(p);661 return false;662 }663 p.expect(T![']']);664 m.complete(p, SLICE_DESC);665 true666}667668fn suffix(p: &mut Parser) {669 loop {670 let start = p.start();671 let _marker: CompletedMarker = if p.at(T![?]) {672 p.bump();673 p.expect(T![.]);674 if p.at(IDENT) {675 name(p);676 start.complete(p, SUFFIX_INDEX)677 } else if p.at(T!['[']) {678 p.bump();679 expr(p);680 p.expect(T![']']);681 start.complete(p, SUFFIX_INDEX_EXPR)682 } else {683 start.complete_missing(p, ExpectedSyntax::Named("index"))684 }685 } else if p.at(T![.]) {686 p.bump();687 name(p);688 start.complete(p, SUFFIX_INDEX)689 } else if p.at(T!['[']) {690 if slice_desc_or_index(p) {691 start.complete(p, SUFFIX_SLICE)692 } else {693 start.complete(p, SUFFIX_INDEX_EXPR)694 }695 } else if p.at(T!['(']) {696 args_desc(p);697 start.complete(p, SUFFIX_APPLY)698 } else {699 start.forget(p);700 break;701 };702 }703}704705fn lhs(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {706 let lhs = lhs_basic(p)?;707708 suffix(p);709710 Ok(lhs)711}712fn name(p: &mut Parser) {713 let m = p.start();714 p.expect(IDENT);715 m.complete(p, NAME);716}717fn destruct_rest(p: &mut Parser) {718 let m = p.start();719 p.bump_assert(T![...]);720 if p.at(IDENT) {721 p.bump();722 }723 m.complete(p, DESTRUCT_REST);724}725fn destruct_object_field(p: &mut Parser) {726 let m = p.start();727 name(p);728 if p.at(T![:]) {729 p.bump();730 destruct(p);731 };732 if p.at(T![=]) {733 p.bump();734 expr(p);735 }736 m.complete(p, DESTRUCT_OBJECT_FIELD);737}738fn obj_local(p: &mut Parser) {739 let m = p.start();740 p.bump_assert(T![local]);741 bind(p);742 m.complete(p, OBJ_LOCAL);743}744fn destruct(p: &mut Parser) -> CompletedMarker {745 let m = p.start();746 let _ex = p.expected_syntax_name("destruction specifier");747 if p.at(T![?]) {748 p.bump();749 m.complete(p, DESTRUCT_SKIP)750 } else if p.at(T!['[']) {751 p.bump();752 // let mut had_rest = false;753 loop {754 if p.at(T![']']) {755 p.bump();756 break;757 } else if p.at(T![...]) {758 // let m_err = p.start_ranger();759 destruct_rest(p);760 // if had_rest {761 // p.custom_error(m_err.finish(p), "only one rest can be present in array");762 // }763 // had_rest = true;764 } else {765 destruct(p);766 }767 if p.at(T![,]) {768 p.bump();769 continue;770 }771 p.expect(T![']']);772 break;773 }774 m.complete(p, DESTRUCT_ARRAY)775 } else if p.at(T!['{']) {776 p.bump();777 let mut had_rest = false;778 loop {779 if p.at(T!['}']) {780 p.bump();781 break;782 } else if p.at(T![...]) {783 // let m_err = p.start_ranger();784 destruct_rest(p);785 // if had_rest {786 // p.custom_error(m_err.finish(p), "only one rest can be present in object");787 // }788 had_rest = true;789 } else {790 if had_rest {791 p.error_with_recovery_set(TS![]);792 }793 destruct_object_field(p);794 }795 if p.at(T![,]) {796 p.bump();797 continue;798 }799 p.expect(T!['}']);800 break;801 }802 m.complete(p, DESTRUCT_OBJECT)803 } else if p.at(IDENT) {804 name(p);805 m.complete(p, DESTRUCT_FULL)806 } else {807 m.forget(p);808 p.error_with_recovery_set(TS![; , '}', '(', :])809 }810}811fn bind(p: &mut Parser) {812 let m = p.start();813 if p.at(IDENT) && p.nth_at(1, T!['(']) {814 name(p);815 params_desc(p);816 p.expect(T![=]);817 expr(p);818 m.complete(p, BIND_FUNCTION)819 } else if p.at(IDENT) && p.nth_at(1, T![=]) && p.nth_at(2, T![function]) {820 name(p);821 p.expect(T![=]);822 p.expect(T![function]);823 params_desc(p);824 expr(p);825 m.complete(p, BIND_FUNCTION)826 } else {827 destruct(p);828 p.expect(T![=]);829 expr(p);830 m.complete(p, BIND_DESTRUCT)831 };832}833fn text(p: &mut Parser) {834 assert!(Text::can_cast(p.current()));835 p.bump();836}837fn number(p: &mut Parser) {838 assert!(Number::can_cast(p.current()));839 p.bump();840}841fn literal(p: &mut Parser) {842 assert!(Literal::can_cast(p.current()));843 p.bump();844}845fn lhs_basic(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {846 let _e = p.expected_syntax_name("expression");847 Ok(if Literal::can_cast(p.current()) {848 let m = p.start();849 literal(p);850 m.complete(p, EXPR_LITERAL)851 } else if Text::can_cast(p.current()) {852 let m = p.start();853 text(p);854 m.complete(p, EXPR_STRING)855 } else if Number::can_cast(p.current()) {856 let m = p.start();857 number(p);858 m.complete(p, EXPR_NUMBER)859 } else if p.at(IDENT) {860 let m = p.start();861 name(p);862 m.complete(p, EXPR_VAR)863 } else if p.at(T![if]) {864 let m = p.start();865 p.bump();866 expr(p);867 p.expect(T![then]);868 expr(p).wrap(p, TRUE_EXPR);869 if p.at(T![else]) {870 p.bump();871 expr(p).wrap(p, FALSE_EXPR);872 }873 m.complete(p, EXPR_IF_THEN_ELSE)874 } else if p.at(T!['[']) {875 array(p)876 } else if p.at(T!['{']) {877 object(p)878 } else if p.at(T![function]) {879 let m = p.start();880 p.bump();881 params_desc(p);882 expr(p);883 m.complete(p, EXPR_FUNCTION)884 } else if p.at(T![error]) {885 let m = p.start();886 p.bump();887 expr(p);888 m.complete(p, EXPR_ERROR)889 } else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {890 let m = p.start();891 p.bump();892 text(p);893 m.complete(p, EXPR_IMPORT)894 } else if let Some(op) = UnaryOperatorKind::cast(p.current()) {895 let ((), right_binding_power) = op.binding_power();896897 let m = p.start();898 p.bump();899 let _ = expr_binding_power(p, right_binding_power);900 m.complete(p, EXPR_UNARY)901 } else if p.at(T!['(']) {902 let m = p.start();903 p.bump();904 expr(p);905 p.expect(T![')']);906 m.complete(p, EXPR_PARENED)907 } else {908 return Err(p.error_with_no_skip());909 })910}911912impl Parse {913 pub fn syntax(&self) -> SyntaxNode {914 SyntaxNode::new_root(self.green_node.clone())915 }916}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.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -49,27 +49,27 @@
match special {
SpecialName::Literal => panic!("literal is not defined: {name}"),
SpecialName::Meta => {
- eprintln!("implicit meta: {}", name);
+ eprintln!("implicit meta: {name}");
kinds.define_token(TokenKind::Meta {
grammar_name: token.to_owned(),
- name: format!("META_{}", name),
- })
+ name: format!("META_{name}"),
+ });
}
SpecialName::Error => {
- eprintln!("implicit error: {}", name);
+ eprintln!("implicit error: {name}");
kinds.define_token(TokenKind::Error {
grammar_name: token.to_owned(),
- name: format!("ERROR_{}", name),
+ name: format!("ERROR_{name}"),
regex: None,
priority: None,
is_lexer_error: true,
- })
+ });
}
};
continue;
};
let name = to_upper_snake_case(token);
- eprintln!("implicit kw: {}", token);
+ eprintln!("implicit kw: {token}");
kinds.define_token(TokenKind::Keyword {
code: token.to_owned(),
name: format!("{name}_KW"),
@@ -98,14 +98,14 @@
"/../crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs",
)),
&syntax_kinds,
- )?;
+ );
ensure_file_contents(
&PathBuf::from(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../crates/jrsonnet-rowan-parser/src/generated/nodes.rs",
)),
&nodes,
- )?;
+ );
Ok(())
}
@@ -189,6 +189,7 @@
reformat(&ast.to_string())
}
+#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
fn generate_nodes(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {
let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
.nodes
@@ -524,7 +525,7 @@
fn write_doc_comment(contents: &[String], dest: &mut String) {
use std::fmt::Write;
for line in contents {
- writeln!(dest, "///{}", line).unwrap();
+ writeln!(dest, "///{line}").unwrap();
}
}
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;