mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Autocomplete methods
This commit is contained in:
parent
2e039cb052
commit
a96141a3ea
@ -140,8 +140,11 @@ impl<T> Trace<T> for SourceResult<T> {
|
||||
F: Fn() -> Tracepoint,
|
||||
{
|
||||
self.map_err(|mut errors| {
|
||||
if span.is_detached() {
|
||||
return errors;
|
||||
}
|
||||
let range = world.source(span.source()).range(span);
|
||||
for error in errors.iter_mut() {
|
||||
for error in errors.iter_mut().filter(|e| !e.span.is_detached()) {
|
||||
// Skip traces that surround the error.
|
||||
let error_range = world.source(error.span.source()).range(error.span);
|
||||
if range.start <= error_range.start && range.end >= error_range.end {
|
||||
|
@ -22,6 +22,8 @@ pub fn analyze(world: &(dyn World + 'static), node: &LinkedNode) -> Vec<Value> {
|
||||
return tracer.finish();
|
||||
}
|
||||
|
||||
Some(ast::Expr::Str(s)) => return vec![Value::Str(s.get().into())],
|
||||
|
||||
Some(ast::Expr::FieldAccess(access)) => {
|
||||
if let Some(child) = node.children().next() {
|
||||
return analyze(world, &child)
|
||||
|
@ -3,7 +3,7 @@ use std::collections::{BTreeSet, HashSet};
|
||||
use if_chain::if_chain;
|
||||
|
||||
use super::{analyze, plain_docs_sentence, summarize_font_family};
|
||||
use crate::model::{CastInfo, Scope, Value};
|
||||
use crate::model::{methods_on, CastInfo, Scope, Value};
|
||||
use crate::syntax::{ast, LinkedNode, Source, SyntaxKind, SyntaxNode};
|
||||
use crate::util::{format_eco, EcoString};
|
||||
use crate::World;
|
||||
@ -271,7 +271,7 @@ fn math_completions(ctx: &mut CompletionContext) {
|
||||
|
||||
/// Complete field accesses.
|
||||
fn complete_field_accesses(ctx: &mut CompletionContext) -> bool {
|
||||
// Behind an identifier plus dot: "emoji.|".
|
||||
// Behind an expression plus dot: "emoji.|".
|
||||
if_chain! {
|
||||
if ctx.leaf.kind() == SyntaxKind::Dot
|
||||
|| (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathAtom)
|
||||
@ -325,7 +325,16 @@ fn field_access_completions(ctx: &mut CompletionContext, value: &Value) {
|
||||
ctx.value_completion(Some(name.clone()), value, None);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
_ => {
|
||||
for &method in methods_on(value.type_name()) {
|
||||
ctx.completions.push(Completion {
|
||||
kind: CompletionKind::Func,
|
||||
label: method.into(),
|
||||
apply: Some(format_eco!("{method}(${{}})")),
|
||||
detail: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,12 @@ pub fn eval(
|
||||
let route = unsafe { Route::insert(route, id) };
|
||||
let scopes = Scopes::new(Some(library));
|
||||
let mut vm = Vm::new(world, route.track(), tracer, id, scopes, 0);
|
||||
let result = source.ast()?.eval(&mut vm);
|
||||
let root = match source.root().cast::<ast::Markup>() {
|
||||
Some(markup) if vm.traced.is_some() => markup,
|
||||
_ => source.ast()?,
|
||||
};
|
||||
|
||||
let result = root.eval(&mut vm);
|
||||
|
||||
// Handle control flow.
|
||||
if let Some(flow) = vm.flow {
|
||||
|
@ -210,3 +210,36 @@ pub fn is_accessor(method: &str) -> bool {
|
||||
fn missing_method(type_name: &str, method: &str) -> String {
|
||||
format!("type {type_name} has no method `{method}`")
|
||||
}
|
||||
|
||||
/// List the available methods for a type.
|
||||
pub fn methods_on(type_name: &str) -> &[&'static str] {
|
||||
match type_name {
|
||||
"color" => &["lighten", "darken", "negate"],
|
||||
"string" => &[
|
||||
"len",
|
||||
"at",
|
||||
"contains",
|
||||
"ends-with",
|
||||
"find",
|
||||
"first",
|
||||
"last",
|
||||
"match",
|
||||
"matches",
|
||||
"position",
|
||||
"replace",
|
||||
"slice",
|
||||
"split",
|
||||
"starts-with",
|
||||
"trim",
|
||||
],
|
||||
"array" => &[
|
||||
"all", "any", "at", "contains", "filter", "find", "first", "flatten", "fold",
|
||||
"insert", "join", "last", "len", "map", "pop", "position", "push", "remove",
|
||||
"rev", "slice", "sorted",
|
||||
],
|
||||
"dictionary" => &["at", "insert", "keys", "len", "pairs", "remove", "values"],
|
||||
"function" => &["where", "with"],
|
||||
"arguments" => &["named", "pos"],
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ pub use self::dict::*;
|
||||
pub use self::eval::*;
|
||||
pub use self::func::*;
|
||||
pub use self::library::*;
|
||||
pub use self::methods::*;
|
||||
pub use self::module::*;
|
||||
pub use self::realize::*;
|
||||
pub use self::scope::*;
|
||||
|
@ -150,6 +150,7 @@ impl SyntaxNode {
|
||||
}
|
||||
|
||||
/// Convert the child to another kind.
|
||||
#[track_caller]
|
||||
pub(super) fn convert_to_kind(&mut self, kind: SyntaxKind) {
|
||||
debug_assert!(!kind.is_error());
|
||||
match &mut self.0 {
|
||||
@ -295,6 +296,7 @@ struct LeafNode {
|
||||
|
||||
impl LeafNode {
|
||||
/// Create a new leaf node.
|
||||
#[track_caller]
|
||||
fn new(kind: SyntaxKind, text: impl Into<EcoString>) -> Self {
|
||||
debug_assert!(!kind.is_error());
|
||||
Self { kind, text: text.into(), span: Span::detached() }
|
||||
@ -340,6 +342,7 @@ struct InnerNode {
|
||||
|
||||
impl InnerNode {
|
||||
/// Create a new inner node with the given kind and children.
|
||||
#[track_caller]
|
||||
fn new(kind: SyntaxKind, children: Vec<SyntaxNode>) -> Self {
|
||||
debug_assert!(!kind.is_error());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user