diff --git a/Cargo.lock b/Cargo.lock index dcd154367..49a7c2b63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1198,12 +1198,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "image" version = "0.25.5" @@ -2943,7 +2937,6 @@ version = "0.13.1" dependencies = [ "comemo", "ecow", - "if_chain", "indexmap 2.7.1", "stacker", "toml", @@ -2991,7 +2984,6 @@ version = "0.13.1" dependencies = [ "comemo", "ecow", - "if_chain", "once_cell", "pathdiff", "serde", diff --git a/Cargo.toml b/Cargo.toml index 43a077ddb..08c6a8c8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,7 +68,6 @@ icu_provider = { version = "1.4", features = ["sync"] } icu_provider_adapters = "1.4" icu_provider_blob = "1.4" icu_segmenter = { version = "1.4", features = ["serde"] } -if_chain = "1" image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif", "webp"] } indexmap = { version = "2", features = ["serde"] } infer = { version = "0.19.0", default-features = false } diff --git a/crates/typst-eval/Cargo.toml b/crates/typst-eval/Cargo.toml index 12a6a6a46..b39382ffe 100644 --- a/crates/typst-eval/Cargo.toml +++ b/crates/typst-eval/Cargo.toml @@ -20,7 +20,6 @@ typst-timing = { workspace = true } typst-utils = { workspace = true } comemo = { workspace = true } ecow = { workspace = true } -if_chain = { workspace = true } indexmap = { workspace = true } toml = { workspace = true } unicode-segmentation = { workspace = true } diff --git a/crates/typst-eval/src/code.rs b/crates/typst-eval/src/code.rs index 9078418e4..1930ebc48 100644 --- a/crates/typst-eval/src/code.rs +++ b/crates/typst-eval/src/code.rs @@ -324,22 +324,19 @@ impl Eval for ast::FieldAccess<'_> { }; // Check whether this is a get rule field access. - if_chain::if_chain! { - if let Value::Func(func) = &value; - if let Some(element) = func.element(); - if let Some(id) = element.field_id(&field); - let styles = vm.context.styles().at(field.span()); - if let Ok(value) = element.field_from_styles( + if let Value::Func(func) = &value && + let Some(element) = func.element() && + let Some(id) = element.field_id(&field) && + let styles = vm.context.styles().at(field.span()) && + let Ok(value) = element.field_from_styles( id, styles.as_ref().map(|&s| s).unwrap_or_default(), - ); - then { + ) { // Only validate the context once we know that this is indeed // a field from the style chain. let _ = styles?; return Ok(value); } - } Err(err) } diff --git a/crates/typst-eval/src/rules.rs b/crates/typst-eval/src/rules.rs index 36fde561c..bf4a80780 100644 --- a/crates/typst-eval/src/rules.rs +++ b/crates/typst-eval/src/rules.rs @@ -57,12 +57,11 @@ impl Eval for ast::ShowRule<'_> { /// Migration hint for `show par: set block(spacing: ..)`. fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) { - if_chain::if_chain! { - if let Some(Selector::Elem(elem, _)) = recipe.selector(); - if *elem == Element::of::(); - if let Transformation::Style(styles) = recipe.transform(); - if styles.has(BlockElem::above) || styles.has(BlockElem::below); - then { + if let Some(Selector::Elem(elem, _)) = recipe.selector() && + *elem == Element::of::() && + let Transformation::Style(styles) = recipe.transform() && + (styles.has(BlockElem::above) || styles.has(BlockElem::below)) + { vm.engine.sink.warn(warning!( recipe.span(), "`show par: set block(spacing: ..)` has no effect anymore"; @@ -70,5 +69,4 @@ fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) { hint: "this is specific to paragraphs as they are not considered blocks anymore" )) } - } } diff --git a/crates/typst-ide/Cargo.toml b/crates/typst-ide/Cargo.toml index 20162e836..e7918e634 100644 --- a/crates/typst-ide/Cargo.toml +++ b/crates/typst-ide/Cargo.toml @@ -17,7 +17,6 @@ typst = { workspace = true } typst-eval = { workspace = true } comemo = { workspace = true } ecow = { workspace = true } -if_chain = { workspace = true } pathdiff = { workspace = true } serde = { workspace = true } unscanny = { workspace = true } diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs index 6cde69f3c..a974eb313 100644 --- a/crates/typst-ide/src/complete.rs +++ b/crates/typst-ide/src/complete.rs @@ -3,7 +3,6 @@ use std::collections::{BTreeMap, HashSet}; use std::ffi::OsStr; use ecow::{eco_format, EcoString}; -use if_chain::if_chain; use serde::{Deserialize, Serialize}; use typst::foundations::{ fields_on, repr, AutoValue, CastInfo, Func, Label, NoneValue, ParamInfo, Repr, @@ -145,27 +144,23 @@ fn complete_markup(ctx: &mut CompletionContext) -> bool { } // Behind a half-completed binding: "#let x = |". - if_chain! { - if let Some(prev) = ctx.leaf.prev_leaf(); - if prev.kind() == SyntaxKind::Eq; - if prev.parent_kind() == Some(SyntaxKind::LetBinding); - then { + if let Some(prev) = ctx.leaf.prev_leaf() + && prev.kind() == SyntaxKind::Eq + && prev.parent_kind() == Some(SyntaxKind::LetBinding) + { ctx.from = ctx.cursor; code_completions(ctx, false); return true; } - } // Behind a half-completed context block: "#context |". - if_chain! { - if let Some(prev) = ctx.leaf.prev_leaf(); - if prev.kind() == SyntaxKind::Context; - then { + if let Some(prev) = ctx.leaf.prev_leaf() + && prev.kind() == SyntaxKind::Context + { ctx.from = ctx.cursor; code_completions(ctx, false); return true; } - } // Directly after a raw block. let mut s = Scanner::new(ctx.text); @@ -373,38 +368,34 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool { ); // Behind an expression plus dot: "emoji.|". - if_chain! { - if ctx.leaf.kind() == SyntaxKind::Dot + if (ctx.leaf.kind() == SyntaxKind::Dot || (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathText) - && ctx.leaf.text() == "."); - if ctx.leaf.range().end == ctx.cursor; - if let Some(prev) = ctx.leaf.prev_sibling(); - if !in_markup || prev.range().end == ctx.leaf.range().start; - if prev.is::(); - if prev.parent_kind() != Some(SyntaxKind::Markup) || - prev.prev_sibling_kind() == Some(SyntaxKind::Hash); - if let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next(); - then { + && ctx.leaf.text() == ".")) + && ctx.leaf.range().end == ctx.cursor + && let Some(prev) = ctx.leaf.prev_sibling() + && (!in_markup || prev.range().end == ctx.leaf.range().start) + && prev.is::() + && (prev.parent_kind() != Some(SyntaxKind::Markup) || + prev.prev_sibling_kind() == Some(SyntaxKind::Hash)) + && let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next() + { ctx.from = ctx.cursor; field_access_completions(ctx, &value, &styles); return true; } - } // Behind a started field access: "emoji.fa|". - if_chain! { - if ctx.leaf.kind() == SyntaxKind::Ident; - if let Some(prev) = ctx.leaf.prev_sibling(); - if prev.kind() == SyntaxKind::Dot; - if let Some(prev_prev) = prev.prev_sibling(); - if prev_prev.is::(); - if let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next(); - then { + if ctx.leaf.kind() == SyntaxKind::Ident + && let Some(prev) = ctx.leaf.prev_sibling() + && prev.kind() == SyntaxKind::Dot + && let Some(prev_prev) = prev.prev_sibling() + && prev_prev.is::() + && let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next() + { ctx.from = ctx.leaf.offset(); field_access_completions(ctx, &value, &styles); return true; } - } false } @@ -507,14 +498,10 @@ fn complete_open_labels(ctx: &mut CompletionContext) -> bool { fn complete_imports(ctx: &mut CompletionContext) -> bool { // In an import path for a file or package: // "#import "|", - if_chain! { - if matches!( - ctx.leaf.parent_kind(), - Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude) - ); - if let Some(ast::Expr::Str(str)) = ctx.leaf.cast(); - let value = str.get(); - then { + if let Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude) = ctx.leaf.parent_kind() + && let Some(ast::Expr::Str(str)) = ctx.leaf.cast() + { + let value = str.get(); ctx.from = ctx.leaf.offset(); if value.starts_with('@') { let all_versions = value.contains(':'); @@ -524,41 +511,36 @@ fn complete_imports(ctx: &mut CompletionContext) -> bool { } return true; } - } // Behind an import list: // "#import "path.typ": |", // "#import "path.typ": a, b, |". - if_chain! { - if let Some(prev) = ctx.leaf.prev_sibling(); - if let Some(ast::Expr::ModuleImport(import)) = prev.get().cast(); - if let Some(ast::Imports::Items(items)) = import.imports(); - if let Some(source) = prev.children().find(|child| child.is::()); - then { + if let Some(prev) = ctx.leaf.prev_sibling() + && let Some(ast::Expr::ModuleImport(import)) = prev.get().cast() + && let Some(ast::Imports::Items(items)) = import.imports() + && let Some(source) = prev.children().find(|child| child.is::()) + { ctx.from = ctx.cursor; import_item_completions(ctx, items, &source); return true; } - } // Behind a half-started identifier in an import list: // "#import "path.typ": thi|", - if_chain! { - if ctx.leaf.kind() == SyntaxKind::Ident; - if let Some(parent) = ctx.leaf.parent(); - if parent.kind() == SyntaxKind::ImportItemPath; - if let Some(grand) = parent.parent(); - if grand.kind() == SyntaxKind::ImportItems; - if let Some(great) = grand.parent(); - if let Some(ast::Expr::ModuleImport(import)) = great.get().cast(); - if let Some(ast::Imports::Items(items)) = import.imports(); - if let Some(source) = great.children().find(|child| child.is::()); - then { + if ctx.leaf.kind() == SyntaxKind::Ident + && let Some(parent) = ctx.leaf.parent() + && parent.kind() == SyntaxKind::ImportItemPath + && let Some(grand) = parent.parent() + && grand.kind() == SyntaxKind::ImportItems + && let Some(great) = grand.parent() + && let Some(ast::Expr::ModuleImport(import)) = great.get().cast() + && let Some(ast::Imports::Items(items)) = import.imports() + && let Some(source) = great.children().find(|child| child.is::()) + { ctx.from = ctx.leaf.offset(); import_item_completions(ctx, items, &source); return true; } - } false } @@ -607,16 +589,14 @@ fn complete_rules(ctx: &mut CompletionContext) -> bool { } // Behind a half-completed show rule: "show strong: |". - if_chain! { - if let Some(prev) = ctx.leaf.prev_leaf(); - if matches!(prev.kind(), SyntaxKind::Colon); - if matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule)); - then { + if let Some(prev) = ctx.leaf.prev_leaf() + && matches!(prev.kind(), SyntaxKind::Colon) + && matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule)) + { ctx.from = ctx.cursor; show_rule_recipe_completions(ctx); return true; } - } false } @@ -682,27 +662,26 @@ fn show_rule_recipe_completions(ctx: &mut CompletionContext) { /// Complete call and set rule parameters. fn complete_params(ctx: &mut CompletionContext) -> bool { // Ensure that we are in a function call or set rule's argument list. - let (callee, set, args, args_linked) = if_chain! { - if let Some(parent) = ctx.leaf.parent(); - if let Some(parent) = match parent.kind() { + let (callee, set, args, args_linked) = + if let Some(parent) = ctx.leaf.parent() + && let Some(parent) = match parent.kind() { SyntaxKind::Named => parent.parent(), _ => Some(parent), - }; - if let Some(args) = parent.get().cast::(); - if let Some(grand) = parent.parent(); - if let Some(expr) = grand.get().cast::(); - let set = matches!(expr, ast::Expr::SetRule(_)); - if let Some(callee) = match expr { + } + && let Some(args) = parent.get().cast::() + && let Some(grand) = parent.parent() + && let Some(expr) = grand.get().cast::() + && let set = matches!(expr, ast::Expr::SetRule(_)) + && let Some(callee) = match expr { ast::Expr::FuncCall(call) => Some(call.callee()), ast::Expr::SetRule(set) => Some(set.target()), _ => None, - }; - then { + } + { (callee, set, args, parent) } else { return false; - } - }; + }; // Find the piece of syntax that decides what we're completing. let mut deciding = ctx.leaf.clone(); @@ -718,11 +697,10 @@ fn complete_params(ctx: &mut CompletionContext) -> bool { } // Parameter values: "func(param:|)", "func(param: |)". - if_chain! { - if deciding.kind() == SyntaxKind::Colon; - if let Some(prev) = deciding.prev_leaf(); - if let Some(param) = prev.get().cast::(); - then { + if let SyntaxKind::Colon = deciding.kind() + && let Some(prev) = deciding.prev_leaf() + && let Some(param) = prev.get().cast::() + { if let Some(next) = deciding.next_leaf() { ctx.from = ctx.cursor.min(next.offset()); } @@ -730,13 +708,11 @@ fn complete_params(ctx: &mut CompletionContext) -> bool { named_param_value_completions(ctx, callee, ¶m); return true; } - } // Parameters: "func(|)", "func(hi|)", "func(12,|)". - if_chain! { - if matches!(deciding.kind(), SyntaxKind::LeftParen | SyntaxKind::Comma); - if deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor; - then { + if let SyntaxKind::LeftParen | SyntaxKind::Comma = deciding.kind() + && (deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor) + { if let Some(next) = deciding.next_leaf() { ctx.from = ctx.cursor.min(next.offset()); } @@ -744,7 +720,6 @@ fn complete_params(ctx: &mut CompletionContext) -> bool { param_completions(ctx, callee, set, args, args_linked); return true; } - } false } @@ -1104,15 +1079,13 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) { fn is_in_equation_show_rule(leaf: &LinkedNode<'_>) -> bool { let mut node = leaf; while let Some(parent) = node.parent() { - if_chain! { - if let Some(expr) = parent.get().cast::(); - if let ast::Expr::ShowRule(show) = expr; - if let Some(ast::Expr::FieldAccess(field)) = show.selector(); - if field.field().as_str() == "equation"; - then { + if let Some(expr) = parent.get().cast::() + && let ast::Expr::ShowRule(show) = expr + && let Some(ast::Expr::FieldAccess(field)) = show.selector() + && field.field().as_str() == "equation" + { return true; } - } node = parent; } false diff --git a/crates/typst-ide/src/tooltip.rs b/crates/typst-ide/src/tooltip.rs index 700414637..078465206 100644 --- a/crates/typst-ide/src/tooltip.rs +++ b/crates/typst-ide/src/tooltip.rs @@ -1,7 +1,6 @@ use std::fmt::Write; use ecow::{eco_format, EcoString}; -use if_chain::if_chain; use typst::engine::Sink; use typst::foundations::{repr, Binding, Capturer, CastInfo, Repr, Value}; use typst::layout::{Length, PagedDocument}; @@ -107,20 +106,18 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option { /// Tooltips for imports. fn import_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option { - if_chain! { - if leaf.kind() == SyntaxKind::Star; - if let Some(parent) = leaf.parent(); - if let Some(import) = parent.cast::(); - if let Some(node) = parent.find(import.source().span()); - if let Some(value) = analyze_import(world, &node); - if let Some(scope) = value.scope(); - then { + if leaf.kind() == SyntaxKind::Star + && let Some(parent) = leaf.parent() + && let Some(import) = parent.cast::() + && let Some(node) = parent.find(import.source().span()) + && let Some(value) = analyze_import(world, &node) + && let Some(scope) = value.scope() + { let names: Vec<_> = scope.iter().map(|(name, ..)| eco_format!("`{name}`")).collect(); let list = repr::separated_list(&names, "and"); return Some(Tooltip::Text(eco_format!("This star imports {list}"))); } - } None } @@ -188,51 +185,46 @@ fn label_tooltip(document: &PagedDocument, leaf: &LinkedNode) -> Option /// Tooltips for components of a named parameter. fn named_param_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option { - let (func, named) = if_chain! { + let (func, named) = // Ensure that we are in a named pair in the arguments to a function // call or set rule. - if let Some(parent) = leaf.parent(); - if let Some(named) = parent.cast::(); - if let Some(grand) = parent.parent(); - if matches!(grand.kind(), SyntaxKind::Args); - if let Some(grand_grand) = grand.parent(); - if let Some(expr) = grand_grand.cast::(); - if let Some(ast::Expr::Ident(callee)) = match expr { + if let Some(parent) = leaf.parent() + && let Some(named) = parent.cast::() + && let Some(grand) = parent.parent() + && matches!(grand.kind(), SyntaxKind::Args) + && let Some(grand_grand) = grand.parent() + && let Some(expr) = grand_grand.cast::() + && let Some(ast::Expr::Ident(callee)) = match expr { ast::Expr::FuncCall(call) => Some(call.callee()), ast::Expr::SetRule(set) => Some(set.target()), _ => None, - }; + } // Find metadata about the function. - if let Some(Value::Func(func)) = world + && let Some(Value::Func(func)) = world .library() .global .scope() .get(&callee) - .map(Binding::read); - then { (func, named) } - else { return None; } - }; + .map(Binding::read) + { (func, named) } + else { return None; }; // Hovering over the parameter name. - if_chain! { - if leaf.index() == 0; - if let Some(ident) = leaf.cast::(); - if let Some(param) = func.param(&ident); - then { + if leaf.index() == 0 + && let Some(ident) = leaf.cast::() + && let Some(param) = func.param(&ident) + { return Some(Tooltip::Text(plain_docs_sentence(param.docs))); } - } // Hovering over a string parameter value. - if_chain! { - if let Some(string) = leaf.cast::(); - if let Some(param) = func.param(&named.name()); - if let Some(docs) = find_string_doc(¶m.input, &string.get()); - then { + if let Some(string) = leaf.cast::() + && let Some(param) = func.param(&named.name()) + && let Some(docs) = find_string_doc(¶m.input, &string.get()) + { return Some(Tooltip::Text(docs.into())); } - } None } @@ -250,27 +242,25 @@ fn find_string_doc(info: &CastInfo, string: &str) -> Option<&'static str> { /// Tooltip for font. fn font_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option { - if_chain! { // Ensure that we are on top of a string. - if let Some(string) = leaf.cast::(); - let lower = string.get().to_lowercase(); + if let Some(string) = leaf.cast::() + && let lower = string.get().to_lowercase() // Ensure that we are in the arguments to the text function. - if let Some(parent) = leaf.parent(); - if let Some(named) = parent.cast::(); - if named.name().as_str() == "font"; + && let Some(parent) = leaf.parent() + && let Some(named) = parent.cast::() + && named.name().as_str() == "font" // Find the font family. - if let Some((_, iter)) = world + && let Some((_, iter)) = world .book() .families() - .find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str()); + .find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str()) - then { + { let detail = summarize_font_family(iter.collect()); return Some(Tooltip::Text(detail)); } - }; None }