@tishlang/tish-format 2.2.7 → 2.8.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.
Files changed (52) hide show
  1. package/bin/tish-format +0 -0
  2. package/crates/js_to_tish/src/transform/expr.rs +5 -1
  3. package/crates/tish/src/cli_help.rs +12 -0
  4. package/crates/tish/src/main.rs +69 -11
  5. package/crates/tish_ast/src/ast.rs +6 -2
  6. package/crates/tish_builtins/src/array.rs +82 -1
  7. package/crates/tish_builtins/src/globals.rs +50 -16
  8. package/crates/tish_builtins/src/math.rs +63 -9
  9. package/crates/tish_builtins/src/number.rs +20 -1
  10. package/crates/tish_builtins/src/string.rs +68 -4
  11. package/crates/tish_builtins/src/typedarrays.rs +23 -16
  12. package/crates/tish_bytecode/src/compiler.rs +94 -28
  13. package/crates/tish_bytecode/tests/break_continue_bytecode.rs +19 -0
  14. package/crates/tish_compile/src/check.rs +1 -1
  15. package/crates/tish_compile/src/codegen.rs +1386 -42
  16. package/crates/tish_compile/src/infer.rs +4 -4
  17. package/crates/tish_compile/src/lib.rs +38 -0
  18. package/crates/tish_compile/src/resolve.rs +3 -2
  19. package/crates/tish_compile/src/types.rs +17 -0
  20. package/crates/tish_compile_js/src/codegen.rs +55 -4
  21. package/crates/tish_compile_js/src/tests_jsx.rs +44 -0
  22. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +1 -0
  23. package/crates/tish_core/Cargo.toml +2 -0
  24. package/crates/tish_core/src/json.rs +135 -34
  25. package/crates/tish_core/src/lib.rs +23 -1
  26. package/crates/tish_core/src/value.rs +64 -11
  27. package/crates/tish_eval/src/eval.rs +144 -197
  28. package/crates/tish_eval/src/natives.rs +45 -45
  29. package/crates/tish_eval/src/regex.rs +35 -27
  30. package/crates/tish_eval/src/value.rs +8 -0
  31. package/crates/tish_fmt/Cargo.toml +1 -1
  32. package/crates/tish_fmt/src/lib.rs +45 -1
  33. package/crates/tish_lint/src/bin/tish-lint.rs +17 -8
  34. package/crates/tish_lint/src/lib.rs +197 -21
  35. package/crates/tish_lsp/Cargo.toml +6 -0
  36. package/crates/tish_lsp/src/import_goto.rs +52 -7
  37. package/crates/tish_lsp/src/main.rs +856 -140
  38. package/crates/tish_opt/src/lib.rs +5 -3
  39. package/crates/tish_parser/src/lib.rs +23 -5
  40. package/crates/tish_parser/src/parser.rs +15 -26
  41. package/crates/tish_resolve/src/lib.rs +188 -18
  42. package/crates/tish_runtime/src/lib.rs +58 -18
  43. package/crates/tish_ui/src/jsx.rs +2 -2
  44. package/crates/tish_vm/src/jit.rs +212 -10
  45. package/crates/tish_vm/src/vm.rs +39 -18
  46. package/crates/tish_wasm/src/lib.rs +116 -22
  47. package/package.json +1 -1
  48. package/platform/darwin-arm64/tish-fmt +0 -0
  49. package/platform/darwin-x64/tish-fmt +0 -0
  50. package/platform/linux-arm64/tish-fmt +0 -0
  51. package/platform/linux-x64/tish-fmt +0 -0
  52. package/platform/win32-x64/tish-fmt.exe +0 -0
