mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-24 05:05:00 +00:00
refactor: rename local variables and some types (#1023)
* fix: naming * refactor: rename local variables and some types
This commit is contained in:
parent
ad0c1e8aca
commit
be1d659719
52 changed files with 805 additions and 787 deletions
|
@ -31,12 +31,12 @@ fn main() -> typlite::Result<()> {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or("Missing required argument: INPUT")?;
|
.ok_or("Missing required argument: INPUT")?;
|
||||||
let output = match args.output {
|
let output = match args.output {
|
||||||
Some(e) if e == "-" => None,
|
Some(stdout_path) if stdout_path == "-" => None,
|
||||||
Some(e) => Some(PathBuf::from(e)),
|
Some(output_path) => Some(PathBuf::from(output_path)),
|
||||||
None => Some(Path::new(input).with_extension("md")),
|
None => Some(Path::new(input).with_extension("md")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let universe = args.compile.resolve().map_err(|e| format!("{e:?}"))?;
|
let universe = args.compile.resolve().map_err(|err| format!("{err:?}"))?;
|
||||||
let world = universe.snapshot();
|
let world = universe.snapshot();
|
||||||
|
|
||||||
let converter = Typlite::new(Arc::new(world)).with_library(lib());
|
let converter = Typlite::new(Arc::new(world)).with_library(lib());
|
||||||
|
@ -45,8 +45,8 @@ fn main() -> typlite::Result<()> {
|
||||||
match (conv, output) {
|
match (conv, output) {
|
||||||
(Ok(conv), None) => println!("{}", conv),
|
(Ok(conv), None) => println!("{}", conv),
|
||||||
(Ok(conv), Some(output)) => std::fs::write(output, conv.as_str()).unwrap(),
|
(Ok(conv), Some(output)) => std::fs::write(output, conv.as_str()).unwrap(),
|
||||||
(Err(e), ..) => {
|
(Err(err), ..) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{err}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,10 @@ pub fn resolve_id_by_path(
|
||||||
pub fn find_source_by_expr(
|
pub fn find_source_by_expr(
|
||||||
world: &dyn World,
|
world: &dyn World,
|
||||||
current: TypstFileId,
|
current: TypstFileId,
|
||||||
e: ast::Expr,
|
import_source: ast::Expr,
|
||||||
) -> Option<Source> {
|
) -> Option<Source> {
|
||||||
// todo: this could be valid: import("path.typ"), where v is parenthesized
|
// todo: this could be valid: import("path.typ"), where v is parenthesized
|
||||||
match e {
|
match import_source {
|
||||||
ast::Expr::Str(s) => world
|
ast::Expr::Str(s) => world
|
||||||
.source(resolve_id_by_path(world, current, s.get().as_str())?)
|
.source(resolve_id_by_path(world, current, s.get().as_str())?)
|
||||||
.ok(),
|
.ok(),
|
||||||
|
|
|
@ -85,8 +85,8 @@ impl<T> RevisionManager<T> {
|
||||||
let slot_base = self
|
let slot_base = self
|
||||||
.slots
|
.slots
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|e| e.revision <= revision.get())
|
.filter(|slot| slot.revision <= revision.get())
|
||||||
.reduce(|a, b| if a.revision > b.revision { a } else { b });
|
.reduce(|x, y| if x.revision > y.revision { x } else { y });
|
||||||
|
|
||||||
if let Some(slot) = slot_base {
|
if let Some(slot) = slot_base {
|
||||||
if slot.revision == revision.get() {
|
if slot.revision == revision.get() {
|
||||||
|
@ -120,7 +120,7 @@ impl<T> RevisionManager<T> {
|
||||||
// if there is no locked revision, we only keep the latest revision
|
// if there is no locked revision, we only keep the latest revision
|
||||||
self.slots
|
self.slots
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.revision)
|
.map(|slot| slot.revision)
|
||||||
.max())
|
.max())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,15 +85,15 @@ impl LspWorldExt for tinymist_world::LspWorld {
|
||||||
Ok(TypstFileId::new(None, VirtualPath::new(relative_path)))
|
Ok(TypstFileId::new(None, VirtualPath::new(relative_path)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_by_path(&self, p: &Path) -> FileResult<Source> {
|
fn source_by_path(&self, path: &Path) -> FileResult<Source> {
|
||||||
// todo: source cache
|
// todo: source cache
|
||||||
self.source(self.file_id_by_path(p)?)
|
self.source(self.file_id_by_path(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uri_for_id(&self, id: TypstFileId) -> Result<Url, FileError> {
|
fn uri_for_id(&self, fid: TypstFileId) -> Result<Url, FileError> {
|
||||||
self.path_for_id(id).and_then(|e| {
|
self.path_for_id(fid).and_then(|path| {
|
||||||
path_to_url(&e)
|
path_to_url(&path)
|
||||||
.map_err(|e| FileError::Other(Some(eco_format!("convert to url: {e:?}"))))
|
.map_err(|err| FileError::Other(Some(eco_format!("convert to url: {err:?}"))))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,10 +118,10 @@ mod matcher_tests {
|
||||||
let root = LinkedNode::new(source.root());
|
let root = LinkedNode::new(source.root());
|
||||||
let node = root.leaf_at_compat(pos).unwrap();
|
let node = root.leaf_at_compat(pos).unwrap();
|
||||||
|
|
||||||
let result = classify_def(node).map(|e| format!("{:?}", e.node().range()));
|
let snap = classify_def(node).map(|def| format!("{:?}", def.node().range()));
|
||||||
let result = result.as_deref().unwrap_or("<nil>");
|
let snap = snap.as_deref().unwrap_or("<nil>");
|
||||||
|
|
||||||
assert_snapshot!(result);
|
assert_snapshot!(snap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,17 +201,17 @@ mod expr_tests {
|
||||||
decl: ident,
|
decl: ident,
|
||||||
step,
|
step,
|
||||||
root,
|
root,
|
||||||
val,
|
term,
|
||||||
} = expr.as_ref();
|
} = expr.as_ref();
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{} -> {}, root {}, val: {val:?}",
|
"{} -> {}, root {}, val: {term:?}",
|
||||||
source.show_expr(&Expr::Decl(ident.clone())),
|
source.show_expr(&Expr::Decl(ident.clone())),
|
||||||
step.as_ref()
|
step.as_ref()
|
||||||
.map(|e| source.show_expr(e))
|
.map(|expr| source.show_expr(expr))
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
root.as_ref()
|
root.as_ref()
|
||||||
.map(|e| source.show_expr(e))
|
.map(|expr| source.show_expr(expr))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -300,7 +300,7 @@ mod type_check_tests {
|
||||||
|
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
|
|
||||||
use super::{Ty, TypeScheme};
|
use super::{Ty, TypeInfo};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
|
@ -314,7 +314,7 @@ mod type_check_tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypeCheckSnapshot<'a>(&'a Source, &'a TypeScheme);
|
struct TypeCheckSnapshot<'a>(&'a Source, &'a TypeInfo);
|
||||||
|
|
||||||
impl fmt::Debug for TypeCheckSnapshot<'_> {
|
impl fmt::Debug for TypeCheckSnapshot<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -322,21 +322,21 @@ mod type_check_tests {
|
||||||
let info = self.1;
|
let info = self.1;
|
||||||
let mut vars = info
|
let mut vars = info
|
||||||
.vars
|
.vars
|
||||||
.iter()
|
.values()
|
||||||
.map(|e| (e.1.name(), e.1))
|
.map(|bounds| (bounds.name(), bounds))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
vars.sort_by(|x, y| x.1.var.cmp(&y.1.var));
|
vars.sort_by(|x, y| x.1.var.cmp(&y.1.var));
|
||||||
|
|
||||||
for (name, var) in vars {
|
for (name, bounds) in vars {
|
||||||
writeln!(f, "{:?} = {:?}", name, info.simplify(var.as_type(), true))?;
|
writeln!(f, "{name:?} = {:?}", info.simplify(bounds.as_type(), true))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(f, "=====")?;
|
writeln!(f, "=====")?;
|
||||||
let mut mapping = info
|
let mut mapping = info
|
||||||
.mapping
|
.mapping
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| (source.range(*e.0).unwrap_or_default(), e.1))
|
.map(|pair| (source.range(*pair.0).unwrap_or_default(), pair.1))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
mapping.sort_by(|x, y| {
|
mapping.sort_by(|x, y| {
|
||||||
|
@ -378,14 +378,14 @@ mod post_type_check_tests {
|
||||||
let text = node.get().clone().into_text();
|
let text = node.get().clone().into_text();
|
||||||
|
|
||||||
let result = ctx.type_check(&source);
|
let result = ctx.type_check(&source);
|
||||||
let literal_type = post_type_check(ctx.shared_(), &result, node);
|
let post_ty = post_type_check(ctx.shared_(), &result, node);
|
||||||
|
|
||||||
with_settings!({
|
with_settings!({
|
||||||
description => format!("Check on {text:?} ({pos:?})"),
|
description => format!("Check on {text:?} ({pos:?})"),
|
||||||
}, {
|
}, {
|
||||||
let literal_type = literal_type.map(|e| format!("{e:#?}"))
|
let post_ty = post_ty.map(|ty| format!("{ty:#?}"))
|
||||||
.unwrap_or_else(|| "<nil>".to_string());
|
.unwrap_or_else(|| "<nil>".to_string());
|
||||||
assert_snapshot!(literal_type);
|
assert_snapshot!(post_ty);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -413,15 +413,15 @@ mod type_describe_tests {
|
||||||
let node = root.leaf_at_compat(pos + 1).unwrap();
|
let node = root.leaf_at_compat(pos + 1).unwrap();
|
||||||
let text = node.get().clone().into_text();
|
let text = node.get().clone().into_text();
|
||||||
|
|
||||||
let result = ctx.type_check(&source);
|
let ti = ctx.type_check(&source);
|
||||||
let literal_type = post_type_check(ctx.shared_(), &result, node);
|
let post_ty = post_type_check(ctx.shared_(), &ti, node);
|
||||||
|
|
||||||
with_settings!({
|
with_settings!({
|
||||||
description => format!("Check on {text:?} ({pos:?})"),
|
description => format!("Check on {text:?} ({pos:?})"),
|
||||||
}, {
|
}, {
|
||||||
let literal_type = literal_type.and_then(|e| e.describe())
|
let post_ty = post_ty.and_then(|ty| ty.describe())
|
||||||
.unwrap_or_else(|| "<nil>".into());
|
.unwrap_or_else(|| "<nil>".into());
|
||||||
assert_snapshot!(literal_type);
|
assert_snapshot!(post_ty);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,11 +70,11 @@ impl YamlBib {
|
||||||
loader
|
loader
|
||||||
.content
|
.content
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(k, span)| [k.span.start, k.span.end, span.start, span.end])
|
.flat_map(|(name, span)| [name.span.start, name.span.end, span.start, span.end])
|
||||||
.map(|e| (e, None)),
|
.map(|offset| (offset, None)),
|
||||||
);
|
);
|
||||||
span_mapper.sort_by_key(|e| e.0);
|
span_mapper.sort_by_key(|(offset, _)| *offset);
|
||||||
span_mapper.dedup_by_key(|e| e.0);
|
span_mapper.dedup_by_key(|(offset, _)| *offset);
|
||||||
let mut span_cursor = 0;
|
let mut span_cursor = 0;
|
||||||
let mut byte_offset = 0;
|
let mut byte_offset = 0;
|
||||||
for (off, ch) in content.chars().chain(Some('\0')).enumerate() {
|
for (off, ch) in content.chars().chain(Some('\0')).enumerate() {
|
||||||
|
@ -170,14 +170,14 @@ impl BibWorker {
|
||||||
}
|
}
|
||||||
"bib" => {
|
"bib" => {
|
||||||
let bibliography = biblatex::RawBibliography::parse(content).ok()?;
|
let bibliography = biblatex::RawBibliography::parse(content).ok()?;
|
||||||
for e in bibliography.entries {
|
for entry in bibliography.entries {
|
||||||
let k = e.v.key;
|
let name = entry.v.key;
|
||||||
let span = e.span;
|
let span = entry.span;
|
||||||
self.info.entries.insert(
|
self.info.entries.insert(
|
||||||
k.v.to_owned(),
|
name.v.to_owned(),
|
||||||
BibEntry {
|
BibEntry {
|
||||||
file_id: path,
|
file_id: path,
|
||||||
name_span: k.span,
|
name_span: name.span,
|
||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -112,13 +112,13 @@ impl<'a> CodeActionWorker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heading_actions(&mut self, node: &LinkedNode) -> Option<()> {
|
fn heading_actions(&mut self, node: &LinkedNode) -> Option<()> {
|
||||||
let h = node.cast::<ast::Heading>()?;
|
let heading = node.cast::<ast::Heading>()?;
|
||||||
let depth = h.depth().get();
|
let depth = heading.depth().get();
|
||||||
|
|
||||||
// Only the marker is replaced, for minimal text change
|
// Only the marker is replaced, for minimal text change
|
||||||
let marker = node
|
let marker = node
|
||||||
.children()
|
.children()
|
||||||
.find(|e| e.kind() == SyntaxKind::HeadingMarker)?;
|
.find(|child| child.kind() == SyntaxKind::HeadingMarker)?;
|
||||||
let marker_range = marker.range();
|
let marker_range = marker.range();
|
||||||
|
|
||||||
if depth > 1 {
|
if depth > 1 {
|
||||||
|
@ -161,8 +161,9 @@ impl<'a> CodeActionWorker<'a> {
|
||||||
|
|
||||||
let mut chs = node.children();
|
let mut chs = node.children();
|
||||||
let chs = chs.by_ref();
|
let chs = chs.by_ref();
|
||||||
let first_dollar = chs.take(1).find(|e| e.kind() == SyntaxKind::Dollar)?;
|
let is_dollar = |node: &LinkedNode| node.kind() == SyntaxKind::Dollar;
|
||||||
let last_dollar = chs.rev().take(1).find(|e| e.kind() == SyntaxKind::Dollar)?;
|
let first_dollar = chs.take(1).find(is_dollar)?;
|
||||||
|
let last_dollar = chs.rev().take(1).find(is_dollar)?;
|
||||||
|
|
||||||
// Erroneous equation is skipped.
|
// Erroneous equation is skipped.
|
||||||
// For example, some unclosed equation.
|
// For example, some unclosed equation.
|
||||||
|
@ -242,15 +243,15 @@ impl<'a> CodeActionWorker<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prepare actions
|
// Prepare actions
|
||||||
let a1 = if is_block {
|
let toggle_action = if is_block {
|
||||||
rewrite_action("Convert to inline equation", "")?
|
rewrite_action("Convert to inline equation", "")?
|
||||||
} else {
|
} else {
|
||||||
rewrite_action("Convert to block equation", " ")?
|
rewrite_action("Convert to block equation", " ")?
|
||||||
};
|
};
|
||||||
let a2 = rewrite_action("Convert to multiple-line block equation", "\n");
|
let block_action = rewrite_action("Convert to multiple-line block equation", "\n");
|
||||||
|
|
||||||
self.actions.push(a1);
|
self.actions.push(toggle_action);
|
||||||
if let Some(a2) = a2 {
|
if let Some(a2) = block_action {
|
||||||
self.actions.push(a2);
|
self.actions.push(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl Definition {
|
||||||
|
|
||||||
/// The location of the definition.
|
/// The location of the definition.
|
||||||
// todo: cache
|
// todo: cache
|
||||||
pub(crate) fn def_at(&self, ctx: &SharedContext) -> Option<(TypstFileId, Range<usize>)> {
|
pub(crate) fn location(&self, ctx: &SharedContext) -> Option<(TypstFileId, Range<usize>)> {
|
||||||
let fid = self.decl.file_id()?;
|
let fid = self.decl.file_id()?;
|
||||||
let span = self.decl.span();
|
let span = self.decl.span();
|
||||||
let range = (!span.is_detached()).then(|| ctx.source_by_id(fid).ok()?.range(span));
|
let range = (!span.is_detached()).then(|| ctx.source_by_id(fid).ok()?.range(span));
|
||||||
|
@ -83,8 +83,8 @@ pub fn definition(
|
||||||
};
|
};
|
||||||
|
|
||||||
let introspector = &document?.document.introspector;
|
let introspector = &document?.document.introspector;
|
||||||
find_bib_definition(ctx, introspector, name)
|
bib_definition(ctx, introspector, name)
|
||||||
.or_else(|| find_ref_definition(introspector, name, ref_expr))
|
.or_else(|| ref_definition(introspector, name, ref_expr))
|
||||||
}
|
}
|
||||||
SyntaxClass::Label {
|
SyntaxClass::Label {
|
||||||
node: _,
|
node: _,
|
||||||
|
@ -102,9 +102,9 @@ fn find_ident_definition(
|
||||||
// Lexical reference
|
// Lexical reference
|
||||||
let ident_store = use_site.clone();
|
let ident_store = use_site.clone();
|
||||||
let ident_ref = match ident_store.cast::<ast::Expr>()? {
|
let ident_ref = match ident_store.cast::<ast::Expr>()? {
|
||||||
ast::Expr::Ident(e) => e.span(),
|
ast::Expr::Ident(ident) => ident.span(),
|
||||||
ast::Expr::MathIdent(e) => e.span(),
|
ast::Expr::MathIdent(ident) => ident.span(),
|
||||||
ast::Expr::FieldAccess(s) => return find_field_definition(ctx, s),
|
ast::Expr::FieldAccess(field_access) => return field_definition(ctx, field_access),
|
||||||
_ => {
|
_ => {
|
||||||
crate::log_debug_ct!("unsupported kind {kind:?}", kind = use_site.kind());
|
crate::log_debug_ct!("unsupported kind {kind:?}", kind = use_site.kind());
|
||||||
Span::detached()
|
Span::detached()
|
||||||
|
@ -114,8 +114,8 @@ fn find_ident_definition(
|
||||||
DefResolver::new(ctx, source)?.of_span(ident_ref)
|
DefResolver::new(ctx, source)?.of_span(ident_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_field_definition(ctx: &Arc<SharedContext>, fa: ast::FieldAccess<'_>) -> Option<Definition> {
|
fn field_definition(ctx: &Arc<SharedContext>, node: ast::FieldAccess) -> Option<Definition> {
|
||||||
let span = fa.span();
|
let span = node.span();
|
||||||
let ty = ctx.type_of_span(span)?;
|
let ty = ctx.type_of_span(span)?;
|
||||||
crate::log_debug_ct!("find_field_definition[{span:?}]: {ty:?}");
|
crate::log_debug_ct!("find_field_definition[{span:?}]: {ty:?}");
|
||||||
|
|
||||||
|
@ -134,22 +134,22 @@ fn find_field_definition(ctx: &Arc<SharedContext>, fa: ast::FieldAccess<'_>) ->
|
||||||
let source = ctx.source_by_id(s.id()?).ok()?;
|
let source = ctx.source_by_id(s.id()?).ok()?;
|
||||||
DefResolver::new(ctx, &source)?.of_span(s)
|
DefResolver::new(ctx, &source)?.of_span(s)
|
||||||
}
|
}
|
||||||
DocSource::Ins(ins) => value_to_def(ins.val.clone(), || Some(fa.field().get().into())),
|
DocSource::Ins(ins) => value_to_def(ins.val.clone(), || Some(node.field().get().into())),
|
||||||
DocSource::Builtin(..) => None,
|
DocSource::Builtin(..) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_bib_definition(
|
fn bib_definition(
|
||||||
ctx: &Arc<SharedContext>,
|
ctx: &Arc<SharedContext>,
|
||||||
introspector: &Introspector,
|
introspector: &Introspector,
|
||||||
key: &str,
|
key: &str,
|
||||||
) -> Option<Definition> {
|
) -> Option<Definition> {
|
||||||
let bib_elem = BibliographyElem::find(introspector.track()).ok()?;
|
let bib_elem = BibliographyElem::find(introspector.track()).ok()?;
|
||||||
let Value::Array(arr) = bib_elem.path().clone().into_value() else {
|
let Value::Array(paths) = bib_elem.path().clone().into_value() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let bib_paths = arr.into_iter().map(Value::cast).flat_map(|e| e.ok());
|
let bib_paths = paths.into_iter().flat_map(|path| path.cast().ok());
|
||||||
let bib_info = ctx.analyze_bib(bib_elem.span(), bib_paths)?;
|
let bib_info = ctx.analyze_bib(bib_elem.span(), bib_paths)?;
|
||||||
|
|
||||||
let entry = bib_info.entries.get(key)?;
|
let entry = bib_info.entries.get(key)?;
|
||||||
|
@ -160,7 +160,7 @@ fn find_bib_definition(
|
||||||
Some(Definition::new(decl.into(), None))
|
Some(Definition::new(decl.into(), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_ref_definition(
|
fn ref_definition(
|
||||||
introspector: &Introspector,
|
introspector: &Introspector,
|
||||||
name: &str,
|
name: &str,
|
||||||
ref_expr: ast::Expr,
|
ref_expr: ast::Expr,
|
||||||
|
@ -307,7 +307,7 @@ fn value_to_def(value: Value, name: impl FnOnce() -> Option<Interned<str>>) -> O
|
||||||
let val = Ty::Value(InsTy::new(value.clone()));
|
let val = Ty::Value(InsTy::new(value.clone()));
|
||||||
Some(match value {
|
Some(match value {
|
||||||
Value::Func(func) => {
|
Value::Func(func) => {
|
||||||
let name = func.name().map(|e| e.into()).or_else(name)?;
|
let name = func.name().map(|name| name.into()).or_else(name)?;
|
||||||
let mut s = SyntaxNode::leaf(SyntaxKind::Ident, &name);
|
let mut s = SyntaxNode::leaf(SyntaxKind::Ident, &name);
|
||||||
s.synthesize(func.span());
|
s.synthesize(func.span());
|
||||||
|
|
||||||
|
@ -334,9 +334,9 @@ impl DefResolver {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = self.ei.resolves.get(&span).cloned()?;
|
let resolved = self.ei.resolves.get(&span).cloned()?;
|
||||||
match (&expr.root, &expr.val) {
|
match (&resolved.root, &resolved.term) {
|
||||||
(Some(expr), ty) => self.of_expr(expr, ty.as_ref()),
|
(Some(expr), term) => self.of_expr(expr, term.as_ref()),
|
||||||
(None, Some(term)) => self.of_term(term),
|
(None, Some(term)) => self.of_term(term),
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,9 @@ impl DefResolver {
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Decl(decl) => self.of_decl(decl, term),
|
Expr::Decl(decl) => self.of_decl(decl, term),
|
||||||
Expr::Ref(r) => self.of_expr(r.root.as_ref()?, r.val.as_ref().or(term)),
|
Expr::Ref(resolved) => {
|
||||||
|
self.of_expr(resolved.root.as_ref()?, resolved.term.as_ref().or(term))
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ use crate::analysis::{
|
||||||
analyze_bib, analyze_expr_, analyze_import_, analyze_signature, definition, post_type_check,
|
analyze_bib, analyze_expr_, analyze_import_, analyze_signature, definition, post_type_check,
|
||||||
AllocStats, AnalysisStats, BibInfo, Definition, PathPreference, QueryStatGuard,
|
AllocStats, AnalysisStats, BibInfo, Definition, PathPreference, QueryStatGuard,
|
||||||
SemanticTokenCache, SemanticTokenContext, SemanticTokens, Signature, SignatureTarget, Ty,
|
SemanticTokenCache, SemanticTokenContext, SemanticTokens, Signature, SignatureTarget, Ty,
|
||||||
TypeScheme,
|
TypeInfo,
|
||||||
};
|
};
|
||||||
use crate::docs::{DefDocs, TidyModuleDocs};
|
use crate::docs::{DefDocs, TidyModuleDocs};
|
||||||
use crate::syntax::{
|
use crate::syntax::{
|
||||||
|
@ -303,7 +303,7 @@ impl LocalContext {
|
||||||
&self,
|
&self,
|
||||||
pref: &PathPreference,
|
pref: &PathPreference,
|
||||||
) -> impl Iterator<Item = &TypstFileId> {
|
) -> impl Iterator<Item = &TypstFileId> {
|
||||||
let r = pref.ext_matcher();
|
let regexes = pref.ext_matcher();
|
||||||
self.caches
|
self.caches
|
||||||
.completion_files
|
.completion_files
|
||||||
.get_or_init(|| {
|
.get_or_init(|| {
|
||||||
|
@ -316,12 +316,12 @@ impl LocalContext {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.iter()
|
.iter()
|
||||||
.filter(move |p| {
|
.filter(move |fid| {
|
||||||
p.vpath()
|
fid.vpath()
|
||||||
.as_rooted_path()
|
.as_rooted_path()
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|p| p.to_str())
|
.and_then(|path| path.to_str())
|
||||||
.is_some_and(|e| r.is_match(e))
|
.is_some_and(|path| regexes.is_match(path))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,14 +416,14 @@ impl LocalContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type check information of a source file.
|
/// Get the type check information of a source file.
|
||||||
pub(crate) fn type_check(&mut self, source: &Source) -> Arc<TypeScheme> {
|
pub(crate) fn type_check(&mut self, source: &Source) -> Arc<TypeInfo> {
|
||||||
let id = source.id();
|
let id = source.id();
|
||||||
let cache = &self.caches.modules.entry(id).or_default().type_check;
|
let cache = &self.caches.modules.entry(id).or_default().type_check;
|
||||||
cache.get_or_init(|| self.shared.type_check(source)).clone()
|
cache.get_or_init(|| self.shared.type_check(source)).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type check information of a source file.
|
/// Get the type check information of a source file.
|
||||||
pub(crate) fn type_check_by_id(&mut self, id: TypstFileId) -> Arc<TypeScheme> {
|
pub(crate) fn type_check_by_id(&mut self, id: TypstFileId) -> Arc<TypeInfo> {
|
||||||
let cache = &self.caches.modules.entry(id).or_default().type_check;
|
let cache = &self.caches.modules.entry(id).or_default().type_check;
|
||||||
cache
|
cache
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -511,13 +511,13 @@ impl SharedContext {
|
||||||
|
|
||||||
/// Convert a Typst range to a LSP range.
|
/// Convert a Typst range to a LSP range.
|
||||||
pub fn to_lsp_range_(&self, position: TypstRange, fid: TypstFileId) -> Option<LspRange> {
|
pub fn to_lsp_range_(&self, position: TypstRange, fid: TypstFileId) -> Option<LspRange> {
|
||||||
let w = fid
|
let ext = fid
|
||||||
.vpath()
|
.vpath()
|
||||||
.as_rootless_path()
|
.as_rootless_path()
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str());
|
.and_then(|ext| ext.to_str());
|
||||||
// yaml/yml/bib
|
// yaml/yml/bib
|
||||||
if matches!(w, Some("yaml" | "yml" | "bib")) {
|
if matches!(ext, Some("yaml" | "yml" | "bib")) {
|
||||||
let bytes = self.file_by_id(fid).ok()?;
|
let bytes = self.file_by_id(fid).ok()?;
|
||||||
let bytes_len = bytes.len();
|
let bytes_len = bytes.len();
|
||||||
let loc = loc_info(bytes)?;
|
let loc = loc_info(bytes)?;
|
||||||
|
@ -578,8 +578,8 @@ impl SharedContext {
|
||||||
position: LspPosition,
|
position: LspPosition,
|
||||||
shift: usize,
|
shift: usize,
|
||||||
) -> Option<SyntaxClass<'s>> {
|
) -> Option<SyntaxClass<'s>> {
|
||||||
let (_, expr) = self.classify_pos_(source, position, shift)?;
|
let (_, syntax) = self.classify_pos_(source, position, shift)?;
|
||||||
expr
|
syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Classifies the syntax under position that can be operated on by IDE
|
/// Classifies the syntax under position that can be operated on by IDE
|
||||||
|
@ -714,7 +714,7 @@ impl SharedContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type check information of a source file.
|
/// Get the type check information of a source file.
|
||||||
pub(crate) fn type_check(self: &Arc<Self>, source: &Source) -> Arc<TypeScheme> {
|
pub(crate) fn type_check(self: &Arc<Self>, source: &Source) -> Arc<TypeInfo> {
|
||||||
let mut route = TypeEnv::default();
|
let mut route = TypeEnv::default();
|
||||||
self.type_check_(source, &mut route)
|
self.type_check_(source, &mut route)
|
||||||
}
|
}
|
||||||
|
@ -724,7 +724,7 @@ impl SharedContext {
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
source: &Source,
|
source: &Source,
|
||||||
route: &mut TypeEnv,
|
route: &mut TypeEnv,
|
||||||
) -> Arc<TypeScheme> {
|
) -> Arc<TypeInfo> {
|
||||||
use crate::analysis::type_check;
|
use crate::analysis::type_check;
|
||||||
|
|
||||||
let ei = self.expr_stage(source);
|
let ei = self.expr_stage(source);
|
||||||
|
@ -787,8 +787,8 @@ impl SharedContext {
|
||||||
doc: Option<&VersionedDocument>,
|
doc: Option<&VersionedDocument>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Option<Definition> {
|
) -> Option<Definition> {
|
||||||
let expr = self.classify_span(source, span)?;
|
let syntax = self.classify_span(source, span)?;
|
||||||
definition(self, source, doc, expr)
|
definition(self, source, doc, syntax)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn def_of_decl(&self, decl: &Interned<Decl>) -> Option<Definition> {
|
pub(crate) fn def_of_decl(&self, decl: &Interned<Decl>) -> Option<Definition> {
|
||||||
|
@ -832,7 +832,7 @@ impl SharedContext {
|
||||||
analyze_signature(self, SignatureTarget::Def(source, def))
|
analyze_signature(self, SignatureTarget::Def(source, def))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn sig_of_type(self: &Arc<Self>, ti: &TypeScheme, ty: Ty) -> Option<Signature> {
|
pub(crate) fn sig_of_type(self: &Arc<Self>, ti: &TypeInfo, ty: Ty) -> Option<Signature> {
|
||||||
super::sig_of_type(self, ti, ty)
|
super::sig_of_type(self, ti, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,9 +980,9 @@ impl SharedContext {
|
||||||
fn work(&self, fid: TypstFileId) {
|
fn work(&self, fid: TypstFileId) {
|
||||||
crate::log_debug_ct!("preload package {fid:?}");
|
crate::log_debug_ct!("preload package {fid:?}");
|
||||||
let source = self.shared.source_by_id(fid).ok().unwrap();
|
let source = self.shared.source_by_id(fid).ok().unwrap();
|
||||||
let expr = self.shared.expr_stage(&source);
|
let exprs = self.shared.expr_stage(&source);
|
||||||
self.shared.type_check(&source);
|
self.shared.type_check(&source);
|
||||||
expr.imports.iter().for_each(|(fid, _)| {
|
exprs.imports.iter().for_each(|(fid, _)| {
|
||||||
if !self.analyzed.lock().insert(*fid) {
|
if !self.analyzed.lock().insert(*fid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1044,14 +1044,14 @@ impl<K, V> IncrCacheMap<K, V> {
|
||||||
let entry = global.entry(key.clone());
|
let entry = global.entry(key.clone());
|
||||||
use dashmap::mapref::entry::Entry;
|
use dashmap::mapref::entry::Entry;
|
||||||
match entry {
|
match entry {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut entry) => {
|
||||||
let (revision, _) = e.get();
|
let (revision, _) = entry.get();
|
||||||
if *revision < self.revision {
|
if *revision < self.revision {
|
||||||
e.insert((self.revision, res.clone()));
|
entry.insert((self.revision, res.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(entry) => {
|
||||||
e.insert((self.revision, res.clone()));
|
entry.insert((self.revision, res.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,7 +1146,7 @@ pub struct AnalysisLocalCaches {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ModuleAnalysisLocalCache {
|
pub struct ModuleAnalysisLocalCache {
|
||||||
expr_stage: OnceCell<Arc<ExprInfo>>,
|
expr_stage: OnceCell<Arc<ExprInfo>>,
|
||||||
type_check: OnceCell<Arc<TypeScheme>>,
|
type_check: OnceCell<Arc<TypeInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A revision-managed (per input change) cache for all level of analysis
|
/// A revision-managed (per input change) cache for all level of analysis
|
||||||
|
@ -1199,10 +1199,10 @@ impl AnalysisRevCache {
|
||||||
self.manager.find_revision(revision, |slot_base| {
|
self.manager.find_revision(revision, |slot_base| {
|
||||||
log::info!("analysis revision {} is created", revision.get());
|
log::info!("analysis revision {} is created", revision.get());
|
||||||
slot_base
|
slot_base
|
||||||
.map(|e| AnalysisRevSlot {
|
.map(|slot| AnalysisRevSlot {
|
||||||
revision: e.revision,
|
revision: slot.revision,
|
||||||
expr_stage: e.data.expr_stage.crawl(revision.get()),
|
expr_stage: slot.data.expr_stage.crawl(revision.get()),
|
||||||
type_check: e.data.type_check.crawl(revision.get()),
|
type_check: slot.data.type_check.crawl(revision.get()),
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| self.default_slot.clone())
|
.unwrap_or_else(|| self.default_slot.clone())
|
||||||
})
|
})
|
||||||
|
@ -1234,7 +1234,7 @@ impl Drop for AnalysisRevLock {
|
||||||
struct AnalysisRevSlot {
|
struct AnalysisRevSlot {
|
||||||
revision: usize,
|
revision: usize,
|
||||||
expr_stage: IncrCacheMap<u128, Arc<ExprInfo>>,
|
expr_stage: IncrCacheMap<u128, Arc<ExprInfo>>,
|
||||||
type_check: IncrCacheMap<u128, Arc<TypeScheme>>,
|
type_check: IncrCacheMap<u128, Arc<TypeInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AnalysisRevSlot {
|
impl Drop for AnalysisRevSlot {
|
||||||
|
@ -1274,7 +1274,7 @@ fn bib_info(
|
||||||
fn loc_info(bytes: Bytes) -> Option<EcoVec<(usize, String)>> {
|
fn loc_info(bytes: Bytes) -> Option<EcoVec<(usize, String)>> {
|
||||||
let mut loc = EcoVec::new();
|
let mut loc = EcoVec::new();
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for line in bytes.split(|e| *e == b'\n') {
|
for line in bytes.split(|byte| *byte == b'\n') {
|
||||||
loc.push((offset, String::from_utf8(line.to_owned()).ok()?));
|
loc.push((offset, String::from_utf8(line.to_owned()).ok()?));
|
||||||
offset += line.len() + 1;
|
offset += line.len() + 1;
|
||||||
}
|
}
|
||||||
|
@ -1327,9 +1327,9 @@ pub struct SearchCtx<'a> {
|
||||||
|
|
||||||
impl SearchCtx<'_> {
|
impl SearchCtx<'_> {
|
||||||
/// Push a file to the worklist.
|
/// Push a file to the worklist.
|
||||||
pub fn push(&mut self, id: TypstFileId) -> bool {
|
pub fn push(&mut self, fid: TypstFileId) -> bool {
|
||||||
if self.searched.insert(id) {
|
if self.searched.insert(fid) {
|
||||||
self.worklist.push(id);
|
self.worklist.push(fid);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -1337,9 +1337,9 @@ impl SearchCtx<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push the dependents of a file to the worklist.
|
/// Push the dependents of a file to the worklist.
|
||||||
pub fn push_dependents(&mut self, id: TypstFileId) {
|
pub fn push_dependents(&mut self, fid: TypstFileId) {
|
||||||
let deps = self.ctx.module_dependencies().get(&id);
|
let deps = self.ctx.module_dependencies().get(&fid);
|
||||||
let dependents = deps.map(|e| e.dependents.clone()).into_iter().flatten();
|
let dependents = deps.map(|dep| dep.dependents.clone()).into_iter().flatten();
|
||||||
for dep in dependents {
|
for dep in dependents {
|
||||||
self.push(dep);
|
self.push(dep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl LinkStrWorker {
|
||||||
SyntaxKind::Include => {
|
SyntaxKind::Include => {
|
||||||
let inc = node.cast::<ast::ModuleInclude>()?;
|
let inc = node.cast::<ast::ModuleInclude>()?;
|
||||||
let path = inc.source();
|
let path = inc.source();
|
||||||
self.analyze_path_exp(node, path);
|
self.analyze_path_expr(node, path);
|
||||||
}
|
}
|
||||||
// early exit
|
// early exit
|
||||||
k if k.is_trivia() || k.is_keyword() || k.is_error() => return Some(()),
|
k if k.is_trivia() || k.is_keyword() || k.is_error() => return Some(()),
|
||||||
|
@ -143,14 +143,14 @@ impl LinkStrWorker {
|
||||||
let arg = call.args().items().next()?;
|
let arg = call.args().items().next()?;
|
||||||
match arg {
|
match arg {
|
||||||
ast::Arg::Pos(s) if pos => {
|
ast::Arg::Pos(s) if pos => {
|
||||||
self.analyze_path_exp(node, s);
|
self.analyze_path_expr(node, s);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
for item in call.args().items() {
|
for item in call.args().items() {
|
||||||
match item {
|
match item {
|
||||||
ast::Arg::Named(named) if named.name().get().as_str() == key => {
|
ast::Arg::Named(named) if named.name().get().as_str() == key => {
|
||||||
self.analyze_path_exp(node, named.expr());
|
self.analyze_path_expr(node, named.expr());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -158,8 +158,8 @@ impl LinkStrWorker {
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyze_path_exp(&mut self, node: &LinkedNode, expr: ast::Expr) -> Option<()> {
|
fn analyze_path_expr(&mut self, node: &LinkedNode, path_expr: ast::Expr) -> Option<()> {
|
||||||
match expr {
|
match path_expr {
|
||||||
ast::Expr::Str(s) => self.analyze_path_str(node, s),
|
ast::Expr::Str(s) => self.analyze_path_str(node, s),
|
||||||
ast::Expr::Array(a) => {
|
ast::Expr::Array(a) => {
|
||||||
for item in a.items() {
|
for item in a.items() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use tinymist_derive::BindTyCtx;
|
||||||
use super::{prelude::*, DynTypeBounds, ParamAttrs, ParamTy, SharedContext};
|
use super::{prelude::*, DynTypeBounds, ParamAttrs, ParamTy, SharedContext};
|
||||||
use super::{
|
use super::{
|
||||||
ArgsTy, Sig, SigChecker, SigShape, SigSurfaceKind, SigTy, Ty, TyCtx, TyCtxMut, TypeBounds,
|
ArgsTy, Sig, SigChecker, SigShape, SigSurfaceKind, SigTy, Ty, TyCtx, TyCtxMut, TypeBounds,
|
||||||
TypeScheme, TypeVar,
|
TypeInfo, TypeVar,
|
||||||
};
|
};
|
||||||
use crate::syntax::{classify_cursor, classify_cursor_by_context, ArgClass, CursorClass};
|
use crate::syntax::{classify_cursor, classify_cursor_by_context, ArgClass, CursorClass};
|
||||||
use crate::ty::BuiltinTy;
|
use crate::ty::BuiltinTy;
|
||||||
|
@ -15,10 +15,10 @@ use crate::ty::BuiltinTy;
|
||||||
/// touching the possible related nodes.
|
/// touching the possible related nodes.
|
||||||
pub(crate) fn post_type_check(
|
pub(crate) fn post_type_check(
|
||||||
ctx: Arc<SharedContext>,
|
ctx: Arc<SharedContext>,
|
||||||
info: &TypeScheme,
|
ti: &TypeInfo,
|
||||||
node: LinkedNode,
|
node: LinkedNode,
|
||||||
) -> Option<Ty> {
|
) -> Option<Ty> {
|
||||||
let mut checker = PostTypeChecker::new(ctx, info);
|
let mut checker = PostTypeChecker::new(ctx, ti);
|
||||||
let res = checker.check(&node);
|
let res = checker.check(&node);
|
||||||
checker.simplify(&res?)
|
checker.simplify(&res?)
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,9 @@ fn check_signature<'a>(
|
||||||
|
|
||||||
pub(crate) struct PostTypeChecker<'a> {
|
pub(crate) struct PostTypeChecker<'a> {
|
||||||
ctx: Arc<SharedContext>,
|
ctx: Arc<SharedContext>,
|
||||||
pub info: &'a TypeScheme,
|
pub info: &'a TypeInfo,
|
||||||
checked: HashMap<Span, Option<Ty>>,
|
checked: HashMap<Span, Option<Ty>>,
|
||||||
locals: TypeScheme,
|
locals: TypeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyCtx for PostTypeChecker<'_> {
|
impl TyCtx for PostTypeChecker<'_> {
|
||||||
|
@ -117,7 +117,7 @@ impl TyCtx for PostTypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyCtxMut for PostTypeChecker<'_> {
|
impl TyCtxMut for PostTypeChecker<'_> {
|
||||||
type Snap = <TypeScheme as TyCtxMut>::Snap;
|
type Snap = <TypeInfo as TyCtxMut>::Snap;
|
||||||
|
|
||||||
fn start_scope(&mut self) -> Self::Snap {
|
fn start_scope(&mut self) -> Self::Snap {
|
||||||
self.locals.start_scope()
|
self.locals.start_scope()
|
||||||
|
@ -145,12 +145,12 @@ impl TyCtxMut for PostTypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostTypeChecker<'a> {
|
impl<'a> PostTypeChecker<'a> {
|
||||||
pub fn new(ctx: Arc<SharedContext>, info: &'a TypeScheme) -> Self {
|
pub fn new(ctx: Arc<SharedContext>, info: &'a TypeInfo) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
info,
|
info,
|
||||||
checked: HashMap::new(),
|
checked: HashMap::new(),
|
||||||
locals: TypeScheme::default(),
|
locals: TypeInfo::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,13 +316,13 @@ impl<'a> PostTypeChecker<'a> {
|
||||||
fn check_context(&mut self, context: &LinkedNode, node: &LinkedNode) -> Option<Ty> {
|
fn check_context(&mut self, context: &LinkedNode, node: &LinkedNode) -> Option<Ty> {
|
||||||
match context.kind() {
|
match context.kind() {
|
||||||
SyntaxKind::LetBinding => {
|
SyntaxKind::LetBinding => {
|
||||||
let p = context.cast::<ast::LetBinding>()?;
|
let let_binding = context.cast::<ast::LetBinding>()?;
|
||||||
let exp = p.init()?;
|
let let_init = let_binding.init()?;
|
||||||
if exp.span() != node.span() {
|
if let_init.span() != node.span() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match p.kind() {
|
match let_binding.kind() {
|
||||||
ast::LetBindingKind::Closure(_c) => None,
|
ast::LetBindingKind::Closure(_c) => None,
|
||||||
ast::LetBindingKind::Normal(pattern) => {
|
ast::LetBindingKind::Normal(pattern) => {
|
||||||
self.destruct_let(pattern, node.clone())
|
self.destruct_let(pattern, node.clone())
|
||||||
|
@ -413,8 +413,8 @@ fn sig_context_of(context: &LinkedNode) -> SigSurfaceKind {
|
||||||
match context.kind() {
|
match context.kind() {
|
||||||
SyntaxKind::Parenthesized => SigSurfaceKind::ArrayOrDict,
|
SyntaxKind::Parenthesized => SigSurfaceKind::ArrayOrDict,
|
||||||
SyntaxKind::Array => {
|
SyntaxKind::Array => {
|
||||||
let c = context.cast::<ast::Array>();
|
let arr = context.cast::<ast::Array>();
|
||||||
if c.is_some_and(|e| e.items().next().is_some()) {
|
if arr.is_some_and(|arr| arr.items().next().is_some()) {
|
||||||
SigSurfaceKind::Array
|
SigSurfaceKind::Array
|
||||||
} else {
|
} else {
|
||||||
SigSurfaceKind::ArrayOrDict
|
SigSurfaceKind::ArrayOrDict
|
||||||
|
|
|
@ -601,9 +601,9 @@ fn token_from_node(
|
||||||
fn token_from_ident(ei: &ExprInfo, ident: &LinkedNode, modifier: &mut ModifierSet) -> TokenType {
|
fn token_from_ident(ei: &ExprInfo, ident: &LinkedNode, modifier: &mut ModifierSet) -> TokenType {
|
||||||
let resolved = ei.resolves.get(&ident.span());
|
let resolved = ei.resolves.get(&ident.span());
|
||||||
let context = if let Some(resolved) = resolved {
|
let context = if let Some(resolved) = resolved {
|
||||||
match (&resolved.root, &resolved.val) {
|
match (&resolved.root, &resolved.term) {
|
||||||
(Some(e), t) => Some(token_from_decl_expr(e, t.as_ref(), modifier)),
|
(Some(root), term) => Some(token_from_decl_expr(root, term.as_ref(), modifier)),
|
||||||
(_, Some(t)) => Some(token_from_term(t, modifier)),
|
(_, Some(ty)) => Some(token_from_term(ty, modifier)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -710,7 +710,7 @@ fn token_from_hashtag(
|
||||||
) -> Option<TokenType> {
|
) -> Option<TokenType> {
|
||||||
get_expr_following_hashtag(hashtag)
|
get_expr_following_hashtag(hashtag)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|e| token_from_node(ei, e, modifier))
|
.and_then(|node| token_from_node(ei, node, modifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -6,7 +6,7 @@ use typst::foundations::Closure;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
prelude::*, BoundChecker, Definition, DocSource, ParamTy, SharedContext, SigTy, SigWithTy,
|
prelude::*, BoundChecker, Definition, DocSource, ParamTy, SharedContext, SigTy, SigWithTy,
|
||||||
TypeScheme, TypeVar,
|
TypeInfo, TypeVar,
|
||||||
};
|
};
|
||||||
use crate::analysis::PostTypeChecker;
|
use crate::analysis::PostTypeChecker;
|
||||||
use crate::docs::{UntypedDefDocs, UntypedSignatureDocs, UntypedVarDocs};
|
use crate::docs::{UntypedDefDocs, UntypedSignatureDocs, UntypedVarDocs};
|
||||||
|
@ -217,7 +217,7 @@ fn analyze_type_signature(
|
||||||
|
|
||||||
pub(crate) fn sig_of_type(
|
pub(crate) fn sig_of_type(
|
||||||
ctx: &Arc<SharedContext>,
|
ctx: &Arc<SharedContext>,
|
||||||
type_info: &TypeScheme,
|
type_info: &TypeInfo,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
) -> Option<Signature> {
|
) -> Option<Signature> {
|
||||||
// todo multiple sources
|
// todo multiple sources
|
||||||
|
@ -596,8 +596,8 @@ fn analyze_closure_signature(
|
||||||
|
|
||||||
for param in closure_ast.params().children() {
|
for param in closure_ast.params().children() {
|
||||||
match param {
|
match param {
|
||||||
ast::Param::Pos(e) => {
|
ast::Param::Pos(pos) => {
|
||||||
let name = format!("{}", PatternDisplay(&e));
|
let name = format!("{}", PatternDisplay(&pos));
|
||||||
add_param(Interned::new(ParamTy {
|
add_param(Interned::new(ParamTy {
|
||||||
name: name.as_str().into(),
|
name: name.as_str().into(),
|
||||||
docs: None,
|
docs: None,
|
||||||
|
@ -607,20 +607,20 @@ fn analyze_closure_signature(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
// todo: pattern
|
// todo: pattern
|
||||||
ast::Param::Named(n) => {
|
ast::Param::Named(named) => {
|
||||||
let expr = unwrap_expr(n.expr()).to_untyped().clone().into_text();
|
let default = unwrap_parens(named.expr()).to_untyped().clone().into_text();
|
||||||
add_param(Interned::new(ParamTy {
|
add_param(Interned::new(ParamTy {
|
||||||
name: n.name().get().into(),
|
name: named.name().get().into(),
|
||||||
docs: Some(eco_format!("Default value: {expr}")),
|
docs: Some(eco_format!("Default value: {default}")),
|
||||||
default: Some(expr),
|
default: Some(default),
|
||||||
ty: Ty::Any,
|
ty: Ty::Any,
|
||||||
attrs: ParamAttrs::named(),
|
attrs: ParamAttrs::named(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
ast::Param::Spread(n) => {
|
ast::Param::Spread(spread) => {
|
||||||
let ident = n.sink_ident().map(|e| e.as_str());
|
let sink = spread.sink_ident().map(|sink| sink.as_str());
|
||||||
add_param(Interned::new(ParamTy {
|
add_param(Interned::new(ParamTy {
|
||||||
name: ident.unwrap_or_default().into(),
|
name: sink.unwrap_or_default().into(),
|
||||||
docs: None,
|
docs: None,
|
||||||
default: None,
|
default: None,
|
||||||
ty: Ty::Any,
|
ty: Ty::Any,
|
||||||
|
@ -657,7 +657,7 @@ impl fmt::Display for PatternDisplay<'_> {
|
||||||
f,
|
f,
|
||||||
"{}: {}",
|
"{}: {}",
|
||||||
n.name().as_str(),
|
n.name().as_str(),
|
||||||
unwrap_expr(n.expr()).to_untyped().text()
|
unwrap_parens(n.expr()).to_untyped().text()
|
||||||
)?,
|
)?,
|
||||||
ast::DestructuringItem::Spread(s) => write!(
|
ast::DestructuringItem::Spread(s) => write!(
|
||||||
f,
|
f,
|
||||||
|
@ -673,10 +673,10 @@ impl fmt::Display for PatternDisplay<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unwrap_expr(mut e: ast::Expr) -> ast::Expr {
|
fn unwrap_parens(mut expr: ast::Expr) -> ast::Expr {
|
||||||
while let ast::Expr::Parenthesized(p) = e {
|
while let ast::Expr::Parenthesized(p) = expr {
|
||||||
e = p.expr();
|
expr = p.expr();
|
||||||
}
|
}
|
||||||
|
|
||||||
e
|
expr
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use tinymist_derive::BindTyCtx;
|
use tinymist_derive::BindTyCtx;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
prelude::*, BuiltinTy, DynTypeBounds, FlowVarKind, SharedContext, TyCtxMut, TypeScheme,
|
prelude::*, BuiltinTy, DynTypeBounds, FlowVarKind, SharedContext, TyCtxMut, TypeInfo, TypeVar,
|
||||||
TypeVar, TypeVarBounds,
|
TypeVarBounds,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
syntax::{Decl, DeclExpr, Expr, ExprInfo, UnaryOp},
|
syntax::{Decl, DeclExpr, Expr, ExprInfo, UnaryOp},
|
||||||
|
@ -26,7 +26,7 @@ pub(crate) use select::*;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TypeEnv {
|
pub struct TypeEnv {
|
||||||
visiting: FxHashMap<TypstFileId, Arc<TypeScheme>>,
|
visiting: FxHashMap<TypstFileId, Arc<TypeInfo>>,
|
||||||
exprs: FxHashMap<TypstFileId, Option<Arc<ExprInfo>>>,
|
exprs: FxHashMap<TypstFileId, Option<Arc<ExprInfo>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ pub(crate) fn type_check(
|
||||||
ctx: Arc<SharedContext>,
|
ctx: Arc<SharedContext>,
|
||||||
ei: Arc<ExprInfo>,
|
ei: Arc<ExprInfo>,
|
||||||
env: &mut TypeEnv,
|
env: &mut TypeEnv,
|
||||||
) -> Arc<TypeScheme> {
|
) -> Arc<TypeInfo> {
|
||||||
let mut info = TypeScheme::default();
|
let mut info = TypeInfo::default();
|
||||||
info.valid = true;
|
info.valid = true;
|
||||||
info.fid = Some(ei.fid);
|
info.fid = Some(ei.fid);
|
||||||
info.revision = ei.revision;
|
info.revision = ei.revision;
|
||||||
|
|
||||||
env.visiting.insert(ei.fid, Arc::new(TypeScheme::default()));
|
env.visiting.insert(ei.fid, Arc::new(TypeInfo::default()));
|
||||||
|
|
||||||
// Retrieve expression information for the source.
|
// Retrieve expression information for the source.
|
||||||
let root = ei.root.clone();
|
let root = ei.root.clone();
|
||||||
|
@ -86,7 +86,7 @@ pub(crate) struct TypeChecker<'a> {
|
||||||
ctx: Arc<SharedContext>,
|
ctx: Arc<SharedContext>,
|
||||||
ei: Arc<ExprInfo>,
|
ei: Arc<ExprInfo>,
|
||||||
|
|
||||||
info: TypeScheme,
|
info: TypeInfo,
|
||||||
module_exports: FxHashMap<(TypstFileId, Interned<str>), OnceLock<Option<Ty>>>,
|
module_exports: FxHashMap<(TypstFileId, Interned<str>), OnceLock<Option<Ty>>>,
|
||||||
|
|
||||||
call_cache: FxHashSet<CallCacheDesc>,
|
call_cache: FxHashSet<CallCacheDesc>,
|
||||||
|
@ -105,7 +105,7 @@ impl TyCtx for TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyCtxMut for TypeChecker<'_> {
|
impl TyCtxMut for TypeChecker<'_> {
|
||||||
type Snap = <TypeScheme as TyCtxMut>::Snap;
|
type Snap = <TypeInfo as TyCtxMut>::Snap;
|
||||||
|
|
||||||
fn start_scope(&mut self) -> Self::Snap {
|
fn start_scope(&mut self) -> Self::Snap {
|
||||||
self.info.start_scope()
|
self.info.start_scope()
|
||||||
|
@ -147,8 +147,8 @@ impl TyCtxMut for TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeChecker<'_> {
|
impl TypeChecker<'_> {
|
||||||
fn check(&mut self, root: &Expr) -> Ty {
|
fn check(&mut self, expr: &Expr) -> Ty {
|
||||||
self.check_syntax(root).unwrap_or(Ty::undef())
|
self.check_syntax(expr).unwrap_or(Ty::undef())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_doc_vars(
|
fn copy_doc_vars(
|
||||||
|
@ -221,7 +221,7 @@ impl TypeChecker<'_> {
|
||||||
// self.info.witness_at_least(s, w.clone());
|
// self.info.witness_at_least(s, w.clone());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
TypeScheme::witness_(s, Ty::Var(var.clone()), &mut self.info.mapping);
|
TypeInfo::witness_(s, Ty::Var(var.clone()), &mut self.info.mapping);
|
||||||
}
|
}
|
||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
@ -300,14 +300,14 @@ impl TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Ty::Union(v), rhs) => {
|
(Ty::Union(types), rhs) => {
|
||||||
for e in v.iter() {
|
for ty in types.iter() {
|
||||||
self.constrain(e, rhs);
|
self.constrain(ty, rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(lhs, Ty::Union(v)) => {
|
(lhs, Ty::Union(types)) => {
|
||||||
for e in v.iter() {
|
for ty in types.iter() {
|
||||||
self.constrain(lhs, e);
|
self.constrain(lhs, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(lhs, Ty::Builtin(BuiltinTy::Stroke)) => {
|
(lhs, Ty::Builtin(BuiltinTy::Stroke)) => {
|
||||||
|
@ -393,7 +393,7 @@ impl TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
(Ty::Value(lhs), rhs) => {
|
(Ty::Value(lhs), rhs) => {
|
||||||
crate::log_debug_ct!("constrain value {lhs:?} ⪯ {rhs:?}");
|
crate::log_debug_ct!("constrain value {lhs:?} ⪯ {rhs:?}");
|
||||||
let _ = TypeScheme::witness_at_most;
|
let _ = TypeInfo::witness_at_most;
|
||||||
// if !lhs.1.is_detached() {
|
// if !lhs.1.is_detached() {
|
||||||
// self.info.witness_at_most(lhs.1, rhs.clone());
|
// self.info.witness_at_most(lhs.1, rhs.clone());
|
||||||
// }
|
// }
|
||||||
|
@ -557,15 +557,15 @@ impl Joiner {
|
||||||
(Ty::Builtin(BuiltinTy::Space | BuiltinTy::None), _) => {}
|
(Ty::Builtin(BuiltinTy::Space | BuiltinTy::None), _) => {}
|
||||||
(Ty::Builtin(BuiltinTy::Clause | BuiltinTy::FlowNone), _) => {}
|
(Ty::Builtin(BuiltinTy::Clause | BuiltinTy::FlowNone), _) => {}
|
||||||
(Ty::Any, _) | (_, Ty::Any) => {}
|
(Ty::Any, _) | (_, Ty::Any) => {}
|
||||||
(Ty::Var(v), _) => self.possibles.push(Ty::Var(v)),
|
(Ty::Var(var), _) => self.possibles.push(Ty::Var(var)),
|
||||||
// todo: check possibles
|
// todo: check possibles
|
||||||
(Ty::Array(e), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Array(e),
|
(Ty::Array(arr), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Array(arr),
|
||||||
(Ty::Array(..), _) => self.definite = Ty::undef(),
|
(Ty::Array(..), _) => self.definite = Ty::undef(),
|
||||||
(Ty::Tuple(e), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Tuple(e),
|
(Ty::Tuple(elems), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Tuple(elems),
|
||||||
(Ty::Tuple(..), _) => self.definite = Ty::undef(),
|
(Ty::Tuple(..), _) => self.definite = Ty::undef(),
|
||||||
// todo: mystery flow none
|
// todo: mystery flow none
|
||||||
// todo: possible some style (auto)
|
// todo: possible some style (auto)
|
||||||
(Ty::Builtin(b), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Builtin(b),
|
(Ty::Builtin(ty), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Builtin(ty),
|
||||||
(Ty::Builtin(..), _) => self.definite = Ty::undef(),
|
(Ty::Builtin(..), _) => self.definite = Ty::undef(),
|
||||||
// todo: value join
|
// todo: value join
|
||||||
(Ty::Value(v), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Value(v),
|
(Ty::Value(v), Ty::Builtin(BuiltinTy::None)) => self.definite = Ty::Value(v),
|
||||||
|
|
|
@ -10,11 +10,11 @@ static EMPTY_DOCSTRING: LazyLock<DocString> = LazyLock::new(DocString::default);
|
||||||
static EMPTY_VAR_DOC: LazyLock<VarDoc> = LazyLock::new(VarDoc::default);
|
static EMPTY_VAR_DOC: LazyLock<VarDoc> = LazyLock::new(VarDoc::default);
|
||||||
|
|
||||||
impl TypeChecker<'_> {
|
impl TypeChecker<'_> {
|
||||||
pub(crate) fn check_syntax(&mut self, root: &Expr) -> Option<Ty> {
|
pub(crate) fn check_syntax(&mut self, expr: &Expr) -> Option<Ty> {
|
||||||
Some(match root {
|
Some(match expr {
|
||||||
Expr::Block(seq) => self.check_block(seq),
|
Expr::Block(exprs) => self.check_block(exprs),
|
||||||
Expr::Array(array) => self.check_array(array),
|
Expr::Array(elems) => self.check_array(elems),
|
||||||
Expr::Dict(dict) => self.check_dict(dict),
|
Expr::Dict(elems) => self.check_dict(elems),
|
||||||
Expr::Args(args) => self.check_args(args),
|
Expr::Args(args) => self.check_args(args),
|
||||||
// todo: check pattern correctly
|
// todo: check pattern correctly
|
||||||
Expr::Pattern(pattern) => self.check_pattern_exp(pattern),
|
Expr::Pattern(pattern) => self.check_pattern_exp(pattern),
|
||||||
|
@ -41,20 +41,20 @@ impl TypeChecker<'_> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_block(&mut self, seq: &Interned<Vec<Expr>>) -> Ty {
|
fn check_block(&mut self, exprs: &Interned<Vec<Expr>>) -> Ty {
|
||||||
let mut joiner = Joiner::default();
|
let mut joiner = Joiner::default();
|
||||||
|
|
||||||
for child in seq.iter() {
|
for child in exprs.iter() {
|
||||||
joiner.join(self.check(child));
|
joiner.join(self.check(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
joiner.finalize()
|
joiner.finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_array(&mut self, array: &Interned<Vec<ArgExpr>>) -> Ty {
|
fn check_array(&mut self, elems: &Interned<Vec<ArgExpr>>) -> Ty {
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
|
|
||||||
for elem in array.iter() {
|
for elem in elems.iter() {
|
||||||
match elem {
|
match elem {
|
||||||
ArgExpr::Pos(p) => {
|
ArgExpr::Pos(p) => {
|
||||||
elements.push(self.check(p));
|
elements.push(self.check(p));
|
||||||
|
@ -69,10 +69,10 @@ impl TypeChecker<'_> {
|
||||||
Ty::Tuple(elements.into())
|
Ty::Tuple(elements.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dict(&mut self, dict: &Interned<Vec<ArgExpr>>) -> Ty {
|
fn check_dict(&mut self, elems: &Interned<Vec<ArgExpr>>) -> Ty {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
|
|
||||||
for elem in dict.iter() {
|
for elem in elems.iter() {
|
||||||
match elem {
|
match elem {
|
||||||
ArgExpr::Named(n) => {
|
ArgExpr::Named(n) => {
|
||||||
let (name, value) = n.as_ref();
|
let (name, value) = n.as_ref();
|
||||||
|
@ -122,19 +122,19 @@ impl TypeChecker<'_> {
|
||||||
Ty::Args(args.into())
|
Ty::Args(args.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pattern_exp(&mut self, pattern: &Interned<Pattern>) -> Ty {
|
fn check_pattern_exp(&mut self, pat: &Interned<Pattern>) -> Ty {
|
||||||
self.check_pattern(None, pattern, &EMPTY_DOCSTRING)
|
self.check_pattern(None, pat, &EMPTY_DOCSTRING)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pattern(
|
fn check_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Option<&Interned<Decl>>,
|
base: Option<&Interned<Decl>>,
|
||||||
pattern: &Interned<Pattern>,
|
pat: &Interned<Pattern>,
|
||||||
docstring: &DocString,
|
docstring: &DocString,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
// todo: recursive doc constructing
|
// todo: recursive doc constructing
|
||||||
match pattern.as_ref() {
|
match pat.as_ref() {
|
||||||
Pattern::Expr(e) => self.check(e),
|
Pattern::Expr(expr) => self.check(expr),
|
||||||
Pattern::Simple(decl) => {
|
Pattern::Simple(decl) => {
|
||||||
let ret = self.check_decl(decl);
|
let ret = self.check_decl(decl);
|
||||||
let var_doc = docstring.as_var();
|
let var_doc = docstring.as_var();
|
||||||
|
@ -155,28 +155,28 @@ impl TypeChecker<'_> {
|
||||||
fn check_pattern_sig(
|
fn check_pattern_sig(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Option<&Interned<Decl>>,
|
base: Option<&Interned<Decl>>,
|
||||||
pattern: &PatternSig,
|
pat: &PatternSig,
|
||||||
docstring: &DocString,
|
docstring: &DocString,
|
||||||
) -> (PatternTy, BTreeMap<Interned<str>, Ty>) {
|
) -> (PatternTy, BTreeMap<Interned<str>, Ty>) {
|
||||||
let mut pos_docs = vec![];
|
let mut pos_docs = vec![];
|
||||||
let mut named_docs = BTreeMap::new();
|
let mut named_docs = BTreeMap::new();
|
||||||
let mut rest_docs = None;
|
let mut rest_docs = None;
|
||||||
|
|
||||||
let mut pos = vec![];
|
let mut pos_all = vec![];
|
||||||
let mut named = BTreeMap::new();
|
let mut named_all = BTreeMap::new();
|
||||||
let mut defaults = BTreeMap::new();
|
let mut defaults = BTreeMap::new();
|
||||||
let mut rest = None;
|
let mut spread_right = None;
|
||||||
|
|
||||||
// todo: combine with check_pattern
|
// todo: combine with check_pattern
|
||||||
for exp in pattern.pos.iter() {
|
for pos_expr in pat.pos.iter() {
|
||||||
// pos.push(self.check_pattern(pattern, Ty::Any, docstring, root.clone()));
|
// pos.push(self.check_pattern(pattern, Ty::Any, docstring, root.clone()));
|
||||||
let res = self.check_pattern_exp(exp);
|
let pos_ty = self.check_pattern_exp(pos_expr);
|
||||||
if let Pattern::Simple(ident) = exp.as_ref() {
|
if let Pattern::Simple(ident) = pos_expr.as_ref() {
|
||||||
let name = ident.name().clone();
|
let name = ident.name().clone();
|
||||||
|
|
||||||
let param_doc = docstring.get_var(&name).unwrap_or(&EMPTY_VAR_DOC);
|
let param_doc = docstring.get_var(&name).unwrap_or(&EMPTY_VAR_DOC);
|
||||||
if let Some(annotated) = docstring.var_ty(&name) {
|
if let Some(annotated) = docstring.var_ty(&name) {
|
||||||
self.constrain(&res, annotated);
|
self.constrain(&pos_ty, annotated);
|
||||||
}
|
}
|
||||||
pos_docs.push(TypelessParamDocs {
|
pos_docs.push(TypelessParamDocs {
|
||||||
name,
|
name,
|
||||||
|
@ -194,22 +194,22 @@ impl TypeChecker<'_> {
|
||||||
attrs: ParamAttrs::positional(),
|
attrs: ParamAttrs::positional(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pos.push(res);
|
pos_all.push(pos_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (decl, exp) in pattern.named.iter() {
|
for (decl, named_expr) in pat.named.iter() {
|
||||||
let name = decl.name().clone();
|
let name = decl.name().clone();
|
||||||
let res = self.check_pattern_exp(exp);
|
let named_ty = self.check_pattern_exp(named_expr);
|
||||||
let var = self.get_var(decl);
|
let var = self.get_var(decl);
|
||||||
let v = Ty::Var(var.clone());
|
let var_ty = Ty::Var(var.clone());
|
||||||
if let Some(annotated) = docstring.var_ty(&name) {
|
if let Some(annotated) = docstring.var_ty(&name) {
|
||||||
self.constrain(&v, annotated);
|
self.constrain(&var_ty, annotated);
|
||||||
}
|
}
|
||||||
// todo: this is less efficient than v.lbs.push(exp), we may have some idea to
|
// todo: this is less efficient than v.lbs.push(exp), we may have some idea to
|
||||||
// optimize it, so I put a todo here.
|
// optimize it, so I put a todo here.
|
||||||
self.constrain(&res, &v);
|
self.constrain(&named_ty, &var_ty);
|
||||||
named.insert(name.clone(), v);
|
named_all.insert(name.clone(), var_ty);
|
||||||
defaults.insert(name.clone(), res);
|
defaults.insert(name.clone(), named_ty);
|
||||||
|
|
||||||
let param_doc = docstring.get_var(&name).unwrap_or(&EMPTY_VAR_DOC);
|
let param_doc = docstring.get_var(&name).unwrap_or(&EMPTY_VAR_DOC);
|
||||||
named_docs.insert(
|
named_docs.insert(
|
||||||
|
@ -218,7 +218,7 @@ impl TypeChecker<'_> {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
docs: param_doc.docs.clone(),
|
docs: param_doc.docs.clone(),
|
||||||
cano_type: (),
|
cano_type: (),
|
||||||
default: Some(exp.repr()),
|
default: Some(named_expr.repr()),
|
||||||
attrs: ParamAttrs::named(),
|
attrs: ParamAttrs::named(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -228,7 +228,7 @@ impl TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: spread left/right
|
// todo: spread left/right
|
||||||
if let Some((decl, _exp)) = &pattern.spread_right {
|
if let Some((decl, _spread_expr)) = &pat.spread_right {
|
||||||
let var = self.get_var(decl);
|
let var = self.get_var(decl);
|
||||||
let name = var.name.clone();
|
let name = var.name.clone();
|
||||||
let param_doc = docstring
|
let param_doc = docstring
|
||||||
|
@ -238,13 +238,13 @@ impl TypeChecker<'_> {
|
||||||
.var_docs
|
.var_docs
|
||||||
.insert(decl.clone(), param_doc.to_untyped());
|
.insert(decl.clone(), param_doc.to_untyped());
|
||||||
|
|
||||||
let exp = Ty::Builtin(BuiltinTy::Args);
|
let term = Ty::Builtin(BuiltinTy::Args);
|
||||||
let v = Ty::Var(var);
|
let var_ty = Ty::Var(var);
|
||||||
if let Some(annotated) = docstring.var_ty(&name) {
|
if let Some(annotated) = docstring.var_ty(&name) {
|
||||||
self.constrain(&v, annotated);
|
self.constrain(&var_ty, annotated);
|
||||||
}
|
}
|
||||||
self.constrain(&exp, &v);
|
self.constrain(&term, &var_ty);
|
||||||
rest = Some(v);
|
spread_right = Some(var_ty);
|
||||||
|
|
||||||
rest_docs = Some(TypelessParamDocs {
|
rest_docs = Some(TypelessParamDocs {
|
||||||
name,
|
name,
|
||||||
|
@ -256,7 +256,7 @@ impl TypeChecker<'_> {
|
||||||
// todo: ..(args)
|
// todo: ..(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
let named: Vec<(Interned<str>, Ty)> = named.into_iter().collect();
|
let named: Vec<(Interned<str>, Ty)> = named_all.into_iter().collect();
|
||||||
|
|
||||||
if let Some(base) = base {
|
if let Some(base) = base {
|
||||||
self.info.var_docs.insert(
|
self.info.var_docs.insert(
|
||||||
|
@ -273,7 +273,7 @@ impl TypeChecker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
PatternTy::new(pos.into_iter(), named, None, rest, None),
|
PatternTy::new(pos_all.into_iter(), named, None, spread_right, None),
|
||||||
defaults,
|
defaults,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@ impl TypeChecker<'_> {
|
||||||
let s = r.decl.span();
|
let s = r.decl.span();
|
||||||
let s = (!s.is_detached()).then_some(s);
|
let s = (!s.is_detached()).then_some(s);
|
||||||
let of = r.root.as_ref().map(|of| self.check(of));
|
let of = r.root.as_ref().map(|of| self.check(of));
|
||||||
let of = of.or_else(|| r.val.clone());
|
let of = of.or_else(|| r.term.clone());
|
||||||
if let Some((s, of)) = s.zip(of.as_ref()) {
|
if let Some((s, of)) = s.zip(of.as_ref()) {
|
||||||
self.info.witness_at_most(s, of.clone());
|
self.info.witness_at_most(s, of.clone());
|
||||||
}
|
}
|
||||||
|
@ -536,7 +536,7 @@ impl TypeChecker<'_> {
|
||||||
let ty = if decl.is_def() {
|
let ty = if decl.is_def() {
|
||||||
Some(Ty::Builtin(BuiltinTy::Module(decl.clone())))
|
Some(Ty::Builtin(BuiltinTy::Module(decl.clone())))
|
||||||
} else {
|
} else {
|
||||||
self.ei.get_def(decl).map(|e| self.check(&e))
|
self.ei.get_def(decl).map(|expr| self.check(&expr))
|
||||||
};
|
};
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = ty {
|
||||||
self.constrain(&v, &ty);
|
self.constrain(&v, &ty);
|
||||||
|
|
|
@ -137,8 +137,8 @@ impl StatefulRequest for CompletionRequest {
|
||||||
|
|
||||||
// Exclude it self from auto completion
|
// Exclude it self from auto completion
|
||||||
// e.g. `#let x = (1.);`
|
// e.g. `#let x = (1.);`
|
||||||
let self_ty = cc_ctx.leaf.cast::<ast::Expr>().and_then(|exp| {
|
let self_ty = cc_ctx.leaf.cast::<ast::Expr>().and_then(|leaf| {
|
||||||
let v = cc_ctx.ctx.mini_eval(exp)?;
|
let v = cc_ctx.ctx.mini_eval(leaf)?;
|
||||||
Some(Ty::Value(InsTy::new(v)))
|
Some(Ty::Value(InsTy::new(v)))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -227,10 +227,10 @@ impl StatefulRequest for CompletionRequest {
|
||||||
detail: typst_completion.detail.as_ref().map(String::from),
|
detail: typst_completion.detail.as_ref().map(String::from),
|
||||||
sort_text: typst_completion.sort_text.as_ref().map(String::from),
|
sort_text: typst_completion.sort_text.as_ref().map(String::from),
|
||||||
filter_text: typst_completion.filter_text.as_ref().map(String::from),
|
filter_text: typst_completion.filter_text.as_ref().map(String::from),
|
||||||
label_details: typst_completion.label_detail.as_ref().map(|e| {
|
label_details: typst_completion.label_detail.as_ref().map(|desc| {
|
||||||
CompletionItemLabelDetails {
|
CompletionItemLabelDetails {
|
||||||
detail: None,
|
detail: None,
|
||||||
description: Some(e.to_string()),
|
description: Some(desc.to_string()),
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
text_edit: Some(text_edit),
|
text_edit: Some(text_edit),
|
||||||
|
|
|
@ -63,12 +63,12 @@ where
|
||||||
.get("negative")
|
.get("negative")
|
||||||
.ok_or_else(|| serde::de::Error::custom("missing field `negative`"))?;
|
.ok_or_else(|| serde::de::Error::custom("missing field `negative`"))?;
|
||||||
let negative = serde_json::from_value(negative.clone())
|
let negative = serde_json::from_value(negative.clone())
|
||||||
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
|
.map_err(|err| serde::de::Error::custom(err.to_string()))?;
|
||||||
Ok(ContextSelector::Negative(negative))
|
Ok(ContextSelector::Negative(negative))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let value = serde_json::from_value(value)
|
let value = serde_json::from_value(value)
|
||||||
.map_err(|e| serde::de::Error::custom(e.to_string()))?;
|
.map_err(|err| serde::de::Error::custom(err.to_string()))?;
|
||||||
Ok(ContextSelector::Positive(Some(value)))
|
Ok(ContextSelector::Positive(Some(value)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub(crate) fn convert_docs(ctx: &SharedContext, content: &str) -> StrResult<EcoS
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.convert()
|
.convert()
|
||||||
.map_err(|e| eco_format!("failed to convert to markdown: {e}"))?;
|
.map_err(|err| eco_format!("failed to convert to markdown: {err}"))?;
|
||||||
|
|
||||||
Ok(conv.replace("```example", "```typ"))
|
Ok(conv.replace("```example", "```typ"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,7 @@ impl ScanDefCtx<'_> {
|
||||||
let mut head = DefInfo {
|
let mut head = DefInfo {
|
||||||
name: key.to_string().into(),
|
name: key.to_string().into(),
|
||||||
kind: decl.kind(),
|
kind: decl.kind(),
|
||||||
constant: expr.map(|e| e.repr()),
|
constant: expr.map(|expr| expr.repr()),
|
||||||
docs,
|
docs,
|
||||||
parsed_docs: def_docs,
|
parsed_docs: def_docs,
|
||||||
decl: Some(decl.clone()),
|
decl: Some(decl.clone()),
|
||||||
|
@ -223,7 +223,7 @@ impl ScanDefCtx<'_> {
|
||||||
if let Some((span, mod_fid)) = head.decl.as_ref().and_then(|d| d.file_id()).zip(site) {
|
if let Some((span, mod_fid)) = head.decl.as_ref().and_then(|d| d.file_id()).zip(site) {
|
||||||
if span != *mod_fid {
|
if span != *mod_fid {
|
||||||
head.is_external = true;
|
head.is_external = true;
|
||||||
head.oneliner = head.docs.as_deref().map(oneliner).map(|e| e.to_owned());
|
head.oneliner = head.docs.map(|docs| oneliner(&docs).to_owned());
|
||||||
head.docs = None;
|
head.docs = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,11 +110,11 @@ pub fn package_docs(ctx: &mut LocalContext, spec: &PackageInfo) -> StrResult<Str
|
||||||
for mut child in children {
|
for mut child in children {
|
||||||
let span = child.decl.as_ref().map(|d| d.span());
|
let span = child.decl.as_ref().map(|d| d.span());
|
||||||
let fid_range = span.and_then(|v| {
|
let fid_range = span.and_then(|v| {
|
||||||
v.id().and_then(|e| {
|
v.id().and_then(|fid| {
|
||||||
let fid = file_ids.insert_full(e).0;
|
let allocated = file_ids.insert_full(fid).0;
|
||||||
let src = ctx.source_by_id(e).ok()?;
|
let src = ctx.source_by_id(fid).ok()?;
|
||||||
let rng = src.range(v)?;
|
let rng = src.range(v)?;
|
||||||
Some((fid, rng.start, rng.end))
|
Some((allocated, rng.start, rng.end))
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let child_fid = child.decl.as_ref().and_then(|d| d.file_id());
|
let child_fid = child.decl.as_ref().and_then(|d| d.file_id());
|
||||||
|
@ -258,8 +258,8 @@ pub fn package_docs(ctx: &mut LocalContext, spec: &PackageInfo) -> StrResult<Str
|
||||||
let err = jbase64(&res);
|
let err = jbase64(&res);
|
||||||
let _ = writeln!(md, "<!-- begin:errors {err} -->");
|
let _ = writeln!(md, "<!-- begin:errors {err} -->");
|
||||||
let _ = writeln!(md, "## Errors");
|
let _ = writeln!(md, "## Errors");
|
||||||
for e in res.errors {
|
for errs in res.errors {
|
||||||
let _ = writeln!(md, "- {e}");
|
let _ = writeln!(md, "- {errs}");
|
||||||
}
|
}
|
||||||
let _ = writeln!(md, "<!-- end:errors -->");
|
let _ = writeln!(md, "<!-- end:errors -->");
|
||||||
|
|
||||||
|
@ -267,22 +267,24 @@ pub fn package_docs(ctx: &mut LocalContext, spec: &PackageInfo) -> StrResult<Str
|
||||||
|
|
||||||
let files = file_ids
|
let files = file_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| {
|
.map(|fid| {
|
||||||
let pkg = e.package().map(|e| packages.insert_full(e.clone()).0);
|
let pkg = fid
|
||||||
|
.package()
|
||||||
|
.map(|spec| packages.insert_full(spec.clone()).0);
|
||||||
|
|
||||||
FileMeta {
|
FileMeta {
|
||||||
package: pkg,
|
package: pkg,
|
||||||
path: e.vpath().as_rootless_path().to_owned(),
|
path: fid.vpath().as_rootless_path().to_owned(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let packages = packages
|
let packages = packages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| PackageMeta {
|
.map(|spec| PackageMeta {
|
||||||
namespace: e.namespace.clone(),
|
namespace: spec.namespace.clone(),
|
||||||
name: e.name.clone(),
|
name: spec.name.clone(),
|
||||||
version: e.version.to_string(),
|
version: spec.version.to_string(),
|
||||||
manifest: None,
|
manifest: None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -246,7 +246,7 @@ impl DocumentMetricsWorker<'_> {
|
||||||
full_name: font.find_name(FULL_NAME),
|
full_name: font.find_name(FULL_NAME),
|
||||||
family: font.find_name(FAMILY),
|
family: font.find_name(FAMILY),
|
||||||
fixed_family: Some(info.family.clone()),
|
fixed_family: Some(info.family.clone()),
|
||||||
source: extra.map(|e| self.internal_source(e)),
|
source: extra.map(|source| self.internal_source(source)),
|
||||||
index: Some(font.index()),
|
index: Some(font.index()),
|
||||||
uses_scale: Some(font_info_value.uses),
|
uses_scale: Some(font_info_value.uses),
|
||||||
uses: None,
|
uses: None,
|
||||||
|
|
|
@ -30,37 +30,36 @@ impl SyntaxRequest for DocumentSymbolRequest {
|
||||||
source: &Source,
|
source: &Source,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
) -> Option<Self::Response> {
|
) -> Option<Self::Response> {
|
||||||
let symbols = get_lexical_hierarchy(source.clone(), LexicalScopeKind::Symbol)?;
|
let hierarchy = get_lexical_hierarchy(source, LexicalScopeKind::Symbol)?;
|
||||||
|
let symbols = symbols_in_hierarchy(&hierarchy, source, position_encoding);
|
||||||
let symbols = filter_document_symbols(&symbols, source, position_encoding);
|
|
||||||
Some(DocumentSymbolResponse::Nested(symbols))
|
Some(DocumentSymbolResponse::Nested(symbols))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn filter_document_symbols(
|
fn symbols_in_hierarchy(
|
||||||
symbols: &[LexicalHierarchy],
|
hierarchy: &[LexicalHierarchy],
|
||||||
source: &Source,
|
source: &Source,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
) -> Vec<DocumentSymbol> {
|
) -> Vec<DocumentSymbol> {
|
||||||
symbols
|
hierarchy
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|hierarchy| {
|
||||||
let rng = typst_to_lsp::range(e.info.range.clone(), source, position_encoding);
|
let range =
|
||||||
|
typst_to_lsp::range(hierarchy.info.range.clone(), source, position_encoding);
|
||||||
|
|
||||||
DocumentSymbol {
|
DocumentSymbol {
|
||||||
name: e.info.name.to_string(),
|
name: hierarchy.info.name.to_string(),
|
||||||
detail: None,
|
detail: None,
|
||||||
kind: e.info.kind.clone().try_into().unwrap(),
|
kind: hierarchy.info.kind.clone().try_into().unwrap(),
|
||||||
tags: None,
|
tags: None,
|
||||||
deprecated: None,
|
deprecated: None,
|
||||||
range: rng,
|
range,
|
||||||
selection_range: rng,
|
selection_range: range,
|
||||||
// .raw_range,
|
children: hierarchy
|
||||||
children: e
|
|
||||||
.children
|
.children
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ch| filter_document_symbols(ch, source, position_encoding)),
|
.map(|ch| symbols_in_hierarchy(ch, source, position_encoding)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
) -> Option<Self::Response> {
|
) -> Option<Self::Response> {
|
||||||
let line_folding_only = self.line_folding_only;
|
let line_folding_only = self.line_folding_only;
|
||||||
|
|
||||||
let symbols = get_lexical_hierarchy(source.clone(), LexicalScopeKind::Braced)?;
|
let hierarchy = get_lexical_hierarchy(source, LexicalScopeKind::Braced)?;
|
||||||
|
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
let LspPosition { line, character } =
|
let LspPosition { line, character } =
|
||||||
|
@ -41,7 +41,7 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
let loc = (line, Some(character));
|
let loc = (line, Some(character));
|
||||||
|
|
||||||
calc_folding_range(
|
calc_folding_range(
|
||||||
&symbols,
|
&hierarchy,
|
||||||
source,
|
source,
|
||||||
position_encoding,
|
position_encoding,
|
||||||
loc,
|
loc,
|
||||||
|
@ -83,9 +83,7 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
results.reverse();
|
results.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if false {
|
crate::log_debug_ct!("FoldingRangeRequest(line_folding_only={line_folding_only}) symbols: {hierarchy:#?} results: {results:#?}");
|
||||||
log::trace!("FoldingRangeRequest(line_folding_only={line_folding_only}) symbols: {symbols:#?} results: {results:#?}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(results)
|
Some(results)
|
||||||
}
|
}
|
||||||
|
@ -94,30 +92,30 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
type LoC = (u32, Option<u32>);
|
type LoC = (u32, Option<u32>);
|
||||||
|
|
||||||
fn calc_folding_range(
|
fn calc_folding_range(
|
||||||
symbols: &[LexicalHierarchy],
|
hierarchy: &[LexicalHierarchy],
|
||||||
source: &Source,
|
source: &Source,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
parent_last_loc: LoC,
|
parent_last_loc: LoC,
|
||||||
last_loc: LoC,
|
last_loc: LoC,
|
||||||
is_last_range: bool,
|
is_last_range: bool,
|
||||||
ranges: &mut Vec<FoldingRange>,
|
folding_ranges: &mut Vec<FoldingRange>,
|
||||||
) {
|
) {
|
||||||
for (i, e) in symbols.iter().enumerate() {
|
for (idx, child) in hierarchy.iter().enumerate() {
|
||||||
let rng = typst_to_lsp::range(e.info.range.clone(), source, position_encoding);
|
let range = typst_to_lsp::range(child.info.range.clone(), source, position_encoding);
|
||||||
let is_not_last_range = i + 1 < symbols.len();
|
let is_not_last_range = idx + 1 < hierarchy.len();
|
||||||
let is_not_final_last_range = !is_last_range || is_not_last_range;
|
let is_not_final_last_range = !is_last_range || is_not_last_range;
|
||||||
|
|
||||||
let mut range = FoldingRange {
|
let mut folding_range = FoldingRange {
|
||||||
start_line: rng.start.line,
|
start_line: range.start.line,
|
||||||
start_character: Some(rng.start.character),
|
start_character: Some(range.start.character),
|
||||||
end_line: rng.end.line,
|
end_line: range.end.line,
|
||||||
end_character: Some(rng.end.character),
|
end_character: Some(range.end.character),
|
||||||
kind: None,
|
kind: None,
|
||||||
collapsed_text: Some(e.info.name.to_string()),
|
collapsed_text: Some(child.info.name.to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_start = if is_not_last_range {
|
let next_start = if is_not_last_range {
|
||||||
let next = &symbols[i + 1];
|
let next = &hierarchy[idx + 1];
|
||||||
let next_rng = typst_to_lsp::range(next.info.range.clone(), source, position_encoding);
|
let next_rng = typst_to_lsp::range(next.info.range.clone(), source, position_encoding);
|
||||||
(next_rng.start.line, Some(next_rng.start.character))
|
(next_rng.start.line, Some(next_rng.start.character))
|
||||||
} else if is_not_final_last_range {
|
} else if is_not_final_last_range {
|
||||||
|
@ -126,17 +124,17 @@ fn calc_folding_range(
|
||||||
last_loc
|
last_loc
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches!(e.info.kind, LexicalKind::Heading(..)) {
|
if matches!(child.info.kind, LexicalKind::Heading(..)) {
|
||||||
range.end_line = range.end_line.max(if is_not_last_range {
|
folding_range.end_line = folding_range.end_line.max(if is_not_last_range {
|
||||||
next_start.0.saturating_sub(1)
|
next_start.0.saturating_sub(1)
|
||||||
} else {
|
} else {
|
||||||
next_start.0
|
next_start.0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ch) = &e.children {
|
if let Some(ch) = &child.children {
|
||||||
let parent_last_loc = if is_not_last_range {
|
let parent_last_loc = if is_not_last_range {
|
||||||
(rng.end.line, Some(rng.end.character))
|
(range.end.line, Some(range.end.character))
|
||||||
} else {
|
} else {
|
||||||
parent_last_loc
|
parent_last_loc
|
||||||
};
|
};
|
||||||
|
@ -148,11 +146,11 @@ fn calc_folding_range(
|
||||||
parent_last_loc,
|
parent_last_loc,
|
||||||
last_loc,
|
last_loc,
|
||||||
!is_not_final_last_range,
|
!is_not_final_last_range,
|
||||||
ranges,
|
folding_ranges,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ranges.push(range);
|
folding_ranges.push(folding_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl StatefulRequest for GotoDefinitionRequest {
|
||||||
|
|
||||||
let def = ctx.def_of_syntax(&source, doc.as_ref(), syntax)?;
|
let def = ctx.def_of_syntax(&source, doc.as_ref(), syntax)?;
|
||||||
|
|
||||||
let (fid, def_range) = def.def_at(ctx.shared())?;
|
let (fid, def_range) = def.location(ctx.shared())?;
|
||||||
let uri = ctx.uri_for_id(fid).ok()?;
|
let uri = ctx.uri_for_id(fid).ok()?;
|
||||||
let range = ctx.to_lsp_range_(def_range, fid)?;
|
let range = ctx.to_lsp_range_(def_range, fid)?;
|
||||||
|
|
||||||
|
|
|
@ -51,22 +51,22 @@ impl StatefulRequest for HoverRequest {
|
||||||
let mut contents = match contents {
|
let mut contents = match contents {
|
||||||
HoverContents::Array(contents) => contents
|
HoverContents::Array(contents) => contents
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| match e {
|
.map(|content| match content {
|
||||||
MarkedString::LanguageString(e) => {
|
MarkedString::LanguageString(content) => {
|
||||||
format!("```{}\n{}\n```", e.language, e.value)
|
format!("```{}\n{}\n```", content.language, content.value)
|
||||||
}
|
}
|
||||||
MarkedString::String(e) => e,
|
MarkedString::String(content) => content,
|
||||||
})
|
})
|
||||||
.join("\n\n---\n"),
|
.join("\n\n---\n"),
|
||||||
HoverContents::Scalar(MarkedString::String(contents)) => contents,
|
HoverContents::Scalar(MarkedString::String(contents)) => contents,
|
||||||
HoverContents::Scalar(MarkedString::LanguageString(contents)) => {
|
HoverContents::Scalar(MarkedString::LanguageString(contents)) => {
|
||||||
format!("```{}\n{}\n```", contents.language, contents.value)
|
format!("```{}\n{}\n```", contents.language, contents.value)
|
||||||
}
|
}
|
||||||
lsp_types::HoverContents::Markup(e) => {
|
lsp_types::HoverContents::Markup(content) => {
|
||||||
match e.kind {
|
match content.kind {
|
||||||
MarkupKind::Markdown => e.value,
|
MarkupKind::Markdown => content.value,
|
||||||
// todo: escape
|
// todo: escape
|
||||||
MarkupKind::PlainText => e.value,
|
MarkupKind::PlainText => content.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,8 +70,8 @@ pub fn path_to_url(path: &Path) -> anyhow::Result<Url> {
|
||||||
return Ok(Url::parse(&format!("untitled:{}", untitled.display()))?);
|
return Ok(Url::parse(&format!("untitled:{}", untitled.display()))?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Url::from_file_path(path).or_else(|e| {
|
Url::from_file_path(path).or_else(|never| {
|
||||||
let _: () = e;
|
let _: () = never;
|
||||||
|
|
||||||
anyhow::bail!("could not convert path to URI: path: {path:?}",)
|
anyhow::bail!("could not convert path to URI: path: {path:?}",)
|
||||||
})
|
})
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct OnEnterWorker<'a> {
|
||||||
impl OnEnterWorker<'_> {
|
impl OnEnterWorker<'_> {
|
||||||
fn indent_of(&self, of: usize) -> String {
|
fn indent_of(&self, of: usize) -> String {
|
||||||
let all_text = self.source.text();
|
let all_text = self.source.text();
|
||||||
let start = all_text[..of].rfind('\n').map(|e| e + 1);
|
let start = all_text[..of].rfind('\n').map(|lf_offset| lf_offset + 1);
|
||||||
let indent_size = all_text[start.unwrap_or_default()..of].chars().count();
|
let indent_size = all_text[start.unwrap_or_default()..of].chars().count();
|
||||||
" ".repeat(indent_size)
|
" ".repeat(indent_size)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ impl OnEnterWorker<'_> {
|
||||||
.children()
|
.children()
|
||||||
.skip(leaf.index().saturating_sub(first_index))
|
.skip(leaf.index().saturating_sub(first_index))
|
||||||
.take_while(skipper)
|
.take_while(skipper)
|
||||||
.filter(|e| matches!(e.kind(), SyntaxKind::LineComment))
|
.filter(|child| matches!(child.kind(), SyntaxKind::LineComment))
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
let comment_prefix = {
|
let comment_prefix = {
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub(crate) fn prepare_renaming(
|
||||||
def: &Definition,
|
def: &Definition,
|
||||||
) -> Option<(String, Option<LspRange>)> {
|
) -> Option<(String, Option<LspRange>)> {
|
||||||
let name = def.name().clone();
|
let name = def.name().clone();
|
||||||
let (def_fid, _def_range) = def.def_at(ctx.shared()).clone()?;
|
let (def_fid, _def_range) = def.location(ctx.shared()).clone()?;
|
||||||
|
|
||||||
if def_fid.package().is_some() {
|
if def_fid.package().is_some() {
|
||||||
crate::log_debug_ct!(
|
crate::log_debug_ct!(
|
||||||
|
|
|
@ -139,19 +139,19 @@ impl ReferencesWorker<'_> {
|
||||||
|
|
||||||
fn push_idents<'b>(
|
fn push_idents<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
s: &Source,
|
src: &Source,
|
||||||
u: &Url,
|
url: &Url,
|
||||||
idents: impl Iterator<Item = (&'b Span, &'b Interned<RefExpr>)>,
|
idents: impl Iterator<Item = (&'b Span, &'b Interned<RefExpr>)>,
|
||||||
) {
|
) {
|
||||||
self.push_ranges(s, u, idents.map(|e| e.0));
|
self.push_ranges(src, url, idents.map(|(span, _)| span));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_ranges<'b>(&mut self, s: &Source, u: &Url, rs: impl Iterator<Item = &'b Span>) {
|
fn push_ranges<'b>(&mut self, src: &Source, url: &Url, spans: impl Iterator<Item = &'b Span>) {
|
||||||
self.references.extend(rs.filter_map(|span| {
|
self.references.extend(spans.filter_map(|span| {
|
||||||
// todo: this is not necessary a name span
|
// todo: this is not necessary a name span
|
||||||
let range = self.ctx.ctx.to_lsp_range(s.range(*span)?, s);
|
let range = self.ctx.ctx.to_lsp_range(src.range(*span)?, src);
|
||||||
Some(LspLocation {
|
Some(LspLocation {
|
||||||
uri: u.clone(),
|
uri: url.clone(),
|
||||||
range,
|
range,
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl StatefulRequest for RenameRequest {
|
||||||
self.new_name
|
self.new_name
|
||||||
};
|
};
|
||||||
|
|
||||||
let def_fid = def.def_at(ctx.shared())?.0;
|
let def_fid = def.location(ctx.shared())?.0;
|
||||||
let old_path = ctx.path_for_id(def_fid).ok()?;
|
let old_path = ctx.path_for_id(def_fid).ok()?;
|
||||||
|
|
||||||
let rename_loc = Path::new(ref_path_str.as_str());
|
let rename_loc = Path::new(ref_path_str.as_str());
|
||||||
|
|
|
@ -43,16 +43,15 @@ impl SemanticRequest for SymbolRequest {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let uri = path_to_url(&path).unwrap();
|
let uri = path_to_url(&path).unwrap();
|
||||||
let res =
|
let res = get_lexical_hierarchy(&source, LexicalScopeKind::Symbol).map(|symbols| {
|
||||||
get_lexical_hierarchy(source.clone(), LexicalScopeKind::Symbol).map(|symbols| {
|
filter_document_symbols(
|
||||||
filter_document_symbols(
|
&symbols,
|
||||||
&symbols,
|
self.pattern.as_deref(),
|
||||||
self.pattern.as_deref(),
|
&source,
|
||||||
&source,
|
&uri,
|
||||||
&uri,
|
ctx.position_encoding(),
|
||||||
ctx.position_encoding(),
|
)
|
||||||
)
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(mut res) = res {
|
if let Some(mut res) = res {
|
||||||
symbols.append(&mut res)
|
symbols.append(&mut res)
|
||||||
|
@ -65,28 +64,29 @@ impl SemanticRequest for SymbolRequest {
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn filter_document_symbols(
|
fn filter_document_symbols(
|
||||||
symbols: &[LexicalHierarchy],
|
hierarchy: &[LexicalHierarchy],
|
||||||
query_string: Option<&str>,
|
query_string: Option<&str>,
|
||||||
source: &Source,
|
source: &Source,
|
||||||
uri: &Url,
|
uri: &Url,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
) -> Vec<SymbolInformation> {
|
) -> Vec<SymbolInformation> {
|
||||||
symbols
|
hierarchy
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|e| {
|
.flat_map(|hierarchy| {
|
||||||
[e].into_iter()
|
[hierarchy]
|
||||||
.chain(e.children.as_deref().into_iter().flatten())
|
.into_iter()
|
||||||
|
.chain(hierarchy.children.as_deref().into_iter().flatten())
|
||||||
})
|
})
|
||||||
.flat_map(|e| {
|
.flat_map(|hierarchy| {
|
||||||
if query_string.is_some_and(|s| !e.info.name.contains(s)) {
|
if query_string.is_some_and(|s| !hierarchy.info.name.contains(s)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rng = typst_to_lsp::range(e.info.range.clone(), source, position_encoding);
|
let rng = typst_to_lsp::range(hierarchy.info.range.clone(), source, position_encoding);
|
||||||
|
|
||||||
Some(SymbolInformation {
|
Some(SymbolInformation {
|
||||||
name: e.info.name.to_string(),
|
name: hierarchy.info.name.to_string(),
|
||||||
kind: e.info.kind.clone().try_into().unwrap(),
|
kind: hierarchy.info.kind.clone().try_into().unwrap(),
|
||||||
tags: None,
|
tags: None,
|
||||||
deprecated: None,
|
deprecated: None,
|
||||||
location: LspLocation {
|
location: LspLocation {
|
||||||
|
|
|
@ -449,7 +449,7 @@ impl Decl {
|
||||||
decl: this.clone(),
|
decl: this.clone(),
|
||||||
step: Some(def.clone()),
|
step: Some(def.clone()),
|
||||||
root: Some(def),
|
root: Some(def),
|
||||||
val,
|
term: val,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,7 +667,7 @@ pub struct RefExpr {
|
||||||
pub decl: DeclExpr,
|
pub decl: DeclExpr,
|
||||||
pub step: Option<Expr>,
|
pub step: Option<Expr>,
|
||||||
pub root: Option<Expr>,
|
pub root: Option<Expr>,
|
||||||
pub val: Option<Ty>,
|
pub term: Option<Ty>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub(crate) fn compute_docstring(
|
||||||
let checker = DocsChecker {
|
let checker = DocsChecker {
|
||||||
fid,
|
fid,
|
||||||
ctx,
|
ctx,
|
||||||
vars: HashMap::new(),
|
var_bounds: HashMap::new(),
|
||||||
globals: HashMap::default(),
|
globals: HashMap::default(),
|
||||||
locals: SnapshotMap::default(),
|
locals: SnapshotMap::default(),
|
||||||
next_id: 0,
|
next_id: 0,
|
||||||
|
@ -98,10 +98,13 @@ pub(crate) fn compute_docstring(
|
||||||
struct DocsChecker<'a> {
|
struct DocsChecker<'a> {
|
||||||
fid: TypstFileId,
|
fid: TypstFileId,
|
||||||
ctx: &'a Arc<SharedContext>,
|
ctx: &'a Arc<SharedContext>,
|
||||||
/// The typing on definitions
|
/// The bounds of type variables
|
||||||
vars: HashMap<DeclExpr, TypeVarBounds>,
|
var_bounds: HashMap<DeclExpr, TypeVarBounds>,
|
||||||
|
/// Global name bindings
|
||||||
globals: HashMap<EcoString, Option<Ty>>,
|
globals: HashMap<EcoString, Option<Ty>>,
|
||||||
|
/// Local name bindings
|
||||||
locals: SnapshotMap<EcoString, Ty>,
|
locals: SnapshotMap<EcoString, Ty>,
|
||||||
|
/// Next generated variable id
|
||||||
next_id: u32,
|
next_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,8 +117,8 @@ impl DocsChecker<'_> {
|
||||||
convert_docs(self.ctx, &docs).and_then(|converted| identify_pat_docs(&converted));
|
convert_docs(self.ctx, &docs).and_then(|converted| identify_pat_docs(&converted));
|
||||||
|
|
||||||
let converted = match Self::fallback_docs(converted, &docs) {
|
let converted = match Self::fallback_docs(converted, &docs) {
|
||||||
Ok(c) => c,
|
Ok(docs) => docs,
|
||||||
Err(e) => return Some(e),
|
Err(err) => return Some(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
let module = self.ctx.module_by_str(docs);
|
let module = self.ctx.module_by_str(docs);
|
||||||
|
@ -138,7 +141,7 @@ impl DocsChecker<'_> {
|
||||||
|
|
||||||
Some(DocString {
|
Some(DocString {
|
||||||
docs: Some(self.ctx.remove_html(converted.docs)),
|
docs: Some(self.ctx.remove_html(converted.docs)),
|
||||||
var_bounds: self.vars,
|
var_bounds: self.var_bounds,
|
||||||
vars: params,
|
vars: params,
|
||||||
res_ty,
|
res_ty,
|
||||||
})
|
})
|
||||||
|
@ -148,13 +151,13 @@ impl DocsChecker<'_> {
|
||||||
let converted = convert_docs(self.ctx, &docs).and_then(identify_tidy_module_docs);
|
let converted = convert_docs(self.ctx, &docs).and_then(identify_tidy_module_docs);
|
||||||
|
|
||||||
let converted = match Self::fallback_docs(converted, &docs) {
|
let converted = match Self::fallback_docs(converted, &docs) {
|
||||||
Ok(c) => c,
|
Ok(docs) => docs,
|
||||||
Err(e) => return Some(e),
|
Err(err) => return Some(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(DocString {
|
Some(DocString {
|
||||||
docs: Some(self.ctx.remove_html(converted.docs)),
|
docs: Some(self.ctx.remove_html(converted.docs)),
|
||||||
var_bounds: self.vars,
|
var_bounds: self.var_bounds,
|
||||||
vars: BTreeMap::new(),
|
vars: BTreeMap::new(),
|
||||||
res_ty: None,
|
res_ty: None,
|
||||||
})
|
})
|
||||||
|
@ -162,13 +165,13 @@ impl DocsChecker<'_> {
|
||||||
|
|
||||||
fn fallback_docs<T>(converted: Result<T, EcoString>, docs: &str) -> Result<T, DocString> {
|
fn fallback_docs<T>(converted: Result<T, EcoString>, docs: &str) -> Result<T, DocString> {
|
||||||
match converted {
|
match converted {
|
||||||
Ok(c) => Ok(c),
|
Ok(converted) => Ok(converted),
|
||||||
Err(e) => {
|
Err(err) => {
|
||||||
let e = e.replace("`", "\\`");
|
let err = err.replace("`", "\\`");
|
||||||
let max_consecutive_backticks = docs
|
let max_consecutive_backticks = docs
|
||||||
.chars()
|
.chars()
|
||||||
.fold((0, 0), |(max, count), c| {
|
.fold((0, 0), |(max, count), ch| {
|
||||||
if c == '`' {
|
if ch == '`' {
|
||||||
(max.max(count + 1), count + 1)
|
(max.max(count + 1), count + 1)
|
||||||
} else {
|
} else {
|
||||||
(max, 0)
|
(max, 0)
|
||||||
|
@ -177,7 +180,7 @@ impl DocsChecker<'_> {
|
||||||
.0;
|
.0;
|
||||||
let backticks = "`".repeat((max_consecutive_backticks + 1).max(3));
|
let backticks = "`".repeat((max_consecutive_backticks + 1).max(3));
|
||||||
let fallback_docs = eco_format!(
|
let fallback_docs = eco_format!(
|
||||||
"```\nfailed to parse docs: {e}\n```\n\n{backticks}typ\n{docs}\n{backticks}\n"
|
"```\nfailed to parse docs: {err}\n```\n\n{backticks}typ\n{docs}\n{backticks}\n"
|
||||||
);
|
);
|
||||||
Err(DocString {
|
Err(DocString {
|
||||||
docs: Some(fallback_docs),
|
docs: Some(fallback_docs),
|
||||||
|
@ -199,20 +202,20 @@ impl DocsChecker<'_> {
|
||||||
};
|
};
|
||||||
let bounds = TypeVarBounds::new(var, DynTypeBounds::default());
|
let bounds = TypeVarBounds::new(var, DynTypeBounds::default());
|
||||||
let var = bounds.as_type();
|
let var = bounds.as_type();
|
||||||
self.vars.insert(encoded, bounds);
|
self.var_bounds.insert(encoded, bounds);
|
||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type_strings(&mut self, m: &Module, strs: &str) -> Option<Ty> {
|
fn check_type_strings(&mut self, m: &Module, inputs: &str) -> Option<Ty> {
|
||||||
let mut types = vec![];
|
let mut terms = vec![];
|
||||||
for name in strs.split(",").map(|e| e.trim()) {
|
for name in inputs.split(",").map(|ty| ty.trim()) {
|
||||||
let Some(ty) = self.check_type_ident(m, name) else {
|
let Some(ty) = self.check_type_ident(m, name) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
types.push(ty);
|
terms.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Ty::from_types(types.into_iter()))
|
Some(Ty::from_types(terms.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type_ident(&mut self, m: &Module, name: &str) -> Option<Ty> {
|
fn check_type_ident(&mut self, m: &Module, name: &str) -> Option<Ty> {
|
||||||
|
@ -308,21 +311,21 @@ impl DocsChecker<'_> {
|
||||||
| ast::Expr::Float(..)
|
| ast::Expr::Float(..)
|
||||||
| ast::Expr::Numeric(..)
|
| ast::Expr::Numeric(..)
|
||||||
| ast::Expr::Str(..) => SharedContext::const_eval(s).map(|v| Ty::Value(InsTy::new(v))),
|
| ast::Expr::Str(..) => SharedContext::const_eval(s).map(|v| Ty::Value(InsTy::new(v))),
|
||||||
ast::Expr::Binary(b) => {
|
ast::Expr::Binary(binary) => {
|
||||||
let mut components = Vec::with_capacity(2);
|
let mut components = Vec::with_capacity(2);
|
||||||
components.push(self.check_type_expr(m, b.lhs())?);
|
components.push(self.check_type_expr(m, binary.lhs())?);
|
||||||
|
|
||||||
let mut expr = b.rhs();
|
let mut rhs = binary.rhs();
|
||||||
while let ast::Expr::Binary(b) = expr {
|
while let ast::Expr::Binary(binary) = rhs {
|
||||||
if b.op() != ast::BinOp::Or {
|
if binary.op() != ast::BinOp::Or {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
components.push(self.check_type_expr(m, b.lhs())?);
|
components.push(self.check_type_expr(m, binary.lhs())?);
|
||||||
expr = b.rhs();
|
rhs = binary.rhs();
|
||||||
}
|
}
|
||||||
|
|
||||||
components.push(self.check_type_expr(m, expr)?);
|
components.push(self.check_type_expr(m, rhs)?);
|
||||||
Some(Ty::from_types(components.into_iter()))
|
Some(Ty::from_types(components.into_iter()))
|
||||||
}
|
}
|
||||||
ast::Expr::FuncCall(c) => match c.callee() {
|
ast::Expr::FuncCall(c) => match c.callee() {
|
||||||
|
@ -353,42 +356,49 @@ impl DocsChecker<'_> {
|
||||||
},
|
},
|
||||||
ast::Expr::Closure(c) => {
|
ast::Expr::Closure(c) => {
|
||||||
crate::log_debug_ct!("check doc closure annotation: {c:?}");
|
crate::log_debug_ct!("check doc closure annotation: {c:?}");
|
||||||
let mut pos = vec![];
|
let mut pos_all = vec![];
|
||||||
let mut named = BTreeMap::new();
|
let mut named_all = BTreeMap::new();
|
||||||
let mut rest = None;
|
let mut spread_right = None;
|
||||||
let snap = self.locals.snapshot();
|
let snap = self.locals.snapshot();
|
||||||
|
|
||||||
let sig = None.or_else(|| {
|
let sig = None.or_else(|| {
|
||||||
for param in c.params().children() {
|
for param in c.params().children() {
|
||||||
match param {
|
match param {
|
||||||
ast::Param::Pos(ast::Pattern::Normal(ast::Expr::Ident(i))) => {
|
ast::Param::Pos(ast::Pattern::Normal(ast::Expr::Ident(pos))) => {
|
||||||
let name = i.get().clone();
|
let name = pos.get().clone();
|
||||||
let base_ty = self.generate_var(name.as_str().into());
|
let term = self.generate_var(name.as_str().into());
|
||||||
self.locals.insert(name, base_ty.clone());
|
self.locals.insert(name, term.clone());
|
||||||
pos.push(base_ty);
|
pos_all.push(term);
|
||||||
}
|
}
|
||||||
ast::Param::Pos(_) => {
|
ast::Param::Pos(_pos) => {
|
||||||
pos.push(Ty::Any);
|
pos_all.push(Ty::Any);
|
||||||
}
|
}
|
||||||
ast::Param::Named(e) => {
|
ast::Param::Named(named) => {
|
||||||
let exp = self.check_type_expr(m, e.expr()).unwrap_or(Ty::Any);
|
let term = self.check_type_expr(m, named.expr()).unwrap_or(Ty::Any);
|
||||||
named.insert(e.name().into(), exp);
|
named_all.insert(named.name().into(), term);
|
||||||
}
|
}
|
||||||
// todo: spread left/right
|
// todo: spread left/right
|
||||||
ast::Param::Spread(s) => {
|
ast::Param::Spread(spread) => {
|
||||||
let Some(i) = s.sink_ident() else {
|
let Some(sink) = spread.sink_ident() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let name = i.get().clone();
|
let sink_name = sink.get().clone();
|
||||||
let rest_ty = self.generate_var(name.as_str().into());
|
let rest_term = self.generate_var(sink_name.as_str().into());
|
||||||
self.locals.insert(name, rest_ty.clone());
|
self.locals.insert(sink_name, rest_term.clone());
|
||||||
rest = Some(rest_ty);
|
spread_right = Some(rest_term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = self.check_type_expr(m, c.body())?;
|
let body = self.check_type_expr(m, c.body())?;
|
||||||
let sig = SigTy::new(pos.into_iter(), named, None, rest, Some(body)).into();
|
let sig = SigTy::new(
|
||||||
|
pos_all.into_iter(),
|
||||||
|
named_all,
|
||||||
|
None,
|
||||||
|
spread_right,
|
||||||
|
Some(body),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
|
||||||
Some(Ty::Func(sig))
|
Some(Ty::Func(sig))
|
||||||
});
|
});
|
||||||
|
|
|
@ -186,10 +186,12 @@ impl ExprInfo {
|
||||||
|
|
||||||
pub fn is_exported(&self, decl: &Interned<Decl>) -> bool {
|
pub fn is_exported(&self, decl: &Interned<Decl>) -> bool {
|
||||||
let of = Expr::Decl(decl.clone());
|
let of = Expr::Decl(decl.clone());
|
||||||
self.exports.get(decl.name()).map_or(false, |e| match e {
|
self.exports
|
||||||
Expr::Ref(r) => r.root == Some(of),
|
.get(decl.name())
|
||||||
e => *e == of,
|
.map_or(false, |export| match export {
|
||||||
})
|
Expr::Ref(ref_expr) => ref_expr.root == Some(of),
|
||||||
|
exprt => *exprt == of,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -207,8 +209,8 @@ impl ExprInfo {
|
||||||
std::fs::create_dir_all(scopes.parent().unwrap()).unwrap();
|
std::fs::create_dir_all(scopes.parent().unwrap()).unwrap();
|
||||||
{
|
{
|
||||||
let mut scopes = std::fs::File::create(scopes).unwrap();
|
let mut scopes = std::fs::File::create(scopes).unwrap();
|
||||||
for (s, e) in self.exprs.iter() {
|
for (span, expr) in self.exprs.iter() {
|
||||||
writeln!(scopes, "{s:?} -> {e}").unwrap();
|
writeln!(scopes, "{span:?} -> {expr}").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let imports = vpath.with_extension("imports.expr");
|
let imports = vpath.with_extension("imports.expr");
|
||||||
|
@ -376,29 +378,29 @@ impl ExprWorker<'_> {
|
||||||
Shorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
|
Shorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
|
||||||
SmartQuote(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
|
SmartQuote(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
|
||||||
|
|
||||||
Strong(e) => {
|
Strong(strong) => {
|
||||||
let body = self.check_inline_markup(e.body());
|
let body = self.check_inline_markup(strong.body());
|
||||||
self.check_element::<StrongElem>(eco_vec![body])
|
self.check_element::<StrongElem>(eco_vec![body])
|
||||||
}
|
}
|
||||||
Emph(e) => {
|
Emph(emph) => {
|
||||||
let body = self.check_inline_markup(e.body());
|
let body = self.check_inline_markup(emph.body());
|
||||||
self.check_element::<EmphElem>(eco_vec![body])
|
self.check_element::<EmphElem>(eco_vec![body])
|
||||||
}
|
}
|
||||||
Heading(e) => {
|
Heading(heading) => {
|
||||||
let body = self.check_markup(e.body());
|
let body = self.check_markup(heading.body());
|
||||||
self.check_element::<HeadingElem>(eco_vec![body])
|
self.check_element::<HeadingElem>(eco_vec![body])
|
||||||
}
|
}
|
||||||
List(e) => {
|
List(item) => {
|
||||||
let body = self.check_markup(e.body());
|
let body = self.check_markup(item.body());
|
||||||
self.check_element::<ListElem>(eco_vec![body])
|
self.check_element::<ListElem>(eco_vec![body])
|
||||||
}
|
}
|
||||||
Enum(e) => {
|
Enum(item) => {
|
||||||
let body = self.check_markup(e.body());
|
let body = self.check_markup(item.body());
|
||||||
self.check_element::<EnumElem>(eco_vec![body])
|
self.check_element::<EnumElem>(eco_vec![body])
|
||||||
}
|
}
|
||||||
Term(t) => {
|
Term(item) => {
|
||||||
let term = self.check_markup(t.term());
|
let term = self.check_markup(item.term());
|
||||||
let description = self.check_markup(t.description());
|
let description = self.check_markup(item.description());
|
||||||
self.check_element::<TermsElem>(eco_vec![term, description])
|
self.check_element::<TermsElem>(eco_vec![term, description])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,19 +409,19 @@ impl ExprWorker<'_> {
|
||||||
MathDelimited(math_delimited) => {
|
MathDelimited(math_delimited) => {
|
||||||
self.check_math(math_delimited.body().to_untyped().children())
|
self.check_math(math_delimited.body().to_untyped().children())
|
||||||
}
|
}
|
||||||
MathAttach(ma) => {
|
MathAttach(attach) => {
|
||||||
let base = ma.base().to_untyped().clone();
|
let base = attach.base().to_untyped().clone();
|
||||||
let bottom = ma.bottom().unwrap_or_default().to_untyped().clone();
|
let bottom = attach.bottom().unwrap_or_default().to_untyped().clone();
|
||||||
let top = ma.top().unwrap_or_default().to_untyped().clone();
|
let top = attach.top().unwrap_or_default().to_untyped().clone();
|
||||||
self.check_math([base, bottom, top].iter())
|
self.check_math([base, bottom, top].iter())
|
||||||
}
|
}
|
||||||
MathPrimes(..) => Expr::Type(Ty::Builtin(BuiltinTy::None)),
|
MathPrimes(..) => Expr::Type(Ty::Builtin(BuiltinTy::None)),
|
||||||
MathFrac(mf) => {
|
MathFrac(frac) => {
|
||||||
let num = mf.num().to_untyped().clone();
|
let num = frac.num().to_untyped().clone();
|
||||||
let denom = mf.denom().to_untyped().clone();
|
let denom = frac.denom().to_untyped().clone();
|
||||||
self.check_math([num, denom].iter())
|
self.check_math([num, denom].iter())
|
||||||
}
|
}
|
||||||
MathRoot(mr) => self.check(mr.radicand()),
|
MathRoot(root) => self.check(root.radicand()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,14 +439,14 @@ impl ExprWorker<'_> {
|
||||||
ast::LetBindingKind::Closure(..) => {
|
ast::LetBindingKind::Closure(..) => {
|
||||||
typed.init().map_or_else(none_expr, |expr| self.check(expr))
|
typed.init().map_or_else(none_expr, |expr| self.check(expr))
|
||||||
}
|
}
|
||||||
ast::LetBindingKind::Normal(p) => {
|
ast::LetBindingKind::Normal(pat) => {
|
||||||
// Check init expression before pattern checking
|
// Check init expression before pattern checking
|
||||||
let body = typed.init().map(|e| self.defer(e));
|
let body = typed.init().map(|init| self.defer(init));
|
||||||
|
|
||||||
let span = p.span();
|
let span = pat.span();
|
||||||
let decl = Decl::pattern(span).into();
|
let decl = Decl::pattern(span).into();
|
||||||
self.check_docstring(&decl, DefKind::Variable);
|
self.check_docstring(&decl, DefKind::Variable);
|
||||||
let pattern = self.check_pattern(p);
|
let pattern = self.check_pattern(pat);
|
||||||
Expr::Let(Interned::new(LetExpr {
|
Expr::Let(Interned::new(LetExpr {
|
||||||
span,
|
span,
|
||||||
pattern,
|
pattern,
|
||||||
|
@ -613,7 +615,7 @@ impl ExprWorker<'_> {
|
||||||
decl: mod_var.clone(),
|
decl: mod_var.clone(),
|
||||||
step: mod_expr.clone(),
|
step: mod_expr.clone(),
|
||||||
root: mod_expr.clone(),
|
root: mod_expr.clone(),
|
||||||
val: None,
|
term: None,
|
||||||
};
|
};
|
||||||
crate::log_debug_ct!("create import variable: {mod_ref:?}");
|
crate::log_debug_ct!("create import variable: {mod_ref:?}");
|
||||||
let mod_ref = Interned::new(mod_ref);
|
let mod_ref = Interned::new(mod_ref);
|
||||||
|
@ -778,7 +780,7 @@ impl ExprWorker<'_> {
|
||||||
decl: import_path.into(),
|
decl: import_path.into(),
|
||||||
step: Some(module.clone()),
|
step: Some(module.clone()),
|
||||||
root: Some(module.clone()),
|
root: Some(module.clone()),
|
||||||
val: None,
|
term: None,
|
||||||
};
|
};
|
||||||
self.resolve_as(ref_expr.into());
|
self.resolve_as(ref_expr.into());
|
||||||
Some(module)
|
Some(module)
|
||||||
|
@ -834,7 +836,7 @@ impl ExprWorker<'_> {
|
||||||
decl: old.clone(),
|
decl: old.clone(),
|
||||||
root,
|
root,
|
||||||
step,
|
step,
|
||||||
val,
|
term: val,
|
||||||
});
|
});
|
||||||
self.resolve_as(ref_expr.clone());
|
self.resolve_as(ref_expr.clone());
|
||||||
|
|
||||||
|
@ -843,7 +845,7 @@ impl ExprWorker<'_> {
|
||||||
decl: new.clone(),
|
decl: new.clone(),
|
||||||
root: ref_expr.root.clone(),
|
root: ref_expr.root.clone(),
|
||||||
step: Some(ref_expr.decl.clone().into()),
|
step: Some(ref_expr.decl.clone().into()),
|
||||||
val: ref_expr.val.clone(),
|
term: ref_expr.term.clone(),
|
||||||
});
|
});
|
||||||
self.resolve_as(ref_expr.clone());
|
self.resolve_as(ref_expr.clone());
|
||||||
}
|
}
|
||||||
|
@ -1012,39 +1014,41 @@ impl ExprWorker<'_> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_inline_markup(&mut self, m: ast::Markup) -> Expr {
|
fn check_inline_markup(&mut self, markup: ast::Markup) -> Expr {
|
||||||
self.check_in_mode(m.to_untyped().children(), InterpretMode::Markup)
|
self.check_in_mode(markup.to_untyped().children(), InterpretMode::Markup)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_markup(&mut self, m: ast::Markup) -> Expr {
|
fn check_markup(&mut self, markup: ast::Markup) -> Expr {
|
||||||
self.with_scope(|this| this.check_inline_markup(m))
|
self.with_scope(|this| this.check_inline_markup(markup))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_code(&mut self, m: ast::Code) -> Expr {
|
fn check_code(&mut self, code: ast::Code) -> Expr {
|
||||||
self.with_scope(|this| this.check_in_mode(m.to_untyped().children(), InterpretMode::Code))
|
self.with_scope(|this| {
|
||||||
|
this.check_in_mode(code.to_untyped().children(), InterpretMode::Code)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_math(&mut self, root: SyntaxNodeChildren) -> Expr {
|
fn check_math(&mut self, children: SyntaxNodeChildren) -> Expr {
|
||||||
self.check_in_mode(root, InterpretMode::Math)
|
self.check_in_mode(children, InterpretMode::Math)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_root_scope(&mut self, root: SyntaxNodeChildren) {
|
fn check_root_scope(&mut self, children: SyntaxNodeChildren) {
|
||||||
self.init_stage = true;
|
self.init_stage = true;
|
||||||
self.check_in_mode(root, InterpretMode::Markup);
|
self.check_in_mode(children, InterpretMode::Markup);
|
||||||
self.init_stage = false;
|
self.init_stage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_in_mode(&mut self, root: SyntaxNodeChildren, mode: InterpretMode) -> Expr {
|
fn check_in_mode(&mut self, children: SyntaxNodeChildren, mode: InterpretMode) -> Expr {
|
||||||
let old_mode = self.lexical.mode;
|
let old_mode = self.lexical.mode;
|
||||||
self.lexical.mode = mode;
|
self.lexical.mode = mode;
|
||||||
|
|
||||||
// collect all comments before the definition
|
// collect all comments before the definition
|
||||||
self.comment_matcher.reset();
|
self.comment_matcher.reset();
|
||||||
|
|
||||||
let mut children = Vec::with_capacity(4);
|
let mut items = Vec::with_capacity(4);
|
||||||
for n in root {
|
for n in children {
|
||||||
if let Some(expr) = n.cast::<ast::Expr>() {
|
if let Some(expr) = n.cast::<ast::Expr>() {
|
||||||
children.push(self.check(expr));
|
items.push(self.check(expr));
|
||||||
self.comment_matcher.reset();
|
self.comment_matcher.reset();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1054,12 +1058,14 @@ impl ExprWorker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lexical.mode = old_mode;
|
self.lexical.mode = old_mode;
|
||||||
Expr::Block(children.into())
|
Expr::Block(items.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ref(&mut self, r: ast::Ref) -> Expr {
|
fn check_ref(&mut self, ref_node: ast::Ref) -> Expr {
|
||||||
let ident = Interned::new(Decl::ref_(r));
|
let ident = Interned::new(Decl::ref_(ref_node));
|
||||||
let body = r.supplement().map(|s| self.check(ast::Expr::Content(s)));
|
let body = ref_node
|
||||||
|
.supplement()
|
||||||
|
.map(|block| self.check(ast::Expr::Content(block)));
|
||||||
let ref_expr = ContentRefExpr {
|
let ref_expr = ContentRefExpr {
|
||||||
ident: ident.clone(),
|
ident: ident.clone(),
|
||||||
of: None,
|
of: None,
|
||||||
|
@ -1070,7 +1076,7 @@ impl ExprWorker<'_> {
|
||||||
decl: ident,
|
decl: ident,
|
||||||
step: None,
|
step: None,
|
||||||
root: None,
|
root: None,
|
||||||
val: None,
|
term: None,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
@ -1108,7 +1114,7 @@ impl ExprWorker<'_> {
|
||||||
decl,
|
decl,
|
||||||
root,
|
root,
|
||||||
step,
|
step,
|
||||||
val,
|
term: val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,8 +1139,8 @@ impl ExprWorker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr(&mut self, expr: ast::Expr, mode: InterpretMode) -> ConcolicExpr {
|
fn eval_expr(&mut self, expr: ast::Expr, mode: InterpretMode) -> ConcolicExpr {
|
||||||
if let Some(s) = self.const_eval_expr(expr) {
|
if let Some(term) = self.const_eval_expr(expr) {
|
||||||
return (None, Some(Ty::Value(InsTy::new(s))));
|
return (None, Some(Ty::Value(InsTy::new(term))));
|
||||||
}
|
}
|
||||||
crate::log_debug_ct!("checking expr: {expr:?}");
|
crate::log_debug_ct!("checking expr: {expr:?}");
|
||||||
|
|
||||||
|
@ -1142,8 +1148,8 @@ impl ExprWorker<'_> {
|
||||||
ast::Expr::FieldAccess(f) => {
|
ast::Expr::FieldAccess(f) => {
|
||||||
let field = Decl::ident_ref(f.field());
|
let field = Decl::ident_ref(f.field());
|
||||||
|
|
||||||
let (expr, val) = self.eval_expr(f.target(), mode);
|
let (expr, term) = self.eval_expr(f.target(), mode);
|
||||||
let val = val.and_then(|v| {
|
let term = term.and_then(|v| {
|
||||||
// todo: use type select
|
// todo: use type select
|
||||||
// v.select(field.name()).ok()
|
// v.select(field.name()).ok()
|
||||||
match v {
|
match v {
|
||||||
|
@ -1153,13 +1159,13 @@ impl ExprWorker<'_> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let expr = expr.map(|e| Expr::Select(SelectExpr::new(field.into(), e)));
|
let sel = expr.map(|expr| Expr::Select(SelectExpr::new(field.into(), expr)));
|
||||||
(expr, val)
|
(sel, term)
|
||||||
}
|
}
|
||||||
ast::Expr::Ident(ident) => {
|
ast::Expr::Ident(ident) => {
|
||||||
let res = self.eval_ident(&ident.get().into(), mode);
|
let expr_term = self.eval_ident(&ident.get().into(), mode);
|
||||||
crate::log_debug_ct!("checking expr: {expr:?} -> res: {res:?}");
|
crate::log_debug_ct!("checking expr: {expr:?} -> res: {expr_term:?}");
|
||||||
res
|
expr_term
|
||||||
}
|
}
|
||||||
_ => (None, None),
|
_ => (None, None),
|
||||||
}
|
}
|
||||||
|
@ -1200,9 +1206,9 @@ impl ExprWorker<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_expr(&mut self, src: Option<Expr>) -> Option<Expr> {
|
fn fold_expr(&mut self, expr: Option<Expr>) -> Option<Expr> {
|
||||||
crate::log_debug_ct!("folding cc: {src:?}");
|
crate::log_debug_ct!("folding cc: {expr:?}");
|
||||||
match src {
|
match expr {
|
||||||
Some(Expr::Decl(decl)) if !decl.is_def() => {
|
Some(Expr::Decl(decl)) if !decl.is_def() => {
|
||||||
crate::log_debug_ct!("folding decl: {decl:?}");
|
crate::log_debug_ct!("folding decl: {decl:?}");
|
||||||
let (x, y) = self.eval_ident(decl.name(), InterpretMode::Code);
|
let (x, y) = self.eval_ident(decl.name(), InterpretMode::Code);
|
||||||
|
@ -1210,7 +1216,7 @@ impl ExprWorker<'_> {
|
||||||
}
|
}
|
||||||
Some(Expr::Ref(r)) => {
|
Some(Expr::Ref(r)) => {
|
||||||
crate::log_debug_ct!("folding ref: {r:?}");
|
crate::log_debug_ct!("folding ref: {r:?}");
|
||||||
self.fold_expr_and_val((r.root.clone(), r.val.clone()))
|
self.fold_expr_and_val((r.root.clone(), r.term.clone()))
|
||||||
}
|
}
|
||||||
Some(Expr::Select(r)) => {
|
Some(Expr::Select(r)) => {
|
||||||
let lhs = self.fold_expr(Some(r.lhs.clone()));
|
let lhs = self.fold_expr(Some(r.lhs.clone()));
|
||||||
|
@ -1235,7 +1241,7 @@ impl ExprWorker<'_> {
|
||||||
decl: key.clone(),
|
decl: key.clone(),
|
||||||
root: Some(lhs.clone()),
|
root: Some(lhs.clone()),
|
||||||
step: Some(selected.clone()),
|
step: Some(selected.clone()),
|
||||||
val: None,
|
term: None,
|
||||||
});
|
});
|
||||||
self.resolve_as(select_ref.clone());
|
self.resolve_as(select_ref.clone());
|
||||||
self.resolve_as_(span, select_ref);
|
self.resolve_as_(span, select_ref);
|
||||||
|
|
|
@ -11,7 +11,7 @@ use typst::syntax::{
|
||||||
use typst_shim::utils::LazyHash;
|
use typst_shim::utils::LazyHash;
|
||||||
|
|
||||||
pub(crate) fn get_lexical_hierarchy(
|
pub(crate) fn get_lexical_hierarchy(
|
||||||
source: Source,
|
source: &Source,
|
||||||
g: LexicalScopeKind,
|
g: LexicalScopeKind,
|
||||||
) -> Option<EcoVec<LexicalHierarchy>> {
|
) -> Option<EcoVec<LexicalHierarchy>> {
|
||||||
let b = std::time::Instant::now();
|
let b = std::time::Instant::now();
|
||||||
|
@ -31,8 +31,8 @@ pub(crate) fn get_lexical_hierarchy(
|
||||||
));
|
));
|
||||||
let res = match worker.get_symbols(root) {
|
let res = match worker.get_symbols(root) {
|
||||||
Ok(()) => Some(()),
|
Ok(()) => Some(()),
|
||||||
Err(e) => {
|
Err(err) => {
|
||||||
log::error!("lexical hierarchy analysis failed: {:?}", e);
|
log::error!("lexical hierarchy analysis failed: {err:?}");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -301,34 +301,34 @@ impl LexicalHierarchyWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse order for correct symbol affection
|
// reverse order for correct symbol affection
|
||||||
let name_offset = pattern.as_ref().map(|e| e.offset());
|
let name_offset = pattern.as_ref().map(|node| node.offset());
|
||||||
self.get_symbols_in_opt_with(pattern, IdentContext::Var)?;
|
self.get_symbols_in_opt_with(pattern, IdentContext::Var)?;
|
||||||
self.get_symbols_in_first_expr(node.children().rev(), name_offset)?;
|
self.get_symbols_in_first_expr(node.children().rev(), name_offset)?;
|
||||||
}
|
}
|
||||||
SyntaxKind::ForLoop => {
|
SyntaxKind::ForLoop => {
|
||||||
let pattern = node.children().find(|n| n.is::<ast::Pattern>());
|
let pattern = node.children().find(|child| child.is::<ast::Pattern>());
|
||||||
let iterable = node
|
let iterable = node
|
||||||
.children()
|
.children()
|
||||||
.skip_while(|n| n.kind() != SyntaxKind::In)
|
.skip_while(|child| child.kind() != SyntaxKind::In)
|
||||||
.find(|e| e.is::<ast::Expr>());
|
.find(|child| child.is::<ast::Expr>());
|
||||||
|
|
||||||
let iterable_offset = iterable.as_ref().map(|e| e.offset());
|
let iterable_offset = iterable.as_ref().map(|node| node.offset());
|
||||||
self.get_symbols_in_opt_with(iterable, IdentContext::Ref)?;
|
self.get_symbols_in_opt_with(iterable, IdentContext::Ref)?;
|
||||||
self.get_symbols_in_opt_with(pattern, IdentContext::Var)?;
|
self.get_symbols_in_opt_with(pattern, IdentContext::Var)?;
|
||||||
self.get_symbols_in_first_expr(node.children().rev(), iterable_offset)?;
|
self.get_symbols_in_first_expr(node.children().rev(), iterable_offset)?;
|
||||||
}
|
}
|
||||||
SyntaxKind::Closure => {
|
SyntaxKind::Closure => {
|
||||||
let n = node.children().next();
|
let first_child = node.children().next();
|
||||||
let current = self.stack.last_mut().unwrap().1.len();
|
let current = self.stack.last_mut().unwrap().1.len();
|
||||||
if let Some(n) = n {
|
if let Some(first_child) = first_child {
|
||||||
if n.kind() == SyntaxKind::Ident {
|
if first_child.kind() == SyntaxKind::Ident {
|
||||||
self.get_symbols_with(n, IdentContext::Func)?;
|
self.get_symbols_with(first_child, IdentContext::Func)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let body = node
|
let body = node
|
||||||
.children()
|
.children()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|n| n.cast::<ast::Expr>().is_some());
|
.find(|child| child.cast::<ast::Expr>().is_some());
|
||||||
if let Some(body) = body {
|
if let Some(body) = body {
|
||||||
let symbol = if current == self.stack.last().unwrap().1.len() {
|
let symbol = if current == self.stack.last().unwrap().1.len() {
|
||||||
// Closure has no updated symbol stack
|
// Closure has no updated symbol stack
|
||||||
|
@ -398,7 +398,7 @@ impl LexicalHierarchyWorker {
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let body = nodes.find(|n| n.is::<ast::Expr>());
|
let body = nodes.find(|n| n.is::<ast::Expr>());
|
||||||
if let Some(body) = body {
|
if let Some(body) = body {
|
||||||
if iterable_offset.is_some_and(|e| e >= body.offset()) {
|
if iterable_offset.is_some_and(|offset| offset >= body.offset()) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.get_symbols_with(body, IdentContext::Ref)?;
|
self.get_symbols_with(body, IdentContext::Ref)?;
|
||||||
|
|
|
@ -90,8 +90,8 @@ pub fn descent_decls<T>(
|
||||||
return Some(t);
|
return Some(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ast::Imports::Items(e)) => {
|
Some(ast::Imports::Items(items)) => {
|
||||||
for item in e.iter() {
|
for item in items.iter() {
|
||||||
if let Some(t) = recv(DescentDecl::Ident(item.bound_name())) {
|
if let Some(t) = recv(DescentDecl::Ident(item.bound_name())) {
|
||||||
return Some(t);
|
return Some(t);
|
||||||
}
|
}
|
||||||
|
@ -389,13 +389,13 @@ fn possible_in_code_trivia(sk: SyntaxKind) -> bool {
|
||||||
/// - Parenthesized expression.
|
/// - Parenthesized expression.
|
||||||
/// - Identifier on the right side of a dot operator (field access).
|
/// - Identifier on the right side of a dot operator (field access).
|
||||||
fn classify_lvalue(mut node: LinkedNode) -> Option<LinkedNode> {
|
fn classify_lvalue(mut node: LinkedNode) -> Option<LinkedNode> {
|
||||||
while let Some(e) = node.cast::<ast::Parenthesized>() {
|
while let Some(paren_expr) = node.cast::<ast::Parenthesized>() {
|
||||||
node = node.find(e.expr().span())?;
|
node = node.find(paren_expr.expr().span())?;
|
||||||
}
|
}
|
||||||
if let Some(e) = node.parent() {
|
if let Some(parent) = node.parent() {
|
||||||
if let Some(f) = e.cast::<ast::FieldAccess>() {
|
if let Some(field_access) = parent.cast::<ast::FieldAccess>() {
|
||||||
if node.span() == f.field().span() {
|
if node.span() == field_access.field().span() {
|
||||||
return Some(e.clone());
|
return Some(parent.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,7 +541,7 @@ impl ArgClass<'_> {
|
||||||
/// A cursor class is either an [`SyntaxClass`] or other things under cursor.
|
/// A cursor class is either an [`SyntaxClass`] or other things under cursor.
|
||||||
/// One thing is not ncessary to refer to some exact node. For example, a cursor
|
/// One thing is not ncessary to refer to some exact node. For example, a cursor
|
||||||
/// moving after some comma in a function call is identified as a
|
/// moving after some comma in a function call is identified as a
|
||||||
/// [`CursorClass::Param`].
|
/// [`CursorClass::Arg`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum CursorClass<'a> {
|
pub enum CursorClass<'a> {
|
||||||
/// A cursor on an argument.
|
/// A cursor on an argument.
|
||||||
|
@ -608,12 +608,12 @@ pub fn classify_cursor_by_context<'a>(
|
||||||
) -> Option<CursorClass<'a>> {
|
) -> Option<CursorClass<'a>> {
|
||||||
use SyntaxClass::*;
|
use SyntaxClass::*;
|
||||||
let context_syntax = classify_syntax(context.clone(), node.offset())?;
|
let context_syntax = classify_syntax(context.clone(), node.offset())?;
|
||||||
let inner_syntax = classify_syntax(node.clone(), node.offset())?;
|
let node_syntax = classify_syntax(node.clone(), node.offset())?;
|
||||||
|
|
||||||
match context_syntax {
|
match context_syntax {
|
||||||
Callee(callee)
|
Callee(callee)
|
||||||
if matches!(inner_syntax, Normal(..) | Label { .. } | Ref(..))
|
if matches!(node_syntax, Normal(..) | Label { .. } | Ref(..))
|
||||||
&& !matches!(inner_syntax, Callee(..)) =>
|
&& !matches!(node_syntax, Callee(..)) =>
|
||||||
{
|
{
|
||||||
let parent = callee.parent()?;
|
let parent = callee.parent()?;
|
||||||
let args = match parent.cast::<ast::Expr>() {
|
let args = match parent.cast::<ast::Expr>() {
|
||||||
|
@ -829,7 +829,7 @@ mod tests {
|
||||||
use typst::syntax::{is_newline, Source};
|
use typst::syntax::{is_newline, Source};
|
||||||
use typst_shim::syntax::LinkedNodeExt;
|
use typst_shim::syntax::LinkedNodeExt;
|
||||||
|
|
||||||
fn map_base(source: &str, mapper: impl Fn(&LinkedNode, usize) -> char) -> String {
|
fn map_node(source: &str, mapper: impl Fn(&LinkedNode, usize) -> char) -> String {
|
||||||
let source = Source::detached(source.to_owned());
|
let source = Source::detached(source.to_owned());
|
||||||
let root = LinkedNode::new(source.root());
|
let root = LinkedNode::new(source.root());
|
||||||
let mut output_mapping = String::new();
|
let mut output_mapping = String::new();
|
||||||
|
@ -853,8 +853,8 @@ mod tests {
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_deref(source: &str) -> String {
|
fn map_syntax(source: &str) -> String {
|
||||||
map_base(source, |root, cursor| {
|
map_node(source, |root, cursor| {
|
||||||
let node = root.leaf_at_compat(cursor);
|
let node = root.leaf_at_compat(cursor);
|
||||||
let kind = node.and_then(|node| classify_syntax(node, cursor));
|
let kind = node.and_then(|node| classify_syntax(node, cursor));
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -870,8 +870,8 @@ mod tests {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_check(source: &str) -> String {
|
fn map_cursor(source: &str) -> String {
|
||||||
map_base(source, |root, cursor| {
|
map_node(source, |root, cursor| {
|
||||||
let node = root.leaf_at_compat(cursor);
|
let node = root.leaf_at_compat(cursor);
|
||||||
let kind = node.and_then(|node| classify_cursor(node));
|
let kind = node.and_then(|node| classify_cursor(node));
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -889,7 +889,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_deref_target() {
|
fn test_get_deref_target() {
|
||||||
assert_snapshot!(map_deref(r#"#let x = 1
|
assert_snapshot!(map_syntax(r#"#let x = 1
|
||||||
Text
|
Text
|
||||||
= Heading #let y = 2;
|
= Heading #let y = 2;
|
||||||
== Heading"#).trim(), @r"
|
== Heading"#).trim(), @r"
|
||||||
|
@ -901,11 +901,11 @@ Text
|
||||||
nnnnvvnnn
|
nnnnvvnnn
|
||||||
== Heading
|
== Heading
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_deref(r#"#let f(x);"#).trim(), @r"
|
assert_snapshot!(map_syntax(r#"#let f(x);"#).trim(), @r"
|
||||||
#let f(x);
|
#let f(x);
|
||||||
nnnnv v
|
nnnnv v
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_deref(r#"#{
|
assert_snapshot!(map_syntax(r#"#{
|
||||||
calc.
|
calc.
|
||||||
}"#).trim(), @r"
|
}"#).trim(), @r"
|
||||||
#{
|
#{
|
||||||
|
@ -919,7 +919,7 @@ Text
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_check_target() {
|
fn test_get_check_target() {
|
||||||
assert_snapshot!(map_check(r#"#let x = 1
|
assert_snapshot!(map_cursor(r#"#let x = 1
|
||||||
Text
|
Text
|
||||||
= Heading #let y = 2;
|
= Heading #let y = 2;
|
||||||
== Heading"#).trim(), @r"
|
== Heading"#).trim(), @r"
|
||||||
|
@ -931,31 +931,31 @@ Text
|
||||||
nnnnnnnnn
|
nnnnnnnnn
|
||||||
== Heading
|
== Heading
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#let f(x);"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#let f(x);"#).trim(), @r"
|
||||||
#let f(x);
|
#let f(x);
|
||||||
nnnnn n
|
nnnnn n
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#f(1, 2) Test"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#f(1, 2) Test"#).trim(), @r"
|
||||||
#f(1, 2) Test
|
#f(1, 2) Test
|
||||||
npppppp
|
npppppp
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#() Test"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#() Test"#).trim(), @r"
|
||||||
#() Test
|
#() Test
|
||||||
ee
|
ee
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#(1) Test"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#(1) Test"#).trim(), @r"
|
||||||
#(1) Test
|
#(1) Test
|
||||||
PPP
|
PPP
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#(a: 1) Test"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#(a: 1) Test"#).trim(), @r"
|
||||||
#(a: 1) Test
|
#(a: 1) Test
|
||||||
eeeeee
|
eeeeee
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#(1, 2) Test"#).trim(), @r"
|
assert_snapshot!(map_cursor(r#"#(1, 2) Test"#).trim(), @r"
|
||||||
#(1, 2) Test
|
#(1, 2) Test
|
||||||
eeeeee
|
eeeeee
|
||||||
");
|
");
|
||||||
assert_snapshot!(map_check(r#"#(1, 2)
|
assert_snapshot!(map_cursor(r#"#(1, 2)
|
||||||
Test"#).trim(), @r"
|
Test"#).trim(), @r"
|
||||||
#(1, 2)
|
#(1, 2)
|
||||||
eeeeee
|
eeeeee
|
||||||
|
|
|
@ -123,8 +123,8 @@ pub(crate) fn scan_workspace_files<T>(
|
||||||
if !de
|
if !de
|
||||||
.path()
|
.path()
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|err| err.to_str())
|
||||||
.is_some_and(|e| ext.is_match(e))
|
.is_some_and(|err| ext.is_match(err))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,30 +19,30 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
|
|
||||||
pub fn write_expr(&mut self, expr: &Expr) -> fmt::Result {
|
pub fn write_expr(&mut self, expr: &Expr) -> fmt::Result {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Block(s) => self.write_seq(s),
|
Expr::Block(exprs) => self.write_seq(exprs),
|
||||||
Expr::Array(a) => self.write_array(a),
|
Expr::Array(elems) => self.write_array(elems),
|
||||||
Expr::Dict(d) => self.write_dict(d),
|
Expr::Dict(elems) => self.write_dict(elems),
|
||||||
Expr::Args(a) => self.write_args(a),
|
Expr::Args(args) => self.write_args(args),
|
||||||
Expr::Pattern(p) => self.write_pattern(p),
|
Expr::Pattern(pat) => self.write_pattern(pat),
|
||||||
Expr::Element(e) => self.write_element(e),
|
Expr::Element(elem) => self.write_element(elem),
|
||||||
Expr::Unary(u) => self.write_unary(u),
|
Expr::Unary(unary) => self.write_unary(unary),
|
||||||
Expr::Binary(b) => self.write_binary(b),
|
Expr::Binary(binary) => self.write_binary(binary),
|
||||||
Expr::Apply(a) => self.write_apply(a),
|
Expr::Apply(apply) => self.write_apply(apply),
|
||||||
Expr::Func(func) => self.write_func(func),
|
Expr::Func(func) => self.write_func(func),
|
||||||
Expr::Let(l) => self.write_let(l),
|
Expr::Let(let_expr) => self.write_let(let_expr),
|
||||||
Expr::Show(s) => self.write_show(s),
|
Expr::Show(show) => self.write_show(show),
|
||||||
Expr::Set(s) => self.write_set(s),
|
Expr::Set(set) => self.write_set(set),
|
||||||
Expr::Ref(r) => self.write_ref(r),
|
Expr::Ref(reference) => self.write_ref(reference),
|
||||||
Expr::ContentRef(r) => self.write_content_ref(r),
|
Expr::ContentRef(content_ref) => self.write_content_ref(content_ref),
|
||||||
Expr::Select(s) => self.write_select(s),
|
Expr::Select(sel) => self.write_select(sel),
|
||||||
Expr::Import(i) => self.write_import(i),
|
Expr::Import(import) => self.write_import(import),
|
||||||
Expr::Include(i) => self.write_include(i),
|
Expr::Include(include) => self.write_include(include),
|
||||||
Expr::Contextual(c) => self.write_contextual(c),
|
Expr::Contextual(contextual) => self.write_contextual(contextual),
|
||||||
Expr::Conditional(c) => self.write_conditional(c),
|
Expr::Conditional(if_expr) => self.write_conditional(if_expr),
|
||||||
Expr::WhileLoop(w) => self.write_while_loop(w),
|
Expr::WhileLoop(while_expr) => self.write_while_loop(while_expr),
|
||||||
Expr::ForLoop(f) => self.write_for_loop(f),
|
Expr::ForLoop(for_expr) => self.write_for_loop(for_expr),
|
||||||
Expr::Type(t) => self.write_type(t),
|
Expr::Type(ty) => self.write_type(ty),
|
||||||
Expr::Decl(d) => self.write_decl(d),
|
Expr::Decl(decl) => self.write_decl(decl),
|
||||||
Expr::Star => self.write_star(),
|
Expr::Star => self.write_star(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,10 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, "{:indent$}", "", indent = self.indent)
|
write!(self.f, "{:indent$}", "", indent = self.indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_seq(&mut self, s: &Interned<Vec<Expr>>) -> fmt::Result {
|
fn write_seq(&mut self, exprs: &Interned<Vec<Expr>>) -> fmt::Result {
|
||||||
writeln!(self.f, "[")?;
|
writeln!(self.f, "[")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for expr in s.iter() {
|
for expr in exprs.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_expr(expr)?;
|
self.write_expr(expr)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -64,10 +64,10 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, "]")
|
write!(self.f, "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_array(&mut self, a: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_array(&mut self, elems: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
writeln!(self.f, "(")?;
|
writeln!(self.f, "(")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for arg in a.iter() {
|
for arg in elems.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -77,10 +77,10 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_dict(&mut self, d: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_dict(&mut self, elems: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
writeln!(self.f, "(:")?;
|
writeln!(self.f, "(:")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for arg in d.iter() {
|
for arg in elems.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -90,9 +90,9 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_args(&mut self, a: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_args(&mut self, args: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
writeln!(self.f, "(")?;
|
writeln!(self.f, "(")?;
|
||||||
for arg in a.iter() {
|
for arg in args.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -101,32 +101,32 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_arg(&mut self, a: &ArgExpr) -> fmt::Result {
|
fn write_arg(&mut self, arg: &ArgExpr) -> fmt::Result {
|
||||||
match a {
|
match arg {
|
||||||
ArgExpr::Pos(e) => self.write_expr(e),
|
ArgExpr::Pos(pos) => self.write_expr(pos),
|
||||||
ArgExpr::Named(n) => {
|
ArgExpr::Named(named) => {
|
||||||
let (k, v) = n.as_ref();
|
let (k, v) = named.as_ref();
|
||||||
write!(self.f, "{k:?}: ")?;
|
write!(self.f, "{k:?}: ")?;
|
||||||
self.write_expr(v)
|
self.write_expr(v)
|
||||||
}
|
}
|
||||||
ArgExpr::NamedRt(n) => {
|
ArgExpr::NamedRt(named) => {
|
||||||
let n = n.as_ref();
|
let (key, val) = named.as_ref();
|
||||||
self.write_expr(&n.0)?;
|
self.write_expr(key)?;
|
||||||
write!(self.f, ": ")?;
|
write!(self.f, ": ")?;
|
||||||
self.write_expr(&n.1)
|
self.write_expr(val)
|
||||||
}
|
}
|
||||||
ArgExpr::Spread(e) => {
|
ArgExpr::Spread(spread) => {
|
||||||
write!(self.f, "..")?;
|
write!(self.f, "..")?;
|
||||||
self.write_expr(e)
|
self.write_expr(spread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_pattern(&mut self, p: &Pattern) -> fmt::Result {
|
pub fn write_pattern(&mut self, p: &Pattern) -> fmt::Result {
|
||||||
match p {
|
match p {
|
||||||
Pattern::Expr(e) => self.write_expr(e),
|
Pattern::Expr(expr) => self.write_expr(expr),
|
||||||
Pattern::Simple(s) => self.write_decl(s),
|
Pattern::Simple(decl) => self.write_decl(decl),
|
||||||
Pattern::Sig(p) => self.write_pattern_sig(p),
|
Pattern::Sig(sig) => self.write_pattern_sig(sig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +161,10 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_element(&mut self, e: &Interned<ElementExpr>) -> fmt::Result {
|
fn write_element(&mut self, elem: &Interned<ElementExpr>) -> fmt::Result {
|
||||||
self.f.write_str("elem(\n")?;
|
self.f.write_str("elem(\n")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for v in &e.content {
|
for v in &elem.content {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_expr(v)?;
|
self.write_expr(v)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -174,26 +174,26 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_unary(&mut self, u: &Interned<UnExpr>) -> fmt::Result {
|
fn write_unary(&mut self, unary: &Interned<UnExpr>) -> fmt::Result {
|
||||||
write!(self.f, "un({:?})(", u.op)?;
|
write!(self.f, "un({:?})(", unary.op)?;
|
||||||
self.write_expr(&u.lhs)?;
|
self.write_expr(&unary.lhs)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_binary(&mut self, b: &Interned<BinExpr>) -> fmt::Result {
|
fn write_binary(&mut self, binary: &Interned<BinExpr>) -> fmt::Result {
|
||||||
let [lhs, rhs] = b.operands();
|
let [lhs, rhs] = binary.operands();
|
||||||
write!(self.f, "bin({:?})(", b.op)?;
|
write!(self.f, "bin({:?})(", binary.op)?;
|
||||||
self.write_expr(lhs)?;
|
self.write_expr(lhs)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(rhs)?;
|
self.write_expr(rhs)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_apply(&mut self, a: &Interned<ApplyExpr>) -> fmt::Result {
|
fn write_apply(&mut self, apply: &Interned<ApplyExpr>) -> fmt::Result {
|
||||||
write!(self.f, "apply(")?;
|
write!(self.f, "apply(")?;
|
||||||
self.write_expr(&a.callee)?;
|
self.write_expr(&apply.callee)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(&a.args)?;
|
self.write_expr(&apply.args)?;
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,121 +205,121 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_let(&mut self, l: &Interned<LetExpr>) -> fmt::Result {
|
fn write_let(&mut self, let_expr: &Interned<LetExpr>) -> fmt::Result {
|
||||||
write!(self.f, "let(")?;
|
write!(self.f, "let(")?;
|
||||||
self.write_pattern(&l.pattern)?;
|
self.write_pattern(&let_expr.pattern)?;
|
||||||
if let Some(body) = &l.body {
|
if let Some(body) = &let_expr.body {
|
||||||
write!(self.f, " = ")?;
|
write!(self.f, " = ")?;
|
||||||
self.write_expr(body)?;
|
self.write_expr(body)?;
|
||||||
}
|
}
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_show(&mut self, s: &Interned<ShowExpr>) -> fmt::Result {
|
fn write_show(&mut self, show: &Interned<ShowExpr>) -> fmt::Result {
|
||||||
write!(self.f, "show(")?;
|
write!(self.f, "show(")?;
|
||||||
if let Some(selector) = &s.selector {
|
if let Some(selector) = &show.selector {
|
||||||
self.write_expr(selector)?;
|
self.write_expr(selector)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
}
|
}
|
||||||
self.write_expr(&s.edit)?;
|
self.write_expr(&show.edit)?;
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_set(&mut self, s: &Interned<SetExpr>) -> fmt::Result {
|
fn write_set(&mut self, set: &Interned<SetExpr>) -> fmt::Result {
|
||||||
write!(self.f, "set(")?;
|
write!(self.f, "set(")?;
|
||||||
self.write_expr(&s.target)?;
|
self.write_expr(&set.target)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(&s.args)?;
|
self.write_expr(&set.args)?;
|
||||||
if let Some(cond) = &s.cond {
|
if let Some(cond) = &set.cond {
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(cond)?;
|
self.write_expr(cond)?;
|
||||||
}
|
}
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ref(&mut self, r: &Interned<RefExpr>) -> fmt::Result {
|
fn write_ref(&mut self, reference: &Interned<RefExpr>) -> fmt::Result {
|
||||||
write!(self.f, "ref({:?}", r.decl)?;
|
write!(self.f, "ref({:?}", reference.decl)?;
|
||||||
if let Some(step) = &r.step {
|
if let Some(step) = &reference.step {
|
||||||
self.f.write_str(", step = ")?;
|
self.f.write_str(", step = ")?;
|
||||||
self.write_expr(step)?;
|
self.write_expr(step)?;
|
||||||
}
|
}
|
||||||
if let Some(of) = &r.root {
|
if let Some(of) = &reference.root {
|
||||||
self.f.write_str(", root = ")?;
|
self.f.write_str(", root = ")?;
|
||||||
self.write_expr(of)?;
|
self.write_expr(of)?;
|
||||||
}
|
}
|
||||||
if let Some(val) = &r.val {
|
if let Some(val) = &reference.term {
|
||||||
write!(self.f, ", val = {val:?}")?;
|
write!(self.f, ", val = {val:?}")?;
|
||||||
}
|
}
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_content_ref(&mut self, r: &Interned<ContentRefExpr>) -> fmt::Result {
|
fn write_content_ref(&mut self, content_ref: &Interned<ContentRefExpr>) -> fmt::Result {
|
||||||
write!(self.f, "content_ref({:?}", r.ident)?;
|
write!(self.f, "content_ref({:?}", content_ref.ident)?;
|
||||||
if let Some(of) = &r.of {
|
if let Some(of) = &content_ref.of {
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_decl(of)?;
|
self.write_decl(of)?;
|
||||||
}
|
}
|
||||||
if let Some(val) = &r.body {
|
if let Some(val) = &content_ref.body {
|
||||||
self.write_expr(val)?;
|
self.write_expr(val)?;
|
||||||
}
|
}
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_select(&mut self, s: &Interned<SelectExpr>) -> fmt::Result {
|
fn write_select(&mut self, sel: &Interned<SelectExpr>) -> fmt::Result {
|
||||||
write!(self.f, "(")?;
|
write!(self.f, "(")?;
|
||||||
self.write_expr(&s.lhs)?;
|
self.write_expr(&sel.lhs)?;
|
||||||
self.f.write_str(").")?;
|
self.f.write_str(").")?;
|
||||||
self.write_decl(&s.key)
|
self.write_decl(&sel.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_import(&mut self, i: &Interned<ImportExpr>) -> fmt::Result {
|
fn write_import(&mut self, import: &Interned<ImportExpr>) -> fmt::Result {
|
||||||
self.f.write_str("import(")?;
|
self.f.write_str("import(")?;
|
||||||
self.write_decl(&i.decl.decl)?;
|
self.write_decl(&import.decl.decl)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_include(&mut self, i: &Interned<IncludeExpr>) -> fmt::Result {
|
fn write_include(&mut self, include: &Interned<IncludeExpr>) -> fmt::Result {
|
||||||
self.f.write_str("include(")?;
|
self.f.write_str("include(")?;
|
||||||
self.write_expr(&i.source)?;
|
self.write_expr(&include.source)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_contextual(&mut self, c: &Interned<Expr>) -> fmt::Result {
|
fn write_contextual(&mut self, contextual: &Interned<Expr>) -> fmt::Result {
|
||||||
self.f.write_str("contextual(")?;
|
self.f.write_str("contextual(")?;
|
||||||
self.write_expr(c)?;
|
self.write_expr(contextual)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_conditional(&mut self, c: &Interned<IfExpr>) -> fmt::Result {
|
fn write_conditional(&mut self, if_expr: &Interned<IfExpr>) -> fmt::Result {
|
||||||
self.f.write_str("if(")?;
|
self.f.write_str("if(")?;
|
||||||
self.write_expr(&c.cond)?;
|
self.write_expr(&if_expr.cond)?;
|
||||||
self.f.write_str(", then = ")?;
|
self.f.write_str(", then = ")?;
|
||||||
self.write_expr(&c.then)?;
|
self.write_expr(&if_expr.then)?;
|
||||||
self.f.write_str(", else = ")?;
|
self.f.write_str(", else = ")?;
|
||||||
self.write_expr(&c.else_)?;
|
self.write_expr(&if_expr.else_)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_while_loop(&mut self, w: &Interned<WhileExpr>) -> fmt::Result {
|
fn write_while_loop(&mut self, while_expr: &Interned<WhileExpr>) -> fmt::Result {
|
||||||
self.f.write_str("while(")?;
|
self.f.write_str("while(")?;
|
||||||
self.write_expr(&w.cond)?;
|
self.write_expr(&while_expr.cond)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(&w.body)?;
|
self.write_expr(&while_expr.body)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_for_loop(&mut self, f: &Interned<ForExpr>) -> fmt::Result {
|
fn write_for_loop(&mut self, for_expr: &Interned<ForExpr>) -> fmt::Result {
|
||||||
self.f.write_str("for(")?;
|
self.f.write_str("for(")?;
|
||||||
self.write_pattern(&f.pattern)?;
|
self.write_pattern(&for_expr.pattern)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(&f.iter)?;
|
self.write_expr(&for_expr.iter)?;
|
||||||
self.f.write_str(", ")?;
|
self.f.write_str(", ")?;
|
||||||
self.write_expr(&f.body)?;
|
self.write_expr(&for_expr.body)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_type(&mut self, t: &Ty) -> fmt::Result {
|
fn write_type(&mut self, ty: &Ty) -> fmt::Result {
|
||||||
let formatted = t.describe();
|
let formatted = ty.describe();
|
||||||
let formatted = formatted.as_deref().unwrap_or("any");
|
let formatted = formatted.as_deref().unwrap_or("any");
|
||||||
self.f.write_str(formatted)
|
self.f.write_str(formatted)
|
||||||
}
|
}
|
||||||
|
@ -352,27 +352,27 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
pub fn write_expr(&mut self, expr: &Expr) -> fmt::Result {
|
pub fn write_expr(&mut self, expr: &Expr) -> fmt::Result {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Block(..) => self.f.write_str("Expr(..)"),
|
Expr::Block(..) => self.f.write_str("Expr(..)"),
|
||||||
Expr::Array(a) => self.write_array(a),
|
Expr::Array(elems) => self.write_array(elems),
|
||||||
Expr::Dict(d) => self.write_dict(d),
|
Expr::Dict(elems) => self.write_dict(elems),
|
||||||
Expr::Args(a) => self.write_args(a),
|
Expr::Args(args) => self.write_args(args),
|
||||||
Expr::Pattern(p) => self.write_pattern(p),
|
Expr::Pattern(pat) => self.write_pattern(pat),
|
||||||
Expr::Element(e) => self.write_element(e),
|
Expr::Element(elem) => self.write_element(elem),
|
||||||
Expr::Unary(u) => self.write_unary(u),
|
Expr::Unary(unary) => self.write_unary(unary),
|
||||||
Expr::Binary(b) => self.write_binary(b),
|
Expr::Binary(binary) => self.write_binary(binary),
|
||||||
Expr::Apply(a) => self.write_apply(a),
|
Expr::Apply(apply) => self.write_apply(apply),
|
||||||
Expr::Func(func) => self.write_func(func),
|
Expr::Func(func) => self.write_func(func),
|
||||||
Expr::Ref(r) => self.write_ref(r),
|
Expr::Ref(ref_expr) => self.write_ref(ref_expr),
|
||||||
Expr::ContentRef(r) => self.write_content_ref(r),
|
Expr::ContentRef(content_ref) => self.write_content_ref(content_ref),
|
||||||
Expr::Select(s) => self.write_select(s),
|
Expr::Select(sel) => self.write_select(sel),
|
||||||
Expr::Import(i) => self.write_import(i),
|
Expr::Import(import) => self.write_import(import),
|
||||||
Expr::Include(i) => self.write_include(i),
|
Expr::Include(include) => self.write_include(include),
|
||||||
Expr::Contextual(..) => self.f.write_str("content"),
|
Expr::Contextual(..) => self.f.write_str("content"),
|
||||||
Expr::Let(..) | Expr::Show(..) | Expr::Set(..) => self.f.write_str("Expr(..)"),
|
Expr::Let(..) | Expr::Show(..) | Expr::Set(..) => self.f.write_str("Expr(..)"),
|
||||||
Expr::Conditional(..) | Expr::WhileLoop(..) | Expr::ForLoop(..) => {
|
Expr::Conditional(..) | Expr::WhileLoop(..) | Expr::ForLoop(..) => {
|
||||||
self.f.write_str("Expr(..)")
|
self.f.write_str("Expr(..)")
|
||||||
}
|
}
|
||||||
Expr::Type(t) => self.write_type(t),
|
Expr::Type(ty) => self.write_type(ty),
|
||||||
Expr::Decl(d) => self.write_decl(d),
|
Expr::Decl(decl) => self.write_decl(decl),
|
||||||
Expr::Star => self.f.write_str("*"),
|
Expr::Star => self.f.write_str("*"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,10 +381,10 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
write!(self.f, "{:indent$}", "", indent = self.indent)
|
write!(self.f, "{:indent$}", "", indent = self.indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_array(&mut self, a: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_array(&mut self, elems: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
if a.len() <= 1 {
|
if elems.len() <= 1 {
|
||||||
self.f.write_char('(')?;
|
self.f.write_char('(')?;
|
||||||
if let Some(arg) = a.first() {
|
if let Some(arg) = elems.first() {
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",")?
|
self.f.write_str(",")?
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
|
|
||||||
writeln!(self.f, "(")?;
|
writeln!(self.f, "(")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for arg in a.iter() {
|
for arg in elems.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -403,10 +403,10 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_dict(&mut self, d: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_dict(&mut self, elems: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
if d.len() <= 1 {
|
if elems.len() <= 1 {
|
||||||
self.f.write_char('(')?;
|
self.f.write_char('(')?;
|
||||||
if let Some(arg) = d.first() {
|
if let Some(arg) = elems.first() {
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
} else {
|
} else {
|
||||||
self.f.write_str(":")?
|
self.f.write_str(":")?
|
||||||
|
@ -416,7 +416,7 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
|
|
||||||
writeln!(self.f, "(:")?;
|
writeln!(self.f, "(:")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for arg in d.iter() {
|
for arg in elems.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -426,9 +426,9 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_args(&mut self, a: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
fn write_args(&mut self, args: &Interned<Vec<ArgExpr>>) -> fmt::Result {
|
||||||
writeln!(self.f, "(")?;
|
writeln!(self.f, "(")?;
|
||||||
for arg in a.iter() {
|
for arg in args.iter() {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_arg(arg)?;
|
self.write_arg(arg)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
|
@ -437,57 +437,57 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_arg(&mut self, a: &ArgExpr) -> fmt::Result {
|
fn write_arg(&mut self, arg: &ArgExpr) -> fmt::Result {
|
||||||
match a {
|
match arg {
|
||||||
ArgExpr::Pos(e) => self.write_expr(e),
|
ArgExpr::Pos(pos) => self.write_expr(pos),
|
||||||
ArgExpr::Named(n) => {
|
ArgExpr::Named(named) => {
|
||||||
let (k, v) = n.as_ref();
|
let (k, v) = named.as_ref();
|
||||||
self.write_decl(k)?;
|
self.write_decl(k)?;
|
||||||
write!(self.f, ": ")?;
|
write!(self.f, ": ")?;
|
||||||
self.write_expr(v)
|
self.write_expr(v)
|
||||||
}
|
}
|
||||||
ArgExpr::NamedRt(n) => {
|
ArgExpr::NamedRt(named) => {
|
||||||
let n = n.as_ref();
|
let n = named.as_ref();
|
||||||
self.write_expr(&n.0)?;
|
self.write_expr(&n.0)?;
|
||||||
write!(self.f, ": ")?;
|
write!(self.f, ": ")?;
|
||||||
self.write_expr(&n.1)
|
self.write_expr(&n.1)
|
||||||
}
|
}
|
||||||
ArgExpr::Spread(e) => {
|
ArgExpr::Spread(spread) => {
|
||||||
write!(self.f, "..")?;
|
write!(self.f, "..")?;
|
||||||
self.write_expr(e)
|
self.write_expr(spread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_pattern(&mut self, p: &Pattern) -> fmt::Result {
|
pub fn write_pattern(&mut self, pat: &Pattern) -> fmt::Result {
|
||||||
match p {
|
match pat {
|
||||||
Pattern::Expr(e) => self.write_expr(e),
|
Pattern::Expr(expr) => self.write_expr(expr),
|
||||||
Pattern::Simple(s) => self.write_decl(s),
|
Pattern::Simple(decl) => self.write_decl(decl),
|
||||||
Pattern::Sig(p) => self.write_pattern_sig(p),
|
Pattern::Sig(sig) => self.write_pattern_sig(sig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_pattern_sig(&mut self, p: &PatternSig) -> fmt::Result {
|
fn write_pattern_sig(&mut self, sig: &PatternSig) -> fmt::Result {
|
||||||
self.f.write_str("pat(\n")?;
|
self.f.write_str("pat(\n")?;
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
for pos in &p.pos {
|
for pos in &sig.pos {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
self.write_pattern(pos)?;
|
self.write_pattern(pos)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
}
|
}
|
||||||
for (name, pat) in &p.named {
|
for (name, pat) in &sig.named {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
write!(self.f, "{name:?} = ")?;
|
write!(self.f, "{name:?} = ")?;
|
||||||
self.write_pattern(pat)?;
|
self.write_pattern(pat)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
}
|
}
|
||||||
if let Some((k, rest)) = &p.spread_left {
|
if let Some((k, rest)) = &sig.spread_left {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
write!(self.f, "..{k:?}: ")?;
|
write!(self.f, "..{k:?}: ")?;
|
||||||
self.write_pattern(rest)?;
|
self.write_pattern(rest)?;
|
||||||
self.f.write_str(",\n")?;
|
self.f.write_str(",\n")?;
|
||||||
}
|
}
|
||||||
if let Some((k, rest)) = &p.spread_right {
|
if let Some((k, rest)) = &sig.spread_right {
|
||||||
self.write_indent()?;
|
self.write_indent()?;
|
||||||
write!(self.f, "..{k:?}: ")?;
|
write!(self.f, "..{k:?}: ")?;
|
||||||
self.write_pattern(rest)?;
|
self.write_pattern(rest)?;
|
||||||
|
@ -498,66 +498,66 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_element(&mut self, e: &Interned<ElementExpr>) -> fmt::Result {
|
fn write_element(&mut self, elem: &Interned<ElementExpr>) -> fmt::Result {
|
||||||
write!(self.f, "{:?}", e.elem.name())
|
write!(self.f, "{:?}", elem.elem.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_unary(&mut self, u: &Interned<UnExpr>) -> fmt::Result {
|
fn write_unary(&mut self, unary: &Interned<UnExpr>) -> fmt::Result {
|
||||||
use UnaryOp::*;
|
use UnaryOp::*;
|
||||||
match u.op {
|
match unary.op {
|
||||||
Pos => {
|
Pos => {
|
||||||
self.f.write_str("+")?;
|
self.f.write_str("+")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
Neg => {
|
Neg => {
|
||||||
self.f.write_str("-")?;
|
self.f.write_str("-")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
Not => {
|
Not => {
|
||||||
self.f.write_str("not ")?;
|
self.f.write_str("not ")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
Return => {
|
Return => {
|
||||||
self.f.write_str("return ")?;
|
self.f.write_str("return ")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
Context => {
|
Context => {
|
||||||
self.f.write_str("context ")?;
|
self.f.write_str("context ")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
Spread => {
|
Spread => {
|
||||||
self.f.write_str("..")?;
|
self.f.write_str("..")?;
|
||||||
self.write_expr(&u.lhs)
|
self.write_expr(&unary.lhs)
|
||||||
}
|
}
|
||||||
NotElementOf => {
|
NotElementOf => {
|
||||||
self.f.write_str("not elementOf(")?;
|
self.f.write_str("not elementOf(")?;
|
||||||
self.write_expr(&u.lhs)?;
|
self.write_expr(&unary.lhs)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
ElementOf => {
|
ElementOf => {
|
||||||
self.f.write_str("elementOf(")?;
|
self.f.write_str("elementOf(")?;
|
||||||
self.write_expr(&u.lhs)?;
|
self.write_expr(&unary.lhs)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
TypeOf => {
|
TypeOf => {
|
||||||
self.f.write_str("typeOf(")?;
|
self.f.write_str("typeOf(")?;
|
||||||
self.write_expr(&u.lhs)?;
|
self.write_expr(&unary.lhs)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_binary(&mut self, b: &Interned<BinExpr>) -> fmt::Result {
|
fn write_binary(&mut self, binary: &Interned<BinExpr>) -> fmt::Result {
|
||||||
let [lhs, rhs] = b.operands();
|
let [lhs, rhs] = binary.operands();
|
||||||
self.write_expr(lhs)?;
|
self.write_expr(lhs)?;
|
||||||
write!(self.f, " {} ", b.op.as_str())?;
|
write!(self.f, " {} ", binary.op.as_str())?;
|
||||||
self.write_expr(rhs)
|
self.write_expr(rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_apply(&mut self, a: &Interned<ApplyExpr>) -> fmt::Result {
|
fn write_apply(&mut self, apply: &Interned<ApplyExpr>) -> fmt::Result {
|
||||||
self.write_expr(&a.callee)?;
|
self.write_expr(&apply.callee)?;
|
||||||
write!(self.f, "(")?;
|
write!(self.f, "(")?;
|
||||||
self.write_expr(&a.args)?;
|
self.write_expr(&apply.args)?;
|
||||||
write!(self.f, ")")
|
write!(self.f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,42 +565,42 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
||||||
self.write_decl(&func.decl)
|
self.write_decl(&func.decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ref(&mut self, r: &Interned<RefExpr>) -> fmt::Result {
|
fn write_ref(&mut self, resolved: &Interned<RefExpr>) -> fmt::Result {
|
||||||
if let Some(r) = &r.root {
|
if let Some(root) = &resolved.root {
|
||||||
return self.write_expr(r);
|
return self.write_expr(root);
|
||||||
}
|
}
|
||||||
if let Some(r) = &r.val {
|
if let Some(term) = &resolved.term {
|
||||||
return self.write_type(r);
|
return self.write_type(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(self.f, "undefined({:?})", r.decl)
|
write!(self.f, "undefined({:?})", resolved.decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_content_ref(&mut self, r: &Interned<ContentRefExpr>) -> fmt::Result {
|
fn write_content_ref(&mut self, content_ref: &Interned<ContentRefExpr>) -> fmt::Result {
|
||||||
write!(self.f, "@{:?}", r.ident)
|
write!(self.f, "@{:?}", content_ref.ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_select(&mut self, s: &Interned<SelectExpr>) -> fmt::Result {
|
fn write_select(&mut self, sel: &Interned<SelectExpr>) -> fmt::Result {
|
||||||
write!(self.f, "")?;
|
write!(self.f, "")?;
|
||||||
self.write_expr(&s.lhs)?;
|
self.write_expr(&sel.lhs)?;
|
||||||
self.f.write_str(".")?;
|
self.f.write_str(".")?;
|
||||||
self.write_decl(&s.key)
|
self.write_decl(&sel.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_import(&mut self, i: &Interned<ImportExpr>) -> fmt::Result {
|
fn write_import(&mut self, import: &Interned<ImportExpr>) -> fmt::Result {
|
||||||
self.f.write_str("import(")?;
|
self.f.write_str("import(")?;
|
||||||
self.write_decl(&i.decl.decl)?;
|
self.write_decl(&import.decl.decl)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_include(&mut self, i: &Interned<IncludeExpr>) -> fmt::Result {
|
fn write_include(&mut self, include: &Interned<IncludeExpr>) -> fmt::Result {
|
||||||
self.f.write_str("include(")?;
|
self.f.write_str("include(")?;
|
||||||
self.write_expr(&i.source)?;
|
self.write_expr(&include.source)?;
|
||||||
self.f.write_str(")")
|
self.f.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_type(&mut self, t: &Ty) -> fmt::Result {
|
fn write_type(&mut self, ty: &Ty) -> fmt::Result {
|
||||||
let formatted = t.describe();
|
let formatted = ty.describe();
|
||||||
let formatted = formatted.as_deref().unwrap_or("any");
|
let formatted = formatted.as_deref().unwrap_or("any");
|
||||||
self.f.write_str(formatted)
|
self.f.write_str(formatted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,42 +97,42 @@ impl PathPreference {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ty {
|
impl Ty {
|
||||||
pub(crate) fn from_cast_info(s: &CastInfo) -> Ty {
|
pub(crate) fn from_cast_info(ty: &CastInfo) -> Ty {
|
||||||
match &s {
|
match &ty {
|
||||||
CastInfo::Any => Ty::Any,
|
CastInfo::Any => Ty::Any,
|
||||||
CastInfo::Value(v, doc) => Ty::Value(InsTy::new_doc(v.clone(), *doc)),
|
CastInfo::Value(val, doc) => Ty::Value(InsTy::new_doc(val.clone(), *doc)),
|
||||||
CastInfo::Type(ty) => Ty::Builtin(BuiltinTy::Type(*ty)),
|
CastInfo::Type(ty) => Ty::Builtin(BuiltinTy::Type(*ty)),
|
||||||
CastInfo::Union(e) => {
|
CastInfo::Union(types) => {
|
||||||
Ty::iter_union(UnionIter(vec![e.as_slice().iter()]).map(Self::from_cast_info))
|
Ty::iter_union(UnionIter(vec![types.as_slice().iter()]).map(Self::from_cast_info))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_param_site(f: &Func, p: &ParamInfo) -> Ty {
|
pub(crate) fn from_param_site(func: &Func, param: &ParamInfo) -> Ty {
|
||||||
use typst::foundations::func::Repr;
|
use typst::foundations::func::Repr;
|
||||||
match f.inner() {
|
match func.inner() {
|
||||||
Repr::Element(..) | Repr::Native(..) => {
|
Repr::Element(..) | Repr::Native(..) => {
|
||||||
if let Some(ty) = param_mapping(f, p) {
|
if let Some(ty) = param_mapping(func, param) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Repr::Closure(_) => {}
|
Repr::Closure(_) => {}
|
||||||
Repr::With(w) => return Ty::from_param_site(&w.0, p),
|
Repr::With(w) => return Ty::from_param_site(&w.0, param),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::from_cast_info(&p.input)
|
Self::from_cast_info(¶m.input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_return_site(f: &Func, c: &'_ CastInfo) -> Self {
|
pub(crate) fn from_return_site(func: &Func, ty: &'_ CastInfo) -> Self {
|
||||||
use typst::foundations::func::Repr;
|
use typst::foundations::func::Repr;
|
||||||
match f.inner() {
|
match func.inner() {
|
||||||
Repr::Element(e) => return Ty::Builtin(BuiltinTy::Element(*e)),
|
Repr::Element(elem) => return Ty::Builtin(BuiltinTy::Element(*elem)),
|
||||||
Repr::Closure(_) => {}
|
Repr::Closure(_) => {}
|
||||||
Repr::With(w) => return Ty::from_return_site(&w.0, c),
|
Repr::With(w) => return Ty::from_return_site(&w.0, ty),
|
||||||
Repr::Native(_) => {}
|
Repr::Native(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::from_cast_info(c)
|
Self::from_cast_info(ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,12 +144,12 @@ impl<'a> Iterator for UnionIter<'a> {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
let iter = self.0.last_mut()?;
|
let iter = self.0.last_mut()?;
|
||||||
if let Some(e) = iter.next() {
|
if let Some(ty) = iter.next() {
|
||||||
match e {
|
match ty {
|
||||||
CastInfo::Union(e) => {
|
CastInfo::Union(types) => {
|
||||||
self.0.push(e.as_slice().iter());
|
self.0.push(types.as_slice().iter());
|
||||||
}
|
}
|
||||||
_ => return Some(e),
|
_ => return Some(ty),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.0.pop();
|
self.0.pop();
|
||||||
|
@ -268,7 +268,7 @@ impl fmt::Debug for BuiltinTy {
|
||||||
BuiltinTy::Radius => write!(f, "Radius"),
|
BuiltinTy::Radius => write!(f, "Radius"),
|
||||||
BuiltinTy::TypeType(ty) => write!(f, "TypeType({})", ty.short_name()),
|
BuiltinTy::TypeType(ty) => write!(f, "TypeType({})", ty.short_name()),
|
||||||
BuiltinTy::Type(ty) => write!(f, "Type({})", ty.short_name()),
|
BuiltinTy::Type(ty) => write!(f, "Type({})", ty.short_name()),
|
||||||
BuiltinTy::Element(e) => e.fmt(f),
|
BuiltinTy::Element(elem) => elem.fmt(f),
|
||||||
BuiltinTy::Tag(tag) => {
|
BuiltinTy::Tag(tag) => {
|
||||||
let (name, id) = tag.as_ref();
|
let (name, id) = tag.as_ref();
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
|
|
|
@ -153,20 +153,20 @@ impl Ty {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a union type from an iterator of types
|
/// Create a union type from an iterator of types
|
||||||
pub fn from_types(e: impl ExactSizeIterator<Item = Ty>) -> Self {
|
pub fn from_types(iter: impl ExactSizeIterator<Item = Ty>) -> Self {
|
||||||
if e.len() == 0 {
|
if iter.len() == 0 {
|
||||||
Ty::Any
|
Ty::Any
|
||||||
} else if e.len() == 1 {
|
} else if iter.len() == 1 {
|
||||||
let mut e = e;
|
let mut iter = iter;
|
||||||
e.next().unwrap()
|
iter.next().unwrap()
|
||||||
} else {
|
} else {
|
||||||
Self::iter_union(e)
|
Self::iter_union(iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a union type from an iterator of types
|
/// Create a union type from an iterator of types
|
||||||
pub fn iter_union(e: impl IntoIterator<Item = Ty>) -> Self {
|
pub fn iter_union(iter: impl IntoIterator<Item = Ty>) -> Self {
|
||||||
let mut v: Vec<Ty> = e.into_iter().collect();
|
let mut v: Vec<Ty> = iter.into_iter().collect();
|
||||||
v.sort();
|
v.sort();
|
||||||
Ty::Union(Interned::new(v))
|
Ty::Union(Interned::new(v))
|
||||||
}
|
}
|
||||||
|
@ -681,7 +681,7 @@ impl RecordTy {
|
||||||
pub fn shape_fields(mut fields: Vec<(StrRef, Ty)>) -> (NameBone, Vec<Ty>) {
|
pub fn shape_fields(mut fields: Vec<(StrRef, Ty)>) -> (NameBone, Vec<Ty>) {
|
||||||
fields.sort_by(|a, b| a.0.cmp(&b.0));
|
fields.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
let names = NameBone {
|
let names = NameBone {
|
||||||
names: fields.iter().map(|e| e.0.clone()).collect(),
|
names: fields.iter().map(|(name, _)| name.clone()).collect(),
|
||||||
};
|
};
|
||||||
let types = fields.into_iter().map(|(_, ty)| ty).collect::<Vec<_>>();
|
let types = fields.into_iter().map(|(_, ty)| ty).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -979,10 +979,10 @@ impl SigTy {
|
||||||
|
|
||||||
let pos = sig_stream.zip(arg_stream);
|
let pos = sig_stream.zip(arg_stream);
|
||||||
let common_ifaces = withs
|
let common_ifaces = withs
|
||||||
.map(|e| e.iter().rev())
|
.map(|args_all| args_all.iter().rev())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|w| self.common_iface_fields(w))
|
.flat_map(|args| self.common_iface_fields(args))
|
||||||
.chain(self.common_iface_fields(args));
|
.chain(self.common_iface_fields(args));
|
||||||
let named = common_ifaces.map(|(_, l, r)| (l, r));
|
let named = common_ifaces.map(|(_, l, r)| (l, r));
|
||||||
|
|
||||||
|
@ -1158,9 +1158,9 @@ impl IfTy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type scheme on a group of syntax structures (typing)
|
/// The type information on a group of syntax structures (typing)
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TypeScheme {
|
pub struct TypeInfo {
|
||||||
/// Whether the typing is valid
|
/// Whether the typing is valid
|
||||||
pub valid: bool,
|
pub valid: bool,
|
||||||
/// The belonging file id
|
/// The belonging file id
|
||||||
|
@ -1181,7 +1181,7 @@ pub struct TypeScheme {
|
||||||
pub(super) cano_cache: Mutex<TypeCanoStore>,
|
pub(super) cano_cache: Mutex<TypeCanoStore>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyCtx for TypeScheme {
|
impl TyCtx for TypeInfo {
|
||||||
fn global_bounds(&self, var: &Interned<TypeVar>, _pol: bool) -> Option<DynTypeBounds> {
|
fn global_bounds(&self, var: &Interned<TypeVar>, _pol: bool) -> Option<DynTypeBounds> {
|
||||||
let v = self.vars.get(&var.def)?;
|
let v = self.vars.get(&var.def)?;
|
||||||
Some(v.bounds.bounds().read().clone())
|
Some(v.bounds.bounds().read().clone())
|
||||||
|
@ -1192,18 +1192,13 @@ impl TyCtx for TypeScheme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeScheme {
|
impl TypeInfo {
|
||||||
// Get the type of a definition
|
|
||||||
// pub fn type_of_def(&self, def: DefId) -> Option<Ty> {
|
|
||||||
// Some(self.simplify(self.vars.get(&def).map(|e| e.as_type())?, false))
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Gets the type of a syntax structure
|
/// Gets the type of a syntax structure
|
||||||
pub fn type_of_span(&self, site: Span) -> Option<Ty> {
|
pub fn type_of_span(&self, site: Span) -> Option<Ty> {
|
||||||
self.mapping
|
self.mapping
|
||||||
.get(&site)
|
.get(&site)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|e| Ty::from_types(e.into_iter()))
|
.map(|types| Ty::from_types(types.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: distinguish at least, at most
|
// todo: distinguish at least, at most
|
||||||
|
@ -1261,7 +1256,7 @@ impl TypeScheme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyCtxMut for TypeScheme {
|
impl TyCtxMut for TypeInfo {
|
||||||
type Snap = ena::undo_log::Snapshot;
|
type Snap = ena::undo_log::Snapshot;
|
||||||
|
|
||||||
fn start_scope(&mut self) -> Self::Snap {
|
fn start_scope(&mut self) -> Self::Snap {
|
||||||
|
|
|
@ -164,17 +164,17 @@ impl IfaceCheckDriver<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Type(e)) if self.value_as_iface() => {
|
Ty::Builtin(BuiltinTy::Type(b_ty)) if self.value_as_iface() => {
|
||||||
// todo: distinguish between element and function
|
// todo: distinguish between element and function
|
||||||
self.checker
|
self.checker
|
||||||
.check(Iface::Type { val: e, at: ty }, &mut self.ctx, pol);
|
.check(Iface::Type { val: b_ty, at: ty }, &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Element(e)) if self.value_as_iface() => {
|
Ty::Builtin(BuiltinTy::Element(elem)) if self.value_as_iface() => {
|
||||||
self.checker
|
self.checker
|
||||||
.check(Iface::Element { val: e, at: ty }, &mut self.ctx, pol);
|
.check(Iface::Element { val: elem, at: ty }, &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Module(e)) => {
|
Ty::Builtin(BuiltinTy::Module(module)) => {
|
||||||
if let Decl::Module(m) = e.as_ref() {
|
if let Decl::Module(m) = module.as_ref() {
|
||||||
self.checker
|
self.checker
|
||||||
.check(Iface::Module { val: m.fid, at: ty }, &mut self.ctx, pol);
|
.check(Iface::Module { val: m.fid, at: ty }, &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,18 @@ pub trait TyMutator {
|
||||||
Value(..) | Any | Boolean(..) | Builtin(..) => None,
|
Value(..) | Any | Boolean(..) | Builtin(..) => None,
|
||||||
Union(v) => Some(Union(self.mutate_vec(v, pol)?)),
|
Union(v) => Some(Union(self.mutate_vec(v, pol)?)),
|
||||||
Var(..) | Let(..) => None,
|
Var(..) | Let(..) => None,
|
||||||
Array(e) => Some(Array(self.mutate(e, pol)?.into())),
|
Array(arr) => Some(Array(self.mutate(arr, pol)?.into())),
|
||||||
Dict(r) => Some(Dict(self.mutate_record(r, pol)?.into())),
|
Dict(dict) => Some(Dict(self.mutate_record(dict, pol)?.into())),
|
||||||
Tuple(e) => Some(Tuple(self.mutate_vec(e, pol)?)),
|
Tuple(tup) => Some(Tuple(self.mutate_vec(tup, pol)?)),
|
||||||
Func(f) => Some(Func(self.mutate_func(f, pol)?.into())),
|
Func(func) => Some(Func(self.mutate_func(func, pol)?.into())),
|
||||||
Args(args) => Some(Args(self.mutate_func(args, pol)?.into())),
|
Args(args) => Some(Args(self.mutate_func(args, pol)?.into())),
|
||||||
Pattern(args) => Some(Pattern(self.mutate_func(args, pol)?.into())),
|
Pattern(pat) => Some(Pattern(self.mutate_func(pat, pol)?.into())),
|
||||||
Param(f) => Some(Param(self.mutate_param(f, pol)?.into())),
|
Param(param) => Some(Param(self.mutate_param(param, pol)?.into())),
|
||||||
Select(s) => Some(Select(self.mutate_select(s, pol)?.into())),
|
Select(sel) => Some(Select(self.mutate_select(sel, pol)?.into())),
|
||||||
With(w) => Some(With(self.mutate_with_sig(w, pol)?.into())),
|
With(sig) => Some(With(self.mutate_with_sig(sig, pol)?.into())),
|
||||||
Unary(u) => Some(Unary(self.mutate_unary(u, pol)?.into())),
|
Unary(unary) => Some(Unary(self.mutate_unary(unary, pol)?.into())),
|
||||||
Binary(b) => Some(Binary(self.mutate_binary(b, pol)?.into())),
|
Binary(binary) => Some(Binary(self.mutate_binary(binary, pol)?.into())),
|
||||||
If(i) => Some(If(self.mutate_if(i, pol)?.into())),
|
If(if_expr) => Some(If(self.mutate_if(if_expr, pol)?.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,33 +208,34 @@ impl SigCheckDriver<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Type(e)) if self.func_as_sig() => {
|
Ty::Builtin(BuiltinTy::Type(b_ty)) if self.func_as_sig() => {
|
||||||
// todo: distinguish between element and function
|
// todo: distinguish between element and function
|
||||||
self.checker
|
self.checker
|
||||||
.check(Sig::TypeCons { val: e, at: ty }, &mut self.ctx, pol);
|
.check(Sig::TypeCons { val: b_ty, at: ty }, &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Element(e)) if self.func_as_sig() => {
|
Ty::Builtin(BuiltinTy::Element(elem)) if self.func_as_sig() => {
|
||||||
// todo: distinguish between element and function
|
// todo: distinguish between element and function
|
||||||
let f = (*e).into();
|
let f = (*elem).into();
|
||||||
self.checker
|
self.checker
|
||||||
.check(Sig::Value { val: &f, at: ty }, &mut self.ctx, pol);
|
.check(Sig::Value { val: &f, at: ty }, &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Func(sig) if self.func_as_sig() => {
|
Ty::Func(sig) if self.func_as_sig() => {
|
||||||
self.checker.check(Sig::Type(sig), &mut self.ctx, pol);
|
self.checker.check(Sig::Type(sig), &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Array(sig) if self.array_as_sig() => {
|
Ty::Array(arr) if self.array_as_sig() => {
|
||||||
self.checker.check(Sig::ArrayCons(sig), &mut self.ctx, pol);
|
self.checker.check(Sig::ArrayCons(arr), &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Tuple(tup) if self.array_as_sig() => {
|
Ty::Tuple(elems) if self.array_as_sig() => {
|
||||||
self.checker.check(Sig::TupleCons(tup), &mut self.ctx, pol);
|
self.checker
|
||||||
|
.check(Sig::TupleCons(elems), &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::Dict(sig) if self.dict_as_sig() => {
|
Ty::Dict(sig) if self.dict_as_sig() => {
|
||||||
// self.check_dict_signature(sig, pol, self.checker);
|
// self.check_dict_signature(sig, pol, self.checker);
|
||||||
self.checker.check(Sig::DictCons(sig), &mut self.ctx, pol);
|
self.checker.check(Sig::DictCons(sig), &mut self.ctx, pol);
|
||||||
}
|
}
|
||||||
Ty::With(w) if self.func_as_sig() => {
|
Ty::With(sig) if self.func_as_sig() => {
|
||||||
self.ctx.args.push(w.with.clone());
|
self.ctx.args.push(sig.with.clone());
|
||||||
self.ty(&w.sig, pol);
|
self.ty(&sig.sig, pol);
|
||||||
self.ctx.args.pop();
|
self.ctx.args.pop();
|
||||||
}
|
}
|
||||||
Ty::Select(sel) => sel.ty.bounds(pol, &mut MethodDriver(self, &sel.select)),
|
Ty::Select(sel) => sel.ty.bounds(pol, &mut MethodDriver(self, &sel.select)),
|
||||||
|
@ -242,9 +243,9 @@ impl SigCheckDriver<'_> {
|
||||||
Ty::Unary(_) => {}
|
Ty::Unary(_) => {}
|
||||||
Ty::Binary(_) => {}
|
Ty::Binary(_) => {}
|
||||||
Ty::If(_) => {}
|
Ty::If(_) => {}
|
||||||
Ty::Param(p) => {
|
Ty::Param(param) => {
|
||||||
// todo: keep type information
|
// todo: keep type information
|
||||||
self.ty(&p.ty, pol);
|
self.ty(¶m.ty, pol);
|
||||||
}
|
}
|
||||||
_ if ty.has_bounds() => ty.bounds(pol, self),
|
_ if ty.has_bounds() => ty.bounds(pol, self),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -302,10 +303,10 @@ impl BoundChecker for MethodDriver<'_, '_> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Builtin(BuiltinTy::Element(e)) => {
|
Ty::Builtin(BuiltinTy::Element(elem)) => {
|
||||||
// todo: distinguish between element and function
|
// todo: distinguish between element and function
|
||||||
if self.is_binder() {
|
if self.is_binder() {
|
||||||
let f = (*e).into();
|
let f = (*elem).into();
|
||||||
self.0.checker.check(
|
self.0.checker.check(
|
||||||
Sig::Partialize(&Sig::Value { val: &f, at: ty }),
|
Sig::Partialize(&Sig::Value { val: &f, at: ty }),
|
||||||
&mut self.0.ctx,
|
&mut self.0.ctx,
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct CompactTy {
|
||||||
is_final: bool,
|
is_final: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeScheme {
|
impl TypeInfo {
|
||||||
/// Simplify (Canonicalize) the given type with the given type scheme.
|
/// Simplify (Canonicalize) the given type with the given type scheme.
|
||||||
pub fn simplify(&self, ty: Ty, principal: bool) -> Ty {
|
pub fn simplify(&self, ty: Ty, principal: bool) -> Ty {
|
||||||
let mut c = self.cano_cache.lock();
|
let mut c = self.cano_cache.lock();
|
||||||
|
@ -101,13 +101,13 @@ impl TypeSimplifier<'_, '_> {
|
||||||
self.analyze(p, pol);
|
self.analyze(p, pol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Tuple(e) => {
|
Ty::Tuple(tup) => {
|
||||||
for ty in e.iter() {
|
for ty in tup.iter() {
|
||||||
self.analyze(ty, pol);
|
self.analyze(ty, pol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Array(e) => {
|
Ty::Array(arr) => {
|
||||||
self.analyze(e, pol);
|
self.analyze(arr, pol);
|
||||||
}
|
}
|
||||||
Ty::With(w) => {
|
Ty::With(w) => {
|
||||||
self.analyze(&w.sig, pol);
|
self.analyze(&w.sig, pol);
|
||||||
|
@ -193,8 +193,8 @@ impl TypeSimplifier<'_, '_> {
|
||||||
|
|
||||||
Ty::Dict(f.into())
|
Ty::Dict(f.into())
|
||||||
}
|
}
|
||||||
Ty::Tuple(e) => Ty::Tuple(self.transform_seq(e, pol)),
|
Ty::Tuple(tup) => Ty::Tuple(self.transform_seq(tup, pol)),
|
||||||
Ty::Array(e) => Ty::Array(self.transform(e, pol).into()),
|
Ty::Array(arr) => Ty::Array(self.transform(arr, pol).into()),
|
||||||
Ty::With(w) => {
|
Ty::With(w) => {
|
||||||
let sig = self.transform(&w.sig, pol).into();
|
let sig = self.transform(&w.sig, pol).into();
|
||||||
// Negate the pol to make correct covariance
|
// Negate the pol to make correct covariance
|
||||||
|
|
|
@ -58,7 +58,7 @@ mod tests {
|
||||||
use insta::{assert_debug_snapshot, assert_snapshot};
|
use insta::{assert_debug_snapshot, assert_snapshot};
|
||||||
use tinymist_derive::BindTyCtx;
|
use tinymist_derive::BindTyCtx;
|
||||||
|
|
||||||
use super::{DynTypeBounds, Interned, Ty, TyCtx, TypeScheme, TypeVar};
|
use super::{DynTypeBounds, Interned, Ty, TyCtx, TypeInfo, TypeVar};
|
||||||
use crate::ty::tests::*;
|
use crate::ty::tests::*;
|
||||||
use crate::ty::ApplyChecker;
|
use crate::ty::ApplyChecker;
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -71,7 +71,7 @@ mod tests {
|
||||||
|
|
||||||
#[derive(Default, BindTyCtx)]
|
#[derive(Default, BindTyCtx)]
|
||||||
#[bind(0)]
|
#[bind(0)]
|
||||||
struct CallCollector(TypeScheme, Vec<Ty>);
|
struct CallCollector(TypeInfo, Vec<Ty>);
|
||||||
|
|
||||||
impl ApplyChecker for CallCollector {
|
impl ApplyChecker for CallCollector {
|
||||||
fn apply(
|
fn apply(
|
||||||
|
|
|
@ -721,7 +721,11 @@ impl<'a> CompletionContext<'a> {
|
||||||
/// Add completions for all available packages.
|
/// Add completions for all available packages.
|
||||||
fn package_completions(&mut self, all_versions: bool) {
|
fn package_completions(&mut self, all_versions: bool) {
|
||||||
let w = self.world().clone();
|
let w = self.world().clone();
|
||||||
let mut packages: Vec<_> = w.packages().iter().map(|e| (&e.0, e.1.clone())).collect();
|
let mut packages: Vec<_> = w
|
||||||
|
.packages()
|
||||||
|
.iter()
|
||||||
|
.map(|(spec, desc)| (spec, desc.clone()))
|
||||||
|
.collect();
|
||||||
// local_packages to references and add them to the packages
|
// local_packages to references and add them to the packages
|
||||||
let local_packages_refs = self.ctx.local_packages();
|
let local_packages_refs = self.ctx.local_packages();
|
||||||
packages.extend(
|
packages.extend(
|
||||||
|
|
|
@ -23,7 +23,7 @@ use crate::snippet::{
|
||||||
use crate::syntax::{
|
use crate::syntax::{
|
||||||
descent_decls, interpret_mode_at, is_ident_like, CursorClass, DescentDecl, InterpretMode,
|
descent_decls, interpret_mode_at, is_ident_like, CursorClass, DescentDecl, InterpretMode,
|
||||||
};
|
};
|
||||||
use crate::ty::{DynTypeBounds, Iface, IfaceChecker, InsTy, SigTy, TyCtx, TypeScheme, TypeVar};
|
use crate::ty::{DynTypeBounds, Iface, IfaceChecker, InsTy, SigTy, TyCtx, TypeInfo, TypeVar};
|
||||||
use crate::upstream::complete::complete_code;
|
use crate::upstream::complete::complete_code;
|
||||||
|
|
||||||
use crate::{completion_kind, prelude::*, LspCompletion};
|
use crate::{completion_kind, prelude::*, LspCompletion};
|
||||||
|
@ -629,7 +629,7 @@ fn check_previous_syntax(leaf: &LinkedNode) -> Option<SurroundingSyntax> {
|
||||||
#[derive(BindTyCtx)]
|
#[derive(BindTyCtx)]
|
||||||
#[bind(types)]
|
#[bind(types)]
|
||||||
struct Defines {
|
struct Defines {
|
||||||
types: Arc<TypeScheme>,
|
types: Arc<TypeInfo>,
|
||||||
defines: BTreeMap<EcoString, Ty>,
|
defines: BTreeMap<EcoString, Ty>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +659,7 @@ impl Defines {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyze_import_source(ctx: &LocalContext, types: &TypeScheme, s: ast::Expr) -> Option<Ty> {
|
fn analyze_import_source(ctx: &LocalContext, types: &TypeInfo, s: ast::Expr) -> Option<Ty> {
|
||||||
if let Some(res) = types.type_of_span(s.span()) {
|
if let Some(res) = types.type_of_span(s.span()) {
|
||||||
if !matches!(res.value(), Some(Value::Str(..))) {
|
if !matches!(res.value(), Some(Value::Str(..))) {
|
||||||
return Some(types.simplify(res, false));
|
return Some(types.simplify(res, false));
|
||||||
|
@ -1077,11 +1077,11 @@ impl TypeCompletionContext<'_, '_> {
|
||||||
self.type_completion(info, docs);
|
self.type_completion(info, docs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Let(e) => {
|
Ty::Let(bounds) => {
|
||||||
for ut in e.ubs.iter() {
|
for ut in bounds.ubs.iter() {
|
||||||
self.type_completion(ut, docs);
|
self.type_completion(ut, docs);
|
||||||
}
|
}
|
||||||
for lt in e.lbs.iter() {
|
for lt in bounds.lbs.iter() {
|
||||||
self.type_completion(lt, docs);
|
self.type_completion(lt, docs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1350,10 +1350,10 @@ impl TypeCompletionContext<'_, '_> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinTy::Element(e) => {
|
BuiltinTy::Element(elem) => {
|
||||||
self.ctx.value_completion(
|
self.ctx.value_completion(
|
||||||
Some(e.name().into()),
|
Some(elem.name().into()),
|
||||||
&Value::Func((*e).into()),
|
&Value::Func((*elem).into()),
|
||||||
true,
|
true,
|
||||||
docs,
|
docs,
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,18 +21,17 @@ impl SemanticRequest for WorkspaceLabelRequest {
|
||||||
|
|
||||||
let mut symbols = vec![];
|
let mut symbols = vec![];
|
||||||
|
|
||||||
for id in ctx.source_files().clone() {
|
for fid in ctx.source_files().clone() {
|
||||||
let Ok(source) = ctx.source_by_id(id) else {
|
let Ok(source) = ctx.source_by_id(fid) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let Ok(path) = ctx.path_for_id(id) else {
|
let Ok(path) = ctx.path_for_id(fid) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let uri = path_to_url(&path).unwrap();
|
let uri = path_to_url(&path).unwrap();
|
||||||
let res =
|
let res = get_lexical_hierarchy(&source, LexicalScopeKind::Symbol).map(|hierarchy| {
|
||||||
get_lexical_hierarchy(source.clone(), LexicalScopeKind::Symbol).map(|symbols| {
|
filter_document_labels(&hierarchy, &source, &uri, ctx.position_encoding())
|
||||||
filter_document_labels(&symbols, &source, &uri, ctx.position_encoding())
|
});
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(mut res) = res {
|
if let Some(mut res) = res {
|
||||||
symbols.append(&mut res)
|
symbols.append(&mut res)
|
||||||
|
@ -45,27 +44,28 @@ impl SemanticRequest for WorkspaceLabelRequest {
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn filter_document_labels(
|
fn filter_document_labels(
|
||||||
symbols: &[LexicalHierarchy],
|
hierarchy: &[LexicalHierarchy],
|
||||||
source: &Source,
|
source: &Source,
|
||||||
uri: &Url,
|
uri: &Url,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
) -> Vec<SymbolInformation> {
|
) -> Vec<SymbolInformation> {
|
||||||
symbols
|
hierarchy
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|e| {
|
.flat_map(|hierarchy| {
|
||||||
[e].into_iter()
|
[hierarchy]
|
||||||
.chain(e.children.as_deref().into_iter().flatten())
|
.into_iter()
|
||||||
|
.chain(hierarchy.children.as_deref().into_iter().flatten())
|
||||||
})
|
})
|
||||||
.flat_map(|e| {
|
.flat_map(|hierarchy| {
|
||||||
if !matches!(e.info.kind, LexicalKind::Var(LexicalVarKind::Label)) {
|
if !matches!(hierarchy.info.kind, LexicalKind::Var(LexicalVarKind::Label)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rng = typst_to_lsp::range(e.info.range.clone(), source, position_encoding);
|
let rng = typst_to_lsp::range(hierarchy.info.range.clone(), source, position_encoding);
|
||||||
|
|
||||||
Some(SymbolInformation {
|
Some(SymbolInformation {
|
||||||
name: e.info.name.to_string(),
|
name: hierarchy.info.name.to_string(),
|
||||||
kind: e.info.kind.clone().try_into().unwrap(),
|
kind: hierarchy.info.kind.clone().try_into().unwrap(),
|
||||||
tags: None,
|
tags: None,
|
||||||
deprecated: None,
|
deprecated: None,
|
||||||
location: LspLocation {
|
location: LspLocation {
|
||||||
|
|
|
@ -178,7 +178,7 @@ impl CompileOnceArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
let relative_entry = match entry.strip_prefix(&root) {
|
let relative_entry = match entry.strip_prefix(&root) {
|
||||||
Ok(e) => e,
|
Ok(relative_entry) => relative_entry,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
log::error!("entry path must be inside the root: {}", entry.display());
|
log::error!("entry path must be inside the root: {}", entry.display());
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
|
|
@ -245,7 +245,7 @@ impl PackageStorage {
|
||||||
description: Option<EcoString>,
|
description: Option<EcoString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let index: Vec<RemotePackageIndex> = match serde_json::from_reader(reader) {
|
let indices: Vec<RemotePackageIndex> = match serde_json::from_reader(reader) {
|
||||||
Ok(index) => index,
|
Ok(index) => index,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("Failed to parse package index: {err} from {url}");
|
log::error!("Failed to parse package index: {err} from {url}");
|
||||||
|
@ -253,16 +253,16 @@ impl PackageStorage {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
index
|
indices
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| {
|
.map(|index| {
|
||||||
(
|
(
|
||||||
PackageSpec {
|
PackageSpec {
|
||||||
namespace: "preview".into(),
|
namespace: "preview".into(),
|
||||||
name: e.name,
|
name: index.name,
|
||||||
version: e.version,
|
version: index.version,
|
||||||
},
|
},
|
||||||
e.description,
|
index.description,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|
|
@ -106,7 +106,7 @@ impl Typlite {
|
||||||
|
|
||||||
let main = world
|
let main = world
|
||||||
.source(current)
|
.source(current)
|
||||||
.map_err(|e| format!("getting source for main file: {e:?}"))?;
|
.map_err(|err| format!("getting source for main file: {err:?}"))?;
|
||||||
|
|
||||||
let worker = TypliteWorker {
|
let worker = TypliteWorker {
|
||||||
current,
|
current,
|
||||||
|
@ -456,7 +456,7 @@ impl TypliteWorker {
|
||||||
world.map_shadow_by_id(main_id, main).unwrap();
|
world.map_shadow_by_id(main_id, main).unwrap();
|
||||||
|
|
||||||
let document = typst::compile(&world).output;
|
let document = typst::compile(&world).output;
|
||||||
let document = document.map_err(|e| {
|
let document = document.map_err(|diagnostics| {
|
||||||
let mut err = String::new();
|
let mut err = String::new();
|
||||||
let _ = write!(err, "compiling node: ");
|
let _ = write!(err, "compiling node: ");
|
||||||
let write_span = |span: typst_syntax::Span, err: &mut String| {
|
let write_span = |span: typst_syntax::Span, err: &mut String| {
|
||||||
|
@ -483,7 +483,7 @@ impl TypliteWorker {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for s in e.iter() {
|
for s in diagnostics.iter() {
|
||||||
match s.severity {
|
match s.severity {
|
||||||
typst::diag::Severity::Error => {
|
typst::diag::Severity::Error => {
|
||||||
let _ = write!(err, "error: ");
|
let _ = write!(err, "error: ");
|
||||||
|
@ -585,8 +585,8 @@ impl TypliteWorker {
|
||||||
return Ok(Value::Content(s));
|
return Ok(Value::Content(s));
|
||||||
}
|
}
|
||||||
s.push('`');
|
s.push('`');
|
||||||
for e in raw.lines() {
|
for line in raw.lines() {
|
||||||
s.push_str(&Self::value(Self::str(e.to_untyped())?));
|
s.push_str(&Self::value(Self::str(line.to_untyped())?));
|
||||||
}
|
}
|
||||||
s.push('`');
|
s.push('`');
|
||||||
Ok(Value::Content(s))
|
Ok(Value::Content(s))
|
||||||
|
|
|
@ -72,8 +72,8 @@ impl RenderActor {
|
||||||
info!("RenderActor: resolving span: {:?}", element_path);
|
info!("RenderActor: resolving span: {:?}", element_path);
|
||||||
let spans = match self.renderer.resolve_span_by_element_path(&element_path) {
|
let spans = match self.renderer.resolve_span_by_element_path(&element_path) {
|
||||||
Ok(spans) => spans,
|
Ok(spans) => spans,
|
||||||
Err(e) => {
|
Err(err) => {
|
||||||
info!("RenderActor: failed to resolve span: {}", e);
|
info!("RenderActor: failed to resolve span: {err}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -201,7 +201,7 @@ impl<T: SourceFileServer + EditorServer> TypstActor<T> {
|
||||||
Some(ed)
|
Some(ed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Some(e), None) | (None, Some(e)) => Some(e),
|
(Some(info), None) | (None, Some(info)) => Some(info),
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ impl<T: SourceFileServer + EditorServer> TypstActor<T> {
|
||||||
}
|
}
|
||||||
Some(rng)
|
Some(rng)
|
||||||
}
|
}
|
||||||
(.., Some(e)) | (Some(e), None) => Some(e),
|
(.., Some(info)) | (Some(info), None) => Some(info),
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue