mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
Yeet if_chain
macro
This commit is contained in:
parent
c9c2315ad3
commit
e81a5a6ef2
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -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",
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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::<ParElem>();
|
||||
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::<ParElem>() &&
|
||||
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";
|
||||
@ -71,4 +70,3 @@ fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) {
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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::<ast::Expr>();
|
||||
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::<ast::Expr>()
|
||||
&& (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::<ast::Expr>();
|
||||
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::<ast::Expr>()
|
||||
&& 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();
|
||||
if let Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude) = ctx.leaf.parent_kind()
|
||||
&& let Some(ast::Expr::Str(str)) = ctx.leaf.cast()
|
||||
{
|
||||
let value = str.get();
|
||||
then {
|
||||
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::<ast::Expr>());
|
||||
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::<ast::Expr>())
|
||||
{
|
||||
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::<ast::Expr>());
|
||||
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::<ast::Expr>())
|
||||
{
|
||||
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,26 +662,25 @@ 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::<ast::Args>();
|
||||
if let Some(grand) = parent.parent();
|
||||
if let Some(expr) = grand.get().cast::<ast::Expr>();
|
||||
let set = matches!(expr, ast::Expr::SetRule(_));
|
||||
if let Some(callee) = match expr {
|
||||
}
|
||||
&& let Some(args) = parent.get().cast::<ast::Args>()
|
||||
&& let Some(grand) = parent.parent()
|
||||
&& let Some(expr) = grand.get().cast::<ast::Expr>()
|
||||
&& 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.
|
||||
@ -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::<ast::Ident>();
|
||||
then {
|
||||
if let SyntaxKind::Colon = deciding.kind()
|
||||
&& let Some(prev) = deciding.prev_leaf()
|
||||
&& let Some(param) = prev.get().cast::<ast::Ident>()
|
||||
{
|
||||
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::<ast::Expr>();
|
||||
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::<ast::Expr>()
|
||||
&& let ast::Expr::ShowRule(show) = expr
|
||||
&& let Some(ast::Expr::FieldAccess(field)) = show.selector()
|
||||
&& field.field().as_str() == "equation"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
false
|
||||
|
@ -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<Tooltip> {
|
||||
|
||||
/// Tooltips for imports.
|
||||
fn import_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
if_chain! {
|
||||
if leaf.kind() == SyntaxKind::Star;
|
||||
if let Some(parent) = leaf.parent();
|
||||
if let Some(import) = parent.cast::<ast::ModuleImport>();
|
||||
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::<ast::ModuleImport>()
|
||||
&& 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<Tooltip>
|
||||
|
||||
/// Tooltips for components of a named parameter.
|
||||
fn named_param_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
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::<ast::Named>();
|
||||
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::<ast::Expr>();
|
||||
if let Some(ast::Expr::Ident(callee)) = match expr {
|
||||
if let Some(parent) = leaf.parent()
|
||||
&& let Some(named) = parent.cast::<ast::Named>()
|
||||
&& let Some(grand) = parent.parent()
|
||||
&& matches!(grand.kind(), SyntaxKind::Args)
|
||||
&& let Some(grand_grand) = grand.parent()
|
||||
&& let Some(expr) = grand_grand.cast::<ast::Expr>()
|
||||
&& 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::<ast::Ident>();
|
||||
if let Some(param) = func.param(&ident);
|
||||
then {
|
||||
if leaf.index() == 0
|
||||
&& let Some(ident) = leaf.cast::<ast::Ident>()
|
||||
&& 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::<ast::Str>();
|
||||
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::<ast::Str>()
|
||||
&& 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<Tooltip> {
|
||||
if_chain! {
|
||||
// Ensure that we are on top of a string.
|
||||
if let Some(string) = leaf.cast::<ast::Str>();
|
||||
let lower = string.get().to_lowercase();
|
||||
if let Some(string) = leaf.cast::<ast::Str>()
|
||||
&& 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::<ast::Named>();
|
||||
if named.name().as_str() == "font";
|
||||
&& let Some(parent) = leaf.parent()
|
||||
&& let Some(named) = parent.cast::<ast::Named>()
|
||||
&& 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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user