@@ -314,6 +314,7 @@ pub fn native_member_definition(
314
314
  lsp_line: u32,
315
315
  lsp_character: u32,
316
316
  word: &str,
317
+ open_docs: &HashMap<Url, String>,
317
318
  ) -> Option<NativeMemberDefinition> {
318
319
  let project_root = infer_project_root(file_path, roots)?;
319
320
  let from_dir = file_path.parent()?;
@@ -357,7 +358,8 @@ pub fn native_member_definition(
357
358
 
358
359
  if from_s.starts_with("./") || from_s.starts_with("../") {
359
360
  if members.len() == 1 {
360
- let loc = resolve_relative_tish(from_dir, from_s, members[0].as_ref())?;
361
+ let loc =
362
+ resolve_relative_tish(from_dir, from_s, members[0].as_ref(), open_docs)?;
361
363
  return Some(NativeMemberDefinition {
362
364
  location: loc,
363
365
  doc: None,
@@ -422,6 +424,7 @@ pub fn definition_for_native_receiver_member(
422
424
  lsp_line: u32,
423
425
  lsp_character: u32,
424
426
  word: &str,
427
+ open_docs: &HashMap<Url, String>,
425
428
  ) -> Option<Location> {
426
429
  native_member_definition(
427
430
  program,
@@ -432,11 +435,28 @@ pub fn definition_for_native_receiver_member(
432
435
  lsp_line,
433
436
  lsp_character,
434
437
  word,
438
+ open_docs,
435
439
  )
436
440
  .map(|d| d.location)
437
441
  }
438
442
 
439
- fn resolve_relative_tish(from_dir: &Path, from_s: &str, imported: &str) -> Option<Location> {
443
+ /// Source text of a target module: the live editor buffer if the file is open with unsaved edits,
444
+ /// otherwise the on-disk contents. Reading the open buffer keeps cross-file goto-definition/hover in
445
+ /// sync with what the user sees — disk would give a stale line/column (or miss a not-yet-saved
446
+ /// export entirely). #148
447
+ fn module_source(can: &Path, u: &Url, open_docs: &HashMap<Url, String>) -> Option<String> {
448
+ match open_docs.get(u) {
449
+ Some(buf) => Some(buf.clone()),
450
+ None => std::fs::read_to_string(can).ok(),
451
+ }
452
+ }
453
+
454
+ fn resolve_relative_tish(
455
+ from_dir: &Path,
456
+ from_s: &str,
457
+ imported: &str,
458
+ open_docs: &HashMap<Url, String>,
459
+ ) -> Option<Location> {
440
460
  let target = from_dir.join(from_s.trim_start_matches("./"));
441
461
  let target = if target.extension().is_none() {
442
462
  target.with_extension("tish")
@@ -445,13 +465,17 @@ fn resolve_relative_tish(from_dir: &Path, from_s: &str, imported: &str) -> Optio
445
465
  };
446
466
  let can = target.canonicalize().ok()?;
447
467
  let u = Url::from_file_path(&can).ok()?;
448
- let src = std::fs::read_to_string(&can).ok()?;
468
+ let src = module_source(&can, &u, open_docs)?;
449
469
  let prog = tishlang_parser::parse(&src).ok()?;
450
470
  crate::find_export(&prog, imported, &u, &src)
451
471
  }
452
472
 
453
473
  /// Resolve a relative default import (`import X from "./m"`) to the `export default` in the source.
454
- fn resolve_relative_tish_default(from_dir: &Path, from_s: &str) -> Option<Location> {
474
+ fn resolve_relative_tish_default(
475
+ from_dir: &Path,
476
+ from_s: &str,
477
+ open_docs: &HashMap<Url, String>,
478
+ ) -> Option<Location> {
455
479
  let target = from_dir.join(from_s.trim_start_matches("./"));
456
480
  let target = if target.extension().is_none() {
457
481
  target.with_extension("tish")
@@ -460,7 +484,7 @@ fn resolve_relative_tish_default(from_dir: &Path, from_s: &str) -> Option<Locati
460
484
  };
461
485
  let can = target.canonicalize().ok()?;
462
486
  let u = Url::from_file_path(&can).ok()?;
463
- let src = std::fs::read_to_string(&can).ok()?;
487
+ let src = module_source(&can, &u, open_docs)?;
464
488
  let prog = tishlang_parser::parse(&src).ok()?;
465
489
  crate::find_default_export(&prog, &u, &src)
466
490
  }
@@ -473,6 +497,7 @@ pub fn definition_for_import(
473
497
  word: &str,
474
498
  roots: &[PathBuf],
475
499
  cargo_src_cache: &RwLock<HashMap<(PathBuf, String), PathBuf>>,
500
+ open_docs: &HashMap<Url, String>,
476
501
  ) -> Option<Location> {
477
502
  if word.is_empty() {
478
503
  return None;
@@ -506,9 +531,9 @@ pub fn definition_for_import(
506
531
  // A default import binds the source module's `export default`, which has no name to
507
532
  // match; resolve it directly. Named imports resolve by exported name.
508
533
  return if is_default {
509
- resolve_relative_tish_default(from_dir, from_s)
534
+ resolve_relative_tish_default(from_dir, from_s, open_docs)
510
535
  } else {
511
- resolve_relative_tish(from_dir, from_s, imported)
536
+ resolve_relative_tish(from_dir, from_s, imported, open_docs)
512
537
  };
513
538
  }
514
539
 
@@ -563,6 +588,26 @@ mod receiver_member_tests {
563
588
  assert_eq!(mem, "setTitle");
564
589
  }
565
590
 
591
+ // #148: cross-file goto-def must read the open editor buffer (unsaved edits), not disk.
592
+ #[test]
593
+ fn module_source_prefers_open_buffer_over_disk() {
594
+ use std::collections::HashMap;
595
+ use tower_lsp::lsp_types::Url;
596
+ // A path that does NOT exist on disk: the disk branch would fail, so a non-None result
597
+ // proves the open buffer was used.
598
+ let path = std::path::Path::new("/nonexistent/tish/module.tish");
599
+ let url = Url::parse("file:///nonexistent/tish/module.tish").unwrap();
600
+ let mut docs = HashMap::new();
601
+ docs.insert(url.clone(), "export fn live() {}".to_string());
602
+ assert_eq!(
603
+ super::module_source(path, &url, &docs).as_deref(),
604
+ Some("export fn live() {}"),
605
+ "open buffer must win over (here, absent) disk content"
606
+ );
607
+ // Not open + nonexistent on disk → None (disk read fails), no panic.
608
+ assert_eq!(super::module_source(path, &url, &HashMap::new()), None);
609
+ }
610
+
566
611
  #[test]
567
612
  fn native_pragma_parse_optional_doc() {
568
613
  let src = r"// @tish-source window.innerHeight src/appkit/window_api.rs 289 | Height in points.