fix: replace last scope when checking import wildcard (#1563)

* fix: replace last scope when checking import wildcard

* test: add some tests
This commit is contained in:
Myriad-Dreamin 2025-03-21 13:31:25 +08:00 committed by GitHub
parent d86205d181
commit af78414788
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 106 additions and 3 deletions

View file

@ -0,0 +1,9 @@
/// path: base.typ
#let base() = 1;
-----
/// contains: base
#import "base.typ"
#import "base.typ": *
#base(/* range -2..0 */ );

View file

@ -0,0 +1,60 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on e( (64..66)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/item_shadow2.typ
---
[
{
"isIncomplete": false,
"items": [
{
"kind": 3,
"label": "base",
"labelDetails": {
"description": "() => any"
},
"sortText": "008",
"textEdit": {
"newText": "base()${1:}",
"range": {
"end": {
"character": 5,
"line": 3
},
"start": {
"character": 1,
"line": 3
}
}
}
}
]
},
{
"isIncomplete": false,
"items": [
{
"kind": 3,
"label": "base",
"labelDetails": {
"description": "() => any"
},
"sortText": "008",
"textEdit": {
"newText": "base()${1:}",
"range": {
"end": {
"character": 5,
"line": 3
},
"start": {
"character": 1,
"line": 3
}
}
}
}
]
}
]

View file

@ -0,0 +1,6 @@
---
source: crates/tinymist-query/src/semantic_tokens_full.rs
expression: "serde_json::to_string(&result).unwrap()"
input_file: crates/tinymist-query/src/fixtures/semantic_tokens/user_shadow.typ
---
{"data":[0,0,1,2,0,0,1,6,2,0,0,6,1,22,0,0,1,10,1,0,0,10,1,22,0,1,0,1,2,0,0,1,6,2,0,0,6,1,22,0,0,1,10,1,0,0,10,1,10,0,0,1,1,22,0,0,1,1,3,0,0,1,1,22,0,1,0,1,5,0,0,1,4,5,0,0,4,1,10,0,0,1,1,22,0]}

View file

@ -0,0 +1,8 @@
/// path: base.typ
#let base() = 1;
-----
#import "base.typ"
#import "base.typ": *
#base;

View file

@ -117,6 +117,15 @@ impl ExprScope {
ExprScope::Lexical(LexicalScope::default())
}
pub fn is_empty(&self) -> bool {
match self {
ExprScope::Lexical(scope) => scope.is_empty(),
ExprScope::Module(module) => is_empty_scope(module.scope()),
ExprScope::Func(func) => func.scope().is_none_or(is_empty_scope),
ExprScope::Type(ty) => is_empty_scope(ty.scope()),
}
}
pub fn get(&self, name: &Interned<str>) -> (Option<Expr>, Option<Ty>) {
let (of, val) = match self {
ExprScope::Lexical(scope) => {
@ -946,6 +955,10 @@ impl<T> BinInst<T> {
}
}
fn is_empty_scope(scope: &typst::foundations::Scope) -> bool {
scope.iter().next().is_none()
}
impl_internable!(
Expr,
ArgsExpr,

View file

@ -264,7 +264,7 @@ impl ExprWorker<'_> {
fn with_scope<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
self.lexical.scopes.push(std::mem::replace(
&mut self.lexical.last,
ExprScope::Lexical(RedBlackTreeMapSync::default()),
ExprScope::empty(),
));
let len = self.lexical.scopes.len();
let result = f(self);
@ -273,6 +273,13 @@ impl ExprWorker<'_> {
result
}
fn push_scope(&mut self, scope: ExprScope) {
let last = std::mem::replace(&mut self.lexical.last, scope);
if !last.is_empty() {
self.lexical.scopes.push(last);
}
}
#[must_use]
fn scope_mut(&mut self) -> &mut LexicalScope {
if matches!(self.lexical.last, ExprScope::Lexical(_)) {
@ -280,7 +287,7 @@ impl ExprWorker<'_> {
}
self.lexical.scopes.push(std::mem::replace(
&mut self.lexical.last,
ExprScope::Lexical(RedBlackTreeMapSync::default()),
ExprScope::empty(),
));
self.lexical_scope_unchecked()
}
@ -717,7 +724,7 @@ impl ExprWorker<'_> {
match imports {
ast::Imports::Wildcard => {
crate::log_debug_ct!("checking wildcard: {mod_expr:?}");
self.lexical.scopes.push(scope);
self.push_scope(scope);
}
ast::Imports::Items(items) => {
let module = Expr::Decl(mod_var.clone());