@tishlang/tish 1.6.0 → 1.7.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/Cargo.toml +1 -0
- package/bin/tish +0 -0
- package/crates/js_to_tish/src/error.rs +2 -8
- package/crates/js_to_tish/src/transform/expr.rs +101 -130
- package/crates/js_to_tish/src/transform/stmt.rs +25 -22
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/src/cli_help.rs +76 -29
- package/crates/tish/src/main.rs +85 -54
- package/crates/tish/tests/cargo_example_compile.rs +3 -1
- package/crates/tish/tests/integration_test.rs +197 -47
- package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
- package/crates/tish/tests/shortcircuit.rs +19 -4
- package/crates/tish_ast/src/ast.rs +12 -14
- package/crates/tish_build_utils/src/lib.rs +31 -6
- package/crates/tish_builtins/src/array.rs +52 -21
- package/crates/tish_builtins/src/construct.rs +2 -8
- package/crates/tish_builtins/src/globals.rs +30 -15
- package/crates/tish_builtins/src/lib.rs +5 -5
- package/crates/tish_builtins/src/math.rs +5 -3
- package/crates/tish_builtins/src/string.rs +71 -19
- package/crates/tish_bytecode/src/chunk.rs +0 -1
- package/crates/tish_bytecode/src/compiler.rs +164 -60
- package/crates/tish_bytecode/src/opcode.rs +13 -4
- package/crates/tish_bytecode/src/peephole.rs +2 -2
- package/crates/tish_compile/src/codegen.rs +921 -299
- package/crates/tish_compile/src/infer.rs +69 -19
- package/crates/tish_compile/src/lib.rs +15 -5
- package/crates/tish_compile/src/resolve.rs +112 -69
- package/crates/tish_compile/src/types.rs +10 -14
- package/crates/tish_compile_js/src/codegen.rs +34 -13
- package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
- package/crates/tish_compiler_wasm/src/lib.rs +16 -13
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +39 -48
- package/crates/tish_core/src/json.rs +5 -3
- package/crates/tish_core/src/lib.rs +1 -1
- package/crates/tish_core/src/uri.rs +9 -6
- package/crates/tish_core/src/value.rs +92 -28
- package/crates/tish_cranelift/src/link.rs +6 -9
- package/crates/tish_cranelift/src/lower.rs +14 -8
- package/crates/tish_eval/src/eval.rs +389 -142
- package/crates/tish_eval/src/lib.rs +10 -6
- package/crates/tish_eval/src/natives.rs +95 -38
- package/crates/tish_eval/src/promise.rs +14 -8
- package/crates/tish_eval/src/timers.rs +28 -19
- package/crates/tish_eval/src/value.rs +10 -3
- package/crates/tish_fmt/src/lib.rs +29 -13
- package/crates/tish_lexer/src/lib.rs +217 -63
- package/crates/tish_lexer/src/token.rs +6 -6
- package/crates/tish_llvm/src/lib.rs +15 -8
- package/crates/tish_lsp/src/main.rs +41 -43
- package/crates/tish_native/src/build.rs +1 -6
- package/crates/tish_native/src/lib.rs +48 -19
- package/crates/tish_opt/src/lib.rs +67 -50
- package/crates/tish_parser/src/lib.rs +36 -11
- package/crates/tish_parser/src/parser.rs +172 -87
- package/crates/tish_runtime/src/http.rs +15 -6
- package/crates/tish_runtime/src/http_fetch.rs +24 -14
- package/crates/tish_runtime/src/lib.rs +224 -168
- package/crates/tish_runtime/src/promise.rs +1 -5
- package/crates/tish_runtime/src/ws.rs +45 -20
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
- package/crates/tish_ui/src/jsx.rs +41 -22
- package/crates/tish_ui/src/lib.rs +2 -2
- package/crates/tish_vm/src/vm.rs +309 -112
- package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
- package/crates/tish_wasm/src/lib.rs +38 -28
- package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
- package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
- package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
- package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
- package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
- package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
- package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
- 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
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
//! Infer bindgen targets from project `package.json` (`tish.rustDependencies`) and glue `Cargo.toml`.
|
|
2
|
+
|
|
3
|
+
use std::fs;
|
|
4
|
+
use std::path::{Path, PathBuf};
|
|
5
|
+
|
|
6
|
+
use serde_json::Value;
|
|
7
|
+
|
|
8
|
+
/// Glue crate identity + upstream Cargo dependency to wrap.
|
|
9
|
+
#[derive(Debug, Clone)]
|
|
10
|
+
pub struct InferredProjectBindgen {
|
|
11
|
+
/// `tish.rustDependencies` key and `[package].name` for the generated crate.
|
|
12
|
+
pub output_crate_name: String,
|
|
13
|
+
pub out_dir: PathBuf,
|
|
14
|
+
pub dependency_name: String,
|
|
15
|
+
pub dependency_version_req: String,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Pick the path-based glue crate from `package.json` → `tish.rustDependencies`.
|
|
19
|
+
pub fn select_glue_crate_from_package_json(
|
|
20
|
+
project_root: &Path,
|
|
21
|
+
rust_dep_key: Option<&str>,
|
|
22
|
+
) -> Result<(String, PathBuf), String> {
|
|
23
|
+
let pkg_json_path = project_root.join("package.json");
|
|
24
|
+
let raw = fs::read_to_string(&pkg_json_path).map_err(|e| {
|
|
25
|
+
format!(
|
|
26
|
+
"could not read {}: {} (for automatic mode, run from the Tish project root or pass --project-root)",
|
|
27
|
+
pkg_json_path.display(),
|
|
28
|
+
e
|
|
29
|
+
)
|
|
30
|
+
})?;
|
|
31
|
+
let j: Value = serde_json::from_str(&raw).map_err(|e| format!("{}: {}", pkg_json_path.display(), e))?;
|
|
32
|
+
let rust_deps = j
|
|
33
|
+
.get("tish")
|
|
34
|
+
.and_then(|t| t.get("rustDependencies"))
|
|
35
|
+
.and_then(|v| v.as_object())
|
|
36
|
+
.ok_or_else(|| {
|
|
37
|
+
format!(
|
|
38
|
+
"{} must contain `tish.rustDependencies` (object) to infer glue paths",
|
|
39
|
+
pkg_json_path.display()
|
|
40
|
+
)
|
|
41
|
+
})?;
|
|
42
|
+
|
|
43
|
+
let mut path_entries: Vec<(String, PathBuf)> = Vec::new();
|
|
44
|
+
for (key, val) in rust_deps {
|
|
45
|
+
let rel = match val {
|
|
46
|
+
Value::Object(o) => o.get("path").and_then(|p| p.as_str()),
|
|
47
|
+
_ => None,
|
|
48
|
+
};
|
|
49
|
+
if let Some(p) = rel {
|
|
50
|
+
let abs = project_root.join(p);
|
|
51
|
+
path_entries.push((key.clone(), abs));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
path_entries.sort_by(|a, b| a.0.cmp(&b.0));
|
|
56
|
+
|
|
57
|
+
if path_entries.is_empty() {
|
|
58
|
+
return Err(
|
|
59
|
+
"no path-based entries in tish.rustDependencies (only version strings? bindgen updates local path crates)"
|
|
60
|
+
.into(),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
match rust_dep_key {
|
|
65
|
+
Some(k) => {
|
|
66
|
+
let found = path_entries
|
|
67
|
+
.iter()
|
|
68
|
+
.find(|(key, _)| key == k)
|
|
69
|
+
.ok_or_else(|| {
|
|
70
|
+
format!(
|
|
71
|
+
"tish.rustDependencies has no path entry for key `{}` (have: {})",
|
|
72
|
+
k,
|
|
73
|
+
path_entries
|
|
74
|
+
.iter()
|
|
75
|
+
.map(|(k, _)| k.as_str())
|
|
76
|
+
.collect::<Vec<_>>()
|
|
77
|
+
.join(", ")
|
|
78
|
+
)
|
|
79
|
+
})?;
|
|
80
|
+
Ok(found.clone())
|
|
81
|
+
}
|
|
82
|
+
None => {
|
|
83
|
+
if path_entries.len() != 1 {
|
|
84
|
+
return Err(format!(
|
|
85
|
+
"multiple path rustDependencies — pass --crate-name <key> (keys: {})",
|
|
86
|
+
path_entries
|
|
87
|
+
.iter()
|
|
88
|
+
.map(|(k, _)| k.as_str())
|
|
89
|
+
.collect::<Vec<_>>()
|
|
90
|
+
.join(", ")
|
|
91
|
+
));
|
|
92
|
+
}
|
|
93
|
+
Ok(path_entries[0].clone())
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fn dep_version_req_string_glue(spec: &toml::Value) -> Result<String, String> {
|
|
99
|
+
match spec {
|
|
100
|
+
toml::Value::String(s) => Ok(s.clone()),
|
|
101
|
+
toml::Value::Table(t) => {
|
|
102
|
+
if t.get("workspace").and_then(|v| v.as_bool()) == Some(true) {
|
|
103
|
+
return Err(
|
|
104
|
+
"glue Cargo.toml uses `workspace = true` for an upstream dep; set an explicit version in the glue crate or use --dependency with --out-dir"
|
|
105
|
+
.into(),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if t.get("path").is_some() || t.get("git").is_some() {
|
|
109
|
+
return Err(
|
|
110
|
+
"expected a registry-style upstream dep with a semver (string or version = \"…\"); path/git deps are not supported as bindgen upstream"
|
|
111
|
+
.into(),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
t.get("version")
|
|
115
|
+
.and_then(|v| v.as_str())
|
|
116
|
+
.map(|s| s.to_string())
|
|
117
|
+
.ok_or_else(|| {
|
|
118
|
+
"dependency entry needs a version string or `version = \"…\"` in a table".into()
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
_ => Err("unsupported dependency entry in glue Cargo.toml".into()),
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// Crates we ignore when inferring bindgen **upstream** from the **app** `Cargo.toml` (not the glue crate).
|
|
126
|
+
const ROOT_MANIFEST_SKIP_DEPS: &[&str] = &["tishlang_runtime", "tishlang_core", "tishlang_build_utils"];
|
|
127
|
+
|
|
128
|
+
/// Registry semver for bindgen metadata probe; skips path/git/workspace-only entries (project root fallback).
|
|
129
|
+
fn dep_version_req_string_root(spec: &toml::Value) -> Option<String> {
|
|
130
|
+
match spec {
|
|
131
|
+
toml::Value::String(s) => Some(s.clone()),
|
|
132
|
+
toml::Value::Table(t) => {
|
|
133
|
+
if t.get("workspace").and_then(|v| v.as_bool()) == Some(true) {
|
|
134
|
+
return None;
|
|
135
|
+
}
|
|
136
|
+
if t.get("path").is_some() || t.get("git").is_some() {
|
|
137
|
+
return None;
|
|
138
|
+
}
|
|
139
|
+
t.get("version").and_then(|v| v.as_str()).map(|s| s.to_string())
|
|
140
|
+
}
|
|
141
|
+
_ => None,
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
fn collect_upstream_candidates_from_table(
|
|
146
|
+
deps: &toml::Table,
|
|
147
|
+
skip_names: &[&str],
|
|
148
|
+
version_fn: fn(&toml::Value) -> Result<String, String>,
|
|
149
|
+
) -> Result<Vec<(String, String)>, String> {
|
|
150
|
+
let mut candidates: Vec<(String, String)> = Vec::new();
|
|
151
|
+
for (name, spec) in deps {
|
|
152
|
+
if name == "tishlang_runtime" || skip_names.iter().any(|s| *s == name) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
let ver = version_fn(spec)?;
|
|
156
|
+
candidates.push((name.clone(), ver));
|
|
157
|
+
}
|
|
158
|
+
Ok(candidates)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
fn collect_upstream_candidates_from_table_root(deps: &toml::Table) -> Vec<(String, String)> {
|
|
162
|
+
let mut candidates: Vec<(String, String)> = Vec::new();
|
|
163
|
+
for (name, spec) in deps {
|
|
164
|
+
if name == "tishlang_runtime" || ROOT_MANIFEST_SKIP_DEPS.iter().any(|s| *s == name) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if let Some(ver) = dep_version_req_string_root(spec) {
|
|
168
|
+
candidates.push((name.clone(), ver));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
candidates
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
fn disambiguate_upstream_candidates(
|
|
175
|
+
candidates: Vec<(String, String)>,
|
|
176
|
+
manifest_path: &Path,
|
|
177
|
+
hint: &str,
|
|
178
|
+
) -> Result<(String, String), String> {
|
|
179
|
+
match candidates.len() {
|
|
180
|
+
0 => Err(format!(
|
|
181
|
+
"{}: no registry semver dependency to use as bindgen upstream{}",
|
|
182
|
+
manifest_path.display(),
|
|
183
|
+
hint
|
|
184
|
+
)),
|
|
185
|
+
1 => Ok(candidates[0].clone()),
|
|
186
|
+
2 => {
|
|
187
|
+
let non_sj: Vec<_> = candidates
|
|
188
|
+
.iter()
|
|
189
|
+
.filter(|(n, _)| n != "serde_json")
|
|
190
|
+
.cloned()
|
|
191
|
+
.collect();
|
|
192
|
+
if non_sj.len() == 1 {
|
|
193
|
+
Ok(non_sj[0].clone())
|
|
194
|
+
} else {
|
|
195
|
+
Err(format!(
|
|
196
|
+
"{}: ambiguous dependencies (expected one upstream, or one non-serde_json + serde_json); use explicit --dependency",
|
|
197
|
+
manifest_path.display()
|
|
198
|
+
))
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
_ => Err(format!(
|
|
202
|
+
"{}: too many candidate upstream crates; narrow [dependencies] or use explicit --dependency",
|
|
203
|
+
manifest_path.display()
|
|
204
|
+
)),
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Read `[dependencies]` from the glue crate: upstream is everything except `tishlang_runtime`,
|
|
209
|
+
/// disambiguating when `serde_json` is present as a JSON-bridge helper alongside another crate.
|
|
210
|
+
pub fn parse_upstream_from_glue_cargo(cargo_toml_path: &Path) -> Result<(String, String), String> {
|
|
211
|
+
let s = fs::read_to_string(cargo_toml_path).map_err(|e| e.to_string())?;
|
|
212
|
+
let root: toml::Value = toml::from_str(&s).map_err(|e| format!("{}: {}", cargo_toml_path.display(), e))?;
|
|
213
|
+
let deps = root
|
|
214
|
+
.get("dependencies")
|
|
215
|
+
.and_then(|d| d.as_table())
|
|
216
|
+
.ok_or_else(|| format!("{} has no [dependencies]", cargo_toml_path.display()))?;
|
|
217
|
+
|
|
218
|
+
let candidates = collect_upstream_candidates_from_table(deps, &[], dep_version_req_string_glue)?;
|
|
219
|
+
disambiguate_upstream_candidates(
|
|
220
|
+
candidates,
|
|
221
|
+
cargo_toml_path,
|
|
222
|
+
" (only tishlang_runtime?) — add e.g. `serde_json = \"1\"`",
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// Infer upstream from the **project** `Cargo.toml` when the glue crate does not exist yet.
|
|
227
|
+
/// Uses `[dependencies]` and `[dev-dependencies]`, skips Tish toolchain path crates (`tishlang_core`, …),
|
|
228
|
+
/// and only keeps entries with a registry semver (skips bare `path =` / `git` deps).
|
|
229
|
+
pub fn parse_upstream_from_root_package_cargo(cargo_toml_path: &Path) -> Result<(String, String), String> {
|
|
230
|
+
let s = fs::read_to_string(cargo_toml_path).map_err(|e| e.to_string())?;
|
|
231
|
+
let root: toml::Value = toml::from_str(&s).map_err(|e| format!("{}: {}", cargo_toml_path.display(), e))?;
|
|
232
|
+
|
|
233
|
+
let mut candidates = root
|
|
234
|
+
.get("dependencies")
|
|
235
|
+
.and_then(|d| d.as_table())
|
|
236
|
+
.map(collect_upstream_candidates_from_table_root)
|
|
237
|
+
.unwrap_or_default();
|
|
238
|
+
if let Some(dev) = root.get("dev-dependencies").and_then(|d| d.as_table()) {
|
|
239
|
+
candidates.extend(collect_upstream_candidates_from_table_root(dev));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Same name in both tables: prefer first occurrence (dependencies before dev-dependencies).
|
|
243
|
+
let mut seen = std::collections::HashSet::new();
|
|
244
|
+
candidates.retain(|(n, _)| seen.insert(n.clone()));
|
|
245
|
+
|
|
246
|
+
disambiguate_upstream_candidates(
|
|
247
|
+
candidates,
|
|
248
|
+
cargo_toml_path,
|
|
249
|
+
" — add a registry dep for the crate to wrap (e.g. serde_json = \"1\") or use --dependency",
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// Full inference: `rustDependencies` path + glue `Cargo.toml`, or project-root `Cargo.toml` if glue is missing.
|
|
254
|
+
pub fn infer_from_project_root(
|
|
255
|
+
project_root: &Path,
|
|
256
|
+
rust_dep_key: Option<&str>,
|
|
257
|
+
) -> Result<InferredProjectBindgen, String> {
|
|
258
|
+
let (output_crate_name, out_dir) = select_glue_crate_from_package_json(project_root, rust_dep_key)?;
|
|
259
|
+
let glue_cargo = out_dir.join("Cargo.toml");
|
|
260
|
+
let root_cargo = project_root.join("Cargo.toml");
|
|
261
|
+
|
|
262
|
+
let (dependency_name, dependency_version_req) = if glue_cargo.is_file() {
|
|
263
|
+
parse_upstream_from_glue_cargo(&glue_cargo)?
|
|
264
|
+
} else if root_cargo.is_file() {
|
|
265
|
+
parse_upstream_from_root_package_cargo(&root_cargo)?
|
|
266
|
+
} else {
|
|
267
|
+
return Err(format!(
|
|
268
|
+
"no Cargo.toml at glue path {} and none at project root {} — add the upstream crate to the app Cargo.toml ([dependencies] or [dev-dependencies]) or bootstrap with:\n --project-root {} --dependency <upstream_crate> --dependency-version 1.0",
|
|
269
|
+
glue_cargo.display(),
|
|
270
|
+
root_cargo.display(),
|
|
271
|
+
project_root.display()
|
|
272
|
+
));
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
Ok(InferredProjectBindgen {
|
|
276
|
+
output_crate_name,
|
|
277
|
+
out_dir,
|
|
278
|
+
dependency_name,
|
|
279
|
+
dependency_version_req,
|
|
280
|
+
})
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/// Paths from `package.json` only (bootstrap before a glue `Cargo.toml` exists).
|
|
284
|
+
pub fn infer_glue_paths_only(
|
|
285
|
+
project_root: &Path,
|
|
286
|
+
rust_dep_key: Option<&str>,
|
|
287
|
+
) -> Result<(String, PathBuf), String> {
|
|
288
|
+
select_glue_crate_from_package_json(project_root, rust_dep_key)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#[cfg(test)]
|
|
292
|
+
mod tests {
|
|
293
|
+
use super::*;
|
|
294
|
+
|
|
295
|
+
#[test]
|
|
296
|
+
fn parse_upstream_single_serde_json() {
|
|
297
|
+
let dir = tempfile::tempdir().unwrap();
|
|
298
|
+
let p = dir.path().join("Cargo.toml");
|
|
299
|
+
fs::write(
|
|
300
|
+
&p,
|
|
301
|
+
r#"[package]
|
|
302
|
+
name = "glue"
|
|
303
|
+
version = "0.1.0"
|
|
304
|
+
edition = "2021"
|
|
305
|
+
[dependencies]
|
|
306
|
+
tishlang_runtime = { path = "../rt" }
|
|
307
|
+
serde_json = "1.0.149"
|
|
308
|
+
"#,
|
|
309
|
+
)
|
|
310
|
+
.unwrap();
|
|
311
|
+
let (n, v) = parse_upstream_from_glue_cargo(&p).unwrap();
|
|
312
|
+
assert_eq!(n, "serde_json");
|
|
313
|
+
assert_eq!(v, "1.0.149");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
#[test]
|
|
317
|
+
fn parse_upstream_two_deps_prefers_non_serde_json() {
|
|
318
|
+
let dir = tempfile::tempdir().unwrap();
|
|
319
|
+
let p = dir.path().join("Cargo.toml");
|
|
320
|
+
fs::write(
|
|
321
|
+
&p,
|
|
322
|
+
r#"[dependencies]
|
|
323
|
+
tishlang_runtime = "0.1"
|
|
324
|
+
mylib = "2"
|
|
325
|
+
serde_json = "1"
|
|
326
|
+
"#,
|
|
327
|
+
)
|
|
328
|
+
.unwrap();
|
|
329
|
+
let (n, _) = parse_upstream_from_glue_cargo(&p).unwrap();
|
|
330
|
+
assert_eq!(n, "mylib");
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
#[test]
|
|
334
|
+
fn parse_upstream_from_root_skips_tishlang_core_path() {
|
|
335
|
+
let dir = tempfile::tempdir().unwrap();
|
|
336
|
+
let p = dir.path().join("Cargo.toml");
|
|
337
|
+
fs::write(
|
|
338
|
+
&p,
|
|
339
|
+
r#"[package]
|
|
340
|
+
name = "app"
|
|
341
|
+
version = "0.1.0"
|
|
342
|
+
edition = "2021"
|
|
343
|
+
[dependencies]
|
|
344
|
+
tishlang_core = { path = "../tish/crates/tish_core" }
|
|
345
|
+
serde_json = "1.0.200"
|
|
346
|
+
"#,
|
|
347
|
+
)
|
|
348
|
+
.unwrap();
|
|
349
|
+
let (n, v) = parse_upstream_from_root_package_cargo(&p).unwrap();
|
|
350
|
+
assert_eq!(n, "serde_json");
|
|
351
|
+
assert_eq!(v, "1.0.200");
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
#[test]
|
|
355
|
+
fn parse_upstream_from_root_merges_dev_dependencies() {
|
|
356
|
+
let dir = tempfile::tempdir().unwrap();
|
|
357
|
+
let p = dir.path().join("Cargo.toml");
|
|
358
|
+
fs::write(
|
|
359
|
+
&p,
|
|
360
|
+
r#"[package]
|
|
361
|
+
name = "app"
|
|
362
|
+
version = "0.1.0"
|
|
363
|
+
edition = "2021"
|
|
364
|
+
[dev-dependencies]
|
|
365
|
+
serde_json = "1"
|
|
366
|
+
"#,
|
|
367
|
+
)
|
|
368
|
+
.unwrap();
|
|
369
|
+
let (n, _) = parse_upstream_from_root_package_cargo(&p).unwrap();
|
|
370
|
+
assert_eq!(n, "serde_json");
|
|
371
|
+
}
|
|
372
|
+
}
|