@tishlang/tish 1.9.2 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/tish +0 -0
- package/crates/js_to_tish/src/transform/expr.rs +8 -6
- package/crates/js_to_tish/src/transform/stmt.rs +12 -13
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/src/cargo_native_registry.rs +4 -1
- package/crates/tish/src/cli_help.rs +9 -1
- package/crates/tish/src/main.rs +66 -11
- package/crates/tish/tests/integration_test.rs +145 -7
- package/crates/tish_ast/src/ast.rs +3 -9
- package/crates/tish_build_utils/src/lib.rs +74 -23
- package/crates/tish_builtins/src/array.rs +2 -3
- package/crates/tish_builtins/src/construct.rs +15 -28
- package/crates/tish_builtins/src/globals.rs +18 -16
- package/crates/tish_builtins/src/helpers.rs +1 -4
- package/crates/tish_builtins/src/lib.rs +1 -0
- package/crates/tish_builtins/src/math.rs +7 -0
- package/crates/tish_builtins/src/object.rs +10 -10
- package/crates/tish_builtins/src/string.rs +27 -3
- package/crates/tish_builtins/src/symbol.rs +83 -0
- package/crates/tish_compile/src/codegen.rs +324 -158
- package/crates/tish_compile/src/lib.rs +39 -7
- package/crates/tish_compile/src/resolve.rs +191 -6
- package/crates/tish_compile/src/types.rs +6 -6
- package/crates/tish_compile_js/src/codegen.rs +8 -5
- package/crates/tish_core/src/console_style.rs +9 -0
- package/crates/tish_core/src/json.rs +17 -7
- package/crates/tish_core/src/macros.rs +2 -2
- package/crates/tish_core/src/value.rs +213 -4
- package/crates/tish_cranelift/src/link.rs +1 -1
- package/crates/tish_cranelift_runtime/Cargo.toml +4 -0
- package/crates/tish_eval/src/eval.rs +135 -73
- package/crates/tish_eval/src/http.rs +18 -12
- package/crates/tish_eval/src/lib.rs +29 -0
- package/crates/tish_eval/src/regex.rs +1 -1
- package/crates/tish_eval/src/value.rs +89 -4
- package/crates/tish_eval/src/value_convert.rs +30 -8
- package/crates/tish_fmt/src/lib.rs +4 -1
- package/crates/tish_lexer/src/lib.rs +7 -2
- package/crates/tish_llvm/src/lib.rs +2 -2
- package/crates/tish_lsp/src/builtin_goto.rs +111 -10
- package/crates/tish_lsp/src/import_goto.rs +35 -22
- package/crates/tish_lsp/src/main.rs +118 -85
- package/crates/tish_native/src/build.rs +270 -24
- package/crates/tish_native/src/config.rs +48 -0
- package/crates/tish_native/src/lib.rs +139 -12
- package/crates/tish_parser/src/lib.rs +5 -2
- package/crates/tish_parser/src/parser.rs +45 -75
- package/crates/tish_pg/src/error.rs +1 -1
- package/crates/tish_pg/src/lib.rs +61 -73
- package/crates/tish_resolve/src/lib.rs +283 -158
- package/crates/tish_resolve/src/pos.rs +10 -2
- package/crates/tish_runtime/Cargo.toml +3 -0
- package/crates/tish_runtime/src/http.rs +39 -39
- package/crates/tish_runtime/src/http_fetch.rs +12 -12
- package/crates/tish_runtime/src/lib.rs +35 -44
- package/crates/tish_runtime/src/native_promise.rs +0 -11
- package/crates/tish_runtime/src/promise.rs +14 -1
- package/crates/tish_runtime/src/promise_io.rs +1 -4
- package/crates/tish_runtime/src/timers.rs +12 -7
- package/crates/tish_runtime/src/ws.rs +40 -27
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +10 -8
- package/crates/tish_ui/src/jsx.rs +6 -4
- package/crates/tish_ui/src/lib.rs +5 -4
- package/crates/tish_ui/src/runtime/hooks.rs +123 -37
- package/crates/tish_ui/src/runtime/mod.rs +21 -41
- package/crates/tish_vm/Cargo.toml +2 -0
- package/crates/tish_vm/src/vm.rs +258 -153
- package/crates/tish_wasm/src/lib.rs +60 -7
- package/crates/tish_wasm_runtime/Cargo.toml +10 -1
- package/crates/tish_wasm_runtime/src/gpu.rs +413 -0
- package/crates/tish_wasm_runtime/src/lib.rs +7 -1
- package/crates/tishlang_cargo_bindgen/src/classify.rs +1 -3
- package/crates/tishlang_cargo_bindgen/src/discover.rs +10 -5
- package/crates/tishlang_cargo_bindgen/src/infer.rs +18 -8
- package/crates/tishlang_cargo_bindgen/src/lib.rs +25 -26
- package/crates/tishlang_cargo_bindgen/src/main.rs +41 -38
- package/crates/tishlang_cargo_bindgen/src/metadata.rs +4 -1
- package/justfile +3 -3
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
|
@@ -12,9 +12,83 @@ use std::sync::Arc;
|
|
|
12
12
|
use ahash::AHashMap;
|
|
13
13
|
use tishlang_ast::{FunParam, Statement};
|
|
14
14
|
use tishlang_core::NativeFn as CoreNativeFn;
|
|
15
|
+
use tishlang_core::TishSymbol;
|
|
15
16
|
|
|
16
|
-
/// Property map for interpreter
|
|
17
|
+
/// Property map for interpreter object string keys (uses `eval::Value`, not `tishlang_core::Value`).
|
|
17
18
|
pub type PropMap = AHashMap<Arc<str>, Value>;
|
|
19
|
+
|
|
20
|
+
/// Interpreter object: string keys plus optional symbol-keyed properties.
|
|
21
|
+
#[derive(Clone, Debug, Default)]
|
|
22
|
+
pub struct EvalObjectData {
|
|
23
|
+
pub strings: PropMap,
|
|
24
|
+
pub symbols: Option<AHashMap<u64, Value>>,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl EvalObjectData {
|
|
28
|
+
pub fn from_strings(strings: PropMap) -> Self {
|
|
29
|
+
Self {
|
|
30
|
+
strings,
|
|
31
|
+
symbols: None,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub fn eval_object_get(obj: &Value, key: &Value) -> Option<Value> {
|
|
37
|
+
let Value::Object(od) = obj else {
|
|
38
|
+
return None;
|
|
39
|
+
};
|
|
40
|
+
let b = od.borrow();
|
|
41
|
+
match key {
|
|
42
|
+
Value::Symbol(s) => b.symbols.as_ref()?.get(&s.id).cloned(),
|
|
43
|
+
Value::Number(n) => {
|
|
44
|
+
let k: Arc<str> = n.to_string().into();
|
|
45
|
+
b.strings.get(&k).cloned()
|
|
46
|
+
}
|
|
47
|
+
Value::String(k) => b.strings.get(k.as_ref()).cloned(),
|
|
48
|
+
_ => None,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
pub fn eval_object_set(obj: &Value, key: &Value, val: Value) -> Result<(), String> {
|
|
53
|
+
let Value::Object(od) = obj else {
|
|
54
|
+
return Err("Cannot set property on non-object".to_string());
|
|
55
|
+
};
|
|
56
|
+
let mut b = od.borrow_mut();
|
|
57
|
+
match key {
|
|
58
|
+
Value::Symbol(s) => {
|
|
59
|
+
if b.symbols.is_none() {
|
|
60
|
+
b.symbols = Some(AHashMap::default());
|
|
61
|
+
}
|
|
62
|
+
b.symbols.as_mut().unwrap().insert(s.id, val);
|
|
63
|
+
Ok(())
|
|
64
|
+
}
|
|
65
|
+
Value::Number(n) => {
|
|
66
|
+
b.strings.insert(n.to_string().into(), val);
|
|
67
|
+
Ok(())
|
|
68
|
+
}
|
|
69
|
+
Value::String(k) => {
|
|
70
|
+
b.strings.insert(Arc::clone(k), val);
|
|
71
|
+
Ok(())
|
|
72
|
+
}
|
|
73
|
+
_ => Err("Object key must be string, number, or symbol".to_string()),
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
pub fn eval_object_has(obj: &Value, key: &Value) -> bool {
|
|
78
|
+
let Value::Object(od) = obj else {
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
81
|
+
let b = od.borrow();
|
|
82
|
+
match key {
|
|
83
|
+
Value::Symbol(s) => b.symbols.as_ref().is_some_and(|m| m.contains_key(&s.id)),
|
|
84
|
+
Value::Number(n) => {
|
|
85
|
+
let k: Arc<str> = n.to_string().into();
|
|
86
|
+
b.strings.contains_key(&k)
|
|
87
|
+
}
|
|
88
|
+
Value::String(k) => b.strings.contains_key(k.as_ref()),
|
|
89
|
+
_ => false,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
18
92
|
use tishlang_core::TishOpaque;
|
|
19
93
|
#[cfg(feature = "http")]
|
|
20
94
|
use tishlang_core::TishPromise;
|
|
@@ -34,7 +108,8 @@ pub enum Value {
|
|
|
34
108
|
Bool(bool),
|
|
35
109
|
Null,
|
|
36
110
|
Array(Rc<RefCell<Vec<Value>>>),
|
|
37
|
-
Object(Rc<RefCell<
|
|
111
|
+
Object(Rc<RefCell<EvalObjectData>>),
|
|
112
|
+
Symbol(Arc<TishSymbol>),
|
|
38
113
|
/// User-defined function with AST body
|
|
39
114
|
Function {
|
|
40
115
|
formals: Arc<[FunParam]>,
|
|
@@ -109,6 +184,7 @@ impl std::fmt::Debug for Value {
|
|
|
109
184
|
Value::CoreFn(_) => write!(f, "CoreFn"),
|
|
110
185
|
Value::Opaque(o) => write!(f, "{}(opaque)", o.type_name()),
|
|
111
186
|
Value::OpaqueMethod(_, _) => write!(f, "[Function]"),
|
|
187
|
+
Value::Symbol(s) => write!(f, "Symbol({})", s.id),
|
|
112
188
|
}
|
|
113
189
|
}
|
|
114
190
|
}
|
|
@@ -137,11 +213,19 @@ impl std::fmt::Display for Value {
|
|
|
137
213
|
Value::Object(obj) => {
|
|
138
214
|
let inner: Vec<String> = obj
|
|
139
215
|
.borrow()
|
|
216
|
+
.strings
|
|
140
217
|
.iter()
|
|
141
218
|
.map(|(k, v)| format!("{}: {}", k.as_ref(), v))
|
|
142
219
|
.collect();
|
|
143
220
|
write!(f, "{{{}}}", inner.join(", "))
|
|
144
221
|
}
|
|
222
|
+
Value::Symbol(s) => {
|
|
223
|
+
if let Some(d) = &s.description {
|
|
224
|
+
write!(f, "Symbol({})", d)
|
|
225
|
+
} else {
|
|
226
|
+
write!(f, "Symbol()")
|
|
227
|
+
}
|
|
228
|
+
}
|
|
145
229
|
Value::Function { .. } => write!(f, "[Function]"),
|
|
146
230
|
Value::Native(_) => write!(f, "[NativeFunction]"),
|
|
147
231
|
#[cfg(feature = "http")]
|
|
@@ -195,6 +279,7 @@ impl Value {
|
|
|
195
279
|
(Value::Null, Value::Null) => true,
|
|
196
280
|
(Value::Array(a), Value::Array(b)) => Rc::ptr_eq(a, b),
|
|
197
281
|
(Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b),
|
|
282
|
+
(Value::Symbol(a), Value::Symbol(b)) => Arc::ptr_eq(a, b),
|
|
198
283
|
(Value::Opaque(a), Value::Opaque(b)) => Arc::ptr_eq(a, b),
|
|
199
284
|
(Value::OpaqueMethod(a, ak), Value::OpaqueMethod(b, bk)) => {
|
|
200
285
|
Arc::ptr_eq(a, b) && ak == bk
|
|
@@ -210,7 +295,7 @@ impl Value {
|
|
|
210
295
|
|
|
211
296
|
/// Create a new object Value from a property map.
|
|
212
297
|
pub fn object(map: PropMap) -> Self {
|
|
213
|
-
Value::Object(Rc::new(RefCell::new(map)))
|
|
298
|
+
Value::Object(Rc::new(RefCell::new(EvalObjectData::from_strings(map))))
|
|
214
299
|
}
|
|
215
300
|
|
|
216
301
|
/// Create an empty array Value.
|
|
@@ -220,7 +305,7 @@ impl Value {
|
|
|
220
305
|
|
|
221
306
|
/// Create an empty object Value.
|
|
222
307
|
pub fn empty_object() -> Self {
|
|
223
|
-
Value::Object(Rc::new(RefCell::new(
|
|
308
|
+
Value::Object(Rc::new(RefCell::new(EvalObjectData::default())))
|
|
224
309
|
}
|
|
225
310
|
|
|
226
311
|
/// Extract the number value, if this is a Number.
|
|
@@ -4,11 +4,12 @@ use std::cell::RefCell;
|
|
|
4
4
|
use std::rc::Rc;
|
|
5
5
|
use std::sync::Arc;
|
|
6
6
|
|
|
7
|
-
use tishlang_core::{ObjectMap, Value as CoreValue, VmRef};
|
|
8
7
|
#[cfg(feature = "regex")]
|
|
9
8
|
use tishlang_core::TishRegExp;
|
|
9
|
+
use ahash::AHashMap;
|
|
10
|
+
use tishlang_core::{ObjectData, ObjectMap, Value as CoreValue, VmRef};
|
|
10
11
|
|
|
11
|
-
use crate::value::{PropMap, Value};
|
|
12
|
+
use crate::value::{EvalObjectData, PropMap, Value};
|
|
12
13
|
|
|
13
14
|
/// Convert interpreter Value to core Value. Fails for interpreter-only variants.
|
|
14
15
|
pub fn eval_to_core(v: &Value) -> Result<CoreValue, String> {
|
|
@@ -25,12 +26,23 @@ pub fn eval_to_core(v: &Value) -> Result<CoreValue, String> {
|
|
|
25
26
|
Ok(CoreValue::Array(VmRef::new(out)))
|
|
26
27
|
}
|
|
27
28
|
Value::Object(map) => {
|
|
28
|
-
let
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
let b = map.borrow();
|
|
30
|
+
let mut strings = ObjectMap::default();
|
|
31
|
+
for (k, v) in b.strings.iter() {
|
|
32
|
+
strings.insert(Arc::clone(k), eval_to_core(v)?);
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
let symbols = if let Some(ss) = &b.symbols {
|
|
35
|
+
let mut sm = AHashMap::default();
|
|
36
|
+
for (id, v) in ss.iter() {
|
|
37
|
+
sm.insert(*id, eval_to_core(v)?);
|
|
38
|
+
}
|
|
39
|
+
Some(sm)
|
|
40
|
+
} else {
|
|
41
|
+
None
|
|
42
|
+
};
|
|
43
|
+
Ok(CoreValue::Object(VmRef::new(ObjectData { strings, symbols })))
|
|
33
44
|
}
|
|
45
|
+
Value::Symbol(s) => Ok(CoreValue::Symbol(Arc::clone(s))),
|
|
34
46
|
Value::Opaque(o) => Ok(CoreValue::Opaque(Arc::clone(o))),
|
|
35
47
|
_ => Err(format!(
|
|
36
48
|
"Cannot pass {:?} to native function (unsupported type)",
|
|
@@ -54,12 +66,22 @@ pub fn core_to_eval(v: CoreValue) -> Value {
|
|
|
54
66
|
Value::Array(Rc::new(RefCell::new(out)))
|
|
55
67
|
}
|
|
56
68
|
CoreValue::Object(map) => {
|
|
69
|
+
let b = map.borrow();
|
|
57
70
|
let mut out = PropMap::default();
|
|
58
|
-
for (k, v) in
|
|
71
|
+
for (k, v) in b.strings.iter() {
|
|
59
72
|
out.insert(Arc::clone(k), core_to_eval(v.clone()));
|
|
60
73
|
}
|
|
61
|
-
|
|
74
|
+
let mut eod = EvalObjectData::from_strings(out);
|
|
75
|
+
if let Some(ss) = &b.symbols {
|
|
76
|
+
let mut es = AHashMap::default();
|
|
77
|
+
for (id, v) in ss.iter() {
|
|
78
|
+
es.insert(*id, core_to_eval(v.clone()));
|
|
79
|
+
}
|
|
80
|
+
eod.symbols = Some(es);
|
|
81
|
+
}
|
|
82
|
+
Value::Object(Rc::new(RefCell::new(eod)))
|
|
62
83
|
}
|
|
84
|
+
CoreValue::Symbol(s) => Value::Symbol(Arc::clone(&s)),
|
|
63
85
|
CoreValue::Opaque(o) => Value::Opaque(o),
|
|
64
86
|
#[cfg(feature = "http")]
|
|
65
87
|
CoreValue::Promise(p) => Value::CorePromise(Arc::clone(&p)),
|
|
@@ -1023,7 +1023,10 @@ mod tests {
|
|
|
1023
1023
|
fn jsx_multiline_when_mixed_children() {
|
|
1024
1024
|
let src = "let x = <div>a{b}</div>\n";
|
|
1025
1025
|
let out = format_source(src).unwrap();
|
|
1026
|
-
assert!(
|
|
1026
|
+
assert!(
|
|
1027
|
+
out.contains('\n'),
|
|
1028
|
+
"expected line breaks in formatted JSX: {out:?}"
|
|
1029
|
+
);
|
|
1027
1030
|
let _ = tishlang_parser::parse(&out).unwrap();
|
|
1028
1031
|
}
|
|
1029
1032
|
}
|
|
@@ -701,11 +701,16 @@ mod tests {
|
|
|
701
701
|
#[test]
|
|
702
702
|
fn line_comment_does_not_emit_spurious_indent_before_next_line() {
|
|
703
703
|
let with_comment = "fn f() {\n return {\n a: 1, // c\n b: 2\n }\n}\n";
|
|
704
|
-
let tokens: Vec<_> = Lexer::new(with_comment)
|
|
704
|
+
let tokens: Vec<_> = Lexer::new(with_comment)
|
|
705
|
+
.collect::<Result<Vec<_>, _>>()
|
|
706
|
+
.unwrap();
|
|
705
707
|
assert!(
|
|
706
708
|
!tokens.iter().any(|t| t.kind == TokenKind::Indent),
|
|
707
709
|
"unexpected Indent after line comment: {:?}",
|
|
708
|
-
tokens
|
|
710
|
+
tokens
|
|
711
|
+
.iter()
|
|
712
|
+
.map(|t| format!("{:?}", t.kind))
|
|
713
|
+
.collect::<Vec<_>>()
|
|
709
714
|
);
|
|
710
715
|
}
|
|
711
716
|
}
|
|
@@ -26,8 +26,8 @@ pub fn compile_to_native(
|
|
|
26
26
|
let program = merge_modules(modules)
|
|
27
27
|
.map(|m| m.program)
|
|
28
28
|
.map_err(|e| LlvmError {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
message: e.to_string(),
|
|
30
|
+
})?;
|
|
31
31
|
let chunk = tishlang_bytecode::compile(&program).map_err(|e| LlvmError {
|
|
32
32
|
message: e.to_string(),
|
|
33
33
|
})?;
|
|
@@ -33,16 +33,117 @@ fn is_ident_char(c: char) -> bool {
|
|
|
33
33
|
|
|
34
34
|
/// HTML / SVG intrinsic tag names (lowercase) that JSX lowers to `h("tag", …)`; must stay sorted for `binary_search`.
|
|
35
35
|
const HTML_INTRINSIC_TAGS: &[&str] = &[
|
|
36
|
-
"a",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
36
|
+
"a",
|
|
37
|
+
"abbr",
|
|
38
|
+
"address",
|
|
39
|
+
"area",
|
|
40
|
+
"article",
|
|
41
|
+
"aside",
|
|
42
|
+
"audio",
|
|
43
|
+
"b",
|
|
44
|
+
"base",
|
|
45
|
+
"bdi",
|
|
46
|
+
"bdo",
|
|
47
|
+
"blockquote",
|
|
48
|
+
"body",
|
|
49
|
+
"br",
|
|
50
|
+
"button",
|
|
51
|
+
"canvas",
|
|
52
|
+
"caption",
|
|
53
|
+
"cite",
|
|
54
|
+
"code",
|
|
55
|
+
"col",
|
|
56
|
+
"colgroup",
|
|
57
|
+
"data",
|
|
58
|
+
"datalist",
|
|
59
|
+
"dd",
|
|
60
|
+
"del",
|
|
61
|
+
"details",
|
|
62
|
+
"dfn",
|
|
63
|
+
"dialog",
|
|
64
|
+
"div",
|
|
65
|
+
"dl",
|
|
66
|
+
"dt",
|
|
67
|
+
"em",
|
|
68
|
+
"embed",
|
|
69
|
+
"fieldset",
|
|
70
|
+
"figcaption",
|
|
71
|
+
"figure",
|
|
72
|
+
"footer",
|
|
73
|
+
"form",
|
|
74
|
+
"h1",
|
|
75
|
+
"h2",
|
|
76
|
+
"h3",
|
|
77
|
+
"h4",
|
|
78
|
+
"h5",
|
|
79
|
+
"h6",
|
|
80
|
+
"head",
|
|
81
|
+
"header",
|
|
82
|
+
"hr",
|
|
83
|
+
"html",
|
|
84
|
+
"i",
|
|
85
|
+
"iframe",
|
|
86
|
+
"img",
|
|
87
|
+
"input",
|
|
88
|
+
"ins",
|
|
89
|
+
"kbd",
|
|
90
|
+
"label",
|
|
91
|
+
"legend",
|
|
92
|
+
"li",
|
|
93
|
+
"link",
|
|
94
|
+
"main",
|
|
95
|
+
"map",
|
|
96
|
+
"mark",
|
|
97
|
+
"meta",
|
|
98
|
+
"meter",
|
|
99
|
+
"nav",
|
|
100
|
+
"noscript",
|
|
101
|
+
"object",
|
|
102
|
+
"ol",
|
|
103
|
+
"optgroup",
|
|
104
|
+
"option",
|
|
105
|
+
"output",
|
|
106
|
+
"p",
|
|
107
|
+
"param",
|
|
108
|
+
"picture",
|
|
109
|
+
"pre",
|
|
110
|
+
"progress",
|
|
111
|
+
"q",
|
|
112
|
+
"rp",
|
|
113
|
+
"rt",
|
|
114
|
+
"ruby",
|
|
115
|
+
"s",
|
|
116
|
+
"samp",
|
|
117
|
+
"script",
|
|
118
|
+
"section",
|
|
119
|
+
"select",
|
|
120
|
+
"slot",
|
|
121
|
+
"small",
|
|
122
|
+
"source",
|
|
123
|
+
"span",
|
|
124
|
+
"strong",
|
|
125
|
+
"style",
|
|
126
|
+
"sub",
|
|
127
|
+
"summary",
|
|
128
|
+
"sup",
|
|
129
|
+
"svg",
|
|
130
|
+
"table",
|
|
131
|
+
"tbody",
|
|
132
|
+
"td",
|
|
133
|
+
"template",
|
|
134
|
+
"textarea",
|
|
135
|
+
"tfoot",
|
|
136
|
+
"th",
|
|
137
|
+
"thead",
|
|
138
|
+
"time",
|
|
139
|
+
"title",
|
|
140
|
+
"tr",
|
|
141
|
+
"track",
|
|
142
|
+
"u",
|
|
143
|
+
"ul",
|
|
144
|
+
"var",
|
|
145
|
+
"video",
|
|
146
|
+
"wbr",
|
|
46
147
|
];
|
|
47
148
|
|
|
48
149
|
static SOURCE_MAP: OnceLock<HashMap<String, BuiltinDef>> = OnceLock::new();
|
|
@@ -9,11 +9,11 @@ use regex::Regex;
|
|
|
9
9
|
use tower_lsp::lsp_types::{Location, Position, Range, Url};
|
|
10
10
|
|
|
11
11
|
use tishlang_ast::{ImportSpecifier, Program, Statement};
|
|
12
|
-
use tishlang_resolve::member_access_chain_at_cursor;
|
|
13
12
|
use tishlang_compile::{
|
|
14
13
|
export_name_to_rust_ident, is_builtin_native_spec, is_cargo_native_spec, is_native_import,
|
|
15
14
|
normalize_builtin_spec, read_project_tish_config, resolve_bare_spec, resolve_native_modules,
|
|
16
15
|
};
|
|
16
|
+
use tishlang_resolve::member_access_chain_at_cursor;
|
|
17
17
|
|
|
18
18
|
/// Pick a workspace / project root for resolving `package.json` and `node_modules`.
|
|
19
19
|
fn infer_project_root(file_path: &Path, roots: &[PathBuf]) -> Option<PathBuf> {
|
|
@@ -43,7 +43,10 @@ fn location_from_rust_path(path: &Path, line: u32, col: u32) -> Option<Location>
|
|
|
43
43
|
Some(Location {
|
|
44
44
|
uri,
|
|
45
45
|
range: Range {
|
|
46
|
-
start: Position {
|
|
46
|
+
start: Position {
|
|
47
|
+
line,
|
|
48
|
+
character: col,
|
|
49
|
+
},
|
|
47
50
|
end: Position {
|
|
48
51
|
line,
|
|
49
52
|
character: end_char.max(col.saturating_add(1)),
|
|
@@ -63,13 +66,10 @@ fn resolve_cargo_dep_crate_root(
|
|
|
63
66
|
Ok(r.source_root())
|
|
64
67
|
}
|
|
65
68
|
serde_json::Value::Object(map) => {
|
|
66
|
-
let path_str = map
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"cargo:… rustDependencies entry must be a version string or an object with \"path\""
|
|
71
|
-
.to_string()
|
|
72
|
-
})?;
|
|
69
|
+
let path_str = map.get("path").and_then(|v| v.as_str()).ok_or_else(|| {
|
|
70
|
+
"cargo:… rustDependencies entry must be a version string or an object with \"path\""
|
|
71
|
+
.to_string()
|
|
72
|
+
})?;
|
|
73
73
|
let glue = Path::new(path_str);
|
|
74
74
|
let glue = if glue.is_absolute() {
|
|
75
75
|
glue.to_path_buf()
|
|
@@ -79,7 +79,8 @@ fn resolve_cargo_dep_crate_root(
|
|
|
79
79
|
let glue = glue.canonicalize().unwrap_or(glue);
|
|
80
80
|
let glue_cargo = glue.join("Cargo.toml");
|
|
81
81
|
if glue_cargo.is_file() {
|
|
82
|
-
match tishlang_cargo_bindgen::resolve_dependency_from_manifest(&glue_cargo, dep_key)
|
|
82
|
+
match tishlang_cargo_bindgen::resolve_dependency_from_manifest(&glue_cargo, dep_key)
|
|
83
|
+
{
|
|
83
84
|
Ok(r) => Ok(r.source_root()),
|
|
84
85
|
Err(_) if glue.join("src").is_dir() => Ok(glue),
|
|
85
86
|
Err(e) => Err(e),
|
|
@@ -128,7 +129,8 @@ fn rust_def_for_crate_root(crate_root: &Path, tish_export: &str) -> Option<Locat
|
|
|
128
129
|
if name.is_empty() {
|
|
129
130
|
continue;
|
|
130
131
|
}
|
|
131
|
-
if let Ok((path, line, col)) =
|
|
132
|
+
if let Ok((path, line, col)) =
|
|
133
|
+
tishlang_cargo_bindgen::rust_public_fn_location(crate_root, name)
|
|
132
134
|
{
|
|
133
135
|
return location_from_rust_path(&path, line, col);
|
|
134
136
|
}
|
|
@@ -218,11 +220,11 @@ fn try_rust_member_on_crate(
|
|
|
218
220
|
}
|
|
219
221
|
|
|
220
222
|
/// Optional `| …` hover line after the 1-based line in a native package’s `lsp-pragmas.d.tish`.
|
|
221
|
-
fn parse_lsp_pragmas_native(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)
|
|
225
|
-
|
|
223
|
+
fn parse_lsp_pragmas_native(
|
|
224
|
+
src: &str,
|
|
225
|
+
) -> HashMap<String, (crate::builtin_goto::BuiltinDef, Option<String>)> {
|
|
226
|
+
let re = Regex::new(r"(?m)^\s*//\s*@tish-source\s+(\S+)\s+(\S+)\s+(\d+)(?:\s*\|\s*(.*?))?\s*$")
|
|
227
|
+
.expect("native lsp pragma regex");
|
|
226
228
|
let mut m = HashMap::new();
|
|
227
229
|
for cap in re.captures_iter(src) {
|
|
228
230
|
let sym = cap[1].to_string();
|
|
@@ -256,7 +258,11 @@ fn pragma_key_for_native_member(
|
|
|
256
258
|
}
|
|
257
259
|
match imported_for_prefix {
|
|
258
260
|
Some(prefix) => {
|
|
259
|
-
let tail: String = members
|
|
261
|
+
let tail: String = members
|
|
262
|
+
.iter()
|
|
263
|
+
.map(|m| m.as_ref())
|
|
264
|
+
.collect::<Vec<_>>()
|
|
265
|
+
.join(".");
|
|
260
266
|
if tail.is_empty() {
|
|
261
267
|
None
|
|
262
268
|
} else {
|
|
@@ -375,14 +381,16 @@ pub fn native_member_definition(
|
|
|
375
381
|
.get("rustDependencies")
|
|
376
382
|
.and_then(|v| v.get(dep_key))
|
|
377
383
|
.cloned()?;
|
|
378
|
-
cargo_crate_root_cached(&project_root, &spec, dep_key, &raw, cargo_src_cache)
|
|
384
|
+
cargo_crate_root_cached(&project_root, &spec, dep_key, &raw, cargo_src_cache)
|
|
385
|
+
.ok()?
|
|
379
386
|
} else {
|
|
380
387
|
let mods = resolve_native_modules(program, &project_root).ok()?;
|
|
381
388
|
let m = mods.iter().find(|mm| mm.spec == spec)?;
|
|
382
389
|
m.crate_path.clone()
|
|
383
390
|
};
|
|
384
391
|
|
|
385
|
-
if let Some(loc) = try_rust_member_on_crate(&crate_root, &members, imported_for_prefix)
|
|
392
|
+
if let Some(loc) = try_rust_member_on_crate(&crate_root, &members, imported_for_prefix)
|
|
393
|
+
{
|
|
386
394
|
return Some(NativeMemberDefinition {
|
|
387
395
|
location: loc,
|
|
388
396
|
doc: None,
|
|
@@ -492,9 +500,14 @@ pub fn definition_for_import(
|
|
|
492
500
|
.get("rustDependencies")
|
|
493
501
|
.and_then(|v| v.get(dep_key))
|
|
494
502
|
.cloned()?;
|
|
495
|
-
let crate_root =
|
|
496
|
-
|
|
497
|
-
|
|
503
|
+
let crate_root = cargo_crate_root_cached(
|
|
504
|
+
&project_root,
|
|
505
|
+
&spec,
|
|
506
|
+
dep_key,
|
|
507
|
+
&raw,
|
|
508
|
+
cargo_src_cache,
|
|
509
|
+
)
|
|
510
|
+
.ok()?;
|
|
498
511
|
return rust_def_for_crate_root(&crate_root, imported);
|
|
499
512
|
}
|
|
500
513
|
|