index.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { describe, expect, spyOn, test } from "bun:test"
  2. import path from "path"
  3. import fs from "fs/promises"
  4. import { Effect, Layer } from "effect"
  5. import { LSP } from "../../src/lsp"
  6. import * as Lsp from "../../src/lsp/index"
  7. import * as launch from "../../src/lsp/launch"
  8. import { LSPServer } from "../../src/lsp/server"
  9. import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
  10. import { provideTmpdirInstance, tmpdir } from "../fixture/fixture"
  11. import { testEffect } from "../lib/effect"
  12. import { Instance } from "../../src/project/instance"
  13. import { Flag } from "../../src/flag/flag" // kilocode_change
  14. import { TsCheck } from "../../src/kilocode/ts-check" // kilocode_change
  15. const it = testEffect(Layer.mergeAll(LSP.defaultLayer, CrossSpawnSpawner.defaultLayer))
  16. describe("lsp.spawn", () => {
  17. it.live("does not spawn builtin LSP for files outside instance", () =>
  18. provideTmpdirInstance((dir) =>
  19. LSP.Service.use((lsp) =>
  20. Effect.gen(function* () {
  21. const spy = spyOn(LSPServer.Typescript, "spawn").mockResolvedValue(undefined)
  22. try {
  23. yield* lsp.touchFile(path.join(dir, "..", "outside.ts"))
  24. yield* lsp.hover({
  25. file: path.join(dir, "..", "hover.ts"),
  26. line: 0,
  27. character: 0,
  28. })
  29. expect(spy).toHaveBeenCalledTimes(0)
  30. } finally {
  31. spy.mockRestore()
  32. }
  33. }),
  34. ),
  35. ),
  36. )
  37. // kilocode_change start - enable flag so spawn() is reached
  38. it.live("would spawn builtin LSP for files inside instance", () =>
  39. provideTmpdirInstance((dir) =>
  40. LSP.Service.use((lsp) =>
  41. Effect.gen(function* () {
  42. const saved = Flag.KILO_EXPERIMENTAL_LSP_TOOL
  43. // @ts-expect-error
  44. Flag.KILO_EXPERIMENTAL_LSP_TOOL = true
  45. const spy = spyOn(LSPServer.Typescript, "spawn").mockResolvedValue(undefined)
  46. try {
  47. yield* lsp.hover({
  48. file: path.join(dir, "src", "inside.ts"),
  49. line: 0,
  50. character: 0,
  51. })
  52. expect(spy).toHaveBeenCalledTimes(1)
  53. } finally {
  54. // @ts-expect-error
  55. Flag.KILO_EXPERIMENTAL_LSP_TOOL = saved
  56. spy.mockRestore()
  57. }
  58. }),
  59. ),
  60. ),
  61. )
  62. // kilocode_change end
  63. // kilocode_change start - Typescript spawn is gated behind KILO_EXPERIMENTAL_LSP_TOOL.
  64. test("spawns tsgo LSP when KILO_EXPERIMENTAL_LSP_TOOL is enabled", async () => {
  65. const saved = Flag.KILO_EXPERIMENTAL_LSP_TOOL
  66. // @ts-expect-error - override static flag for test
  67. Flag.KILO_EXPERIMENTAL_LSP_TOOL = true
  68. await using tmp = await tmpdir()
  69. const spawnSpy = spyOn(launch, "spawn").mockImplementation(
  70. () => ({ stdin: {}, stdout: {}, stderr: {}, on: () => {}, kill: () => {} }) as any,
  71. )
  72. const tsgoSpy = spyOn(TsCheck, "native_tsgo").mockResolvedValue("/fake/tsgo")
  73. try {
  74. await Instance.provide({
  75. directory: tmp.path,
  76. fn: async () => {
  77. const result = await LSPServer.Typescript.spawn(tmp.path)
  78. expect(result).toBeDefined()
  79. expect(tsgoSpy).toHaveBeenCalledWith(tmp.path)
  80. expect(spawnSpy).toHaveBeenCalled()
  81. const args = spawnSpy.mock.calls[0][1] as string[]
  82. expect(args).toContain("--lsp")
  83. expect(args).toContain("--stdio")
  84. },
  85. })
  86. } finally {
  87. // @ts-expect-error
  88. Flag.KILO_EXPERIMENTAL_LSP_TOOL = saved
  89. spawnSpy.mockRestore()
  90. tsgoSpy.mockRestore()
  91. }
  92. })
  93. test("Typescript.spawn returns undefined when KILO_EXPERIMENTAL_LSP_TOOL is off", async () => {
  94. const saved = Flag.KILO_EXPERIMENTAL_LSP_TOOL
  95. // @ts-expect-error
  96. Flag.KILO_EXPERIMENTAL_LSP_TOOL = false
  97. try {
  98. const result = await LSPServer.Typescript.spawn("/tmp/any")
  99. expect(result).toBeUndefined()
  100. } finally {
  101. // @ts-expect-error
  102. Flag.KILO_EXPERIMENTAL_LSP_TOOL = saved
  103. }
  104. })
  105. // kilocode_change end
  106. })