nadesiko3 3.3.49 → 3.3.50

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 (342) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +143 -143
  3. package/batch/.DS_Store +0 -0
  4. package/batch/browsers.template.md +3 -3
  5. package/batch/build_browsers.nako3 +72 -72
  6. package/batch/build_command.nako3 +44 -44
  7. package/batch/build_nako_version.nako3 +42 -42
  8. package/batch/calc_hash.nako3 +29 -29
  9. package/batch/cmd_txt2json.nako3 +74 -74
  10. package/batch/command.txt +79 -0
  11. package/batch/command_nakopad.txt +69 -0
  12. package/batch/download-extlib.nako3 +43 -43
  13. package/batch/gen_command_nakopad.nako3 +57 -57
  14. package/batch/jsplugin2text.nako3 +285 -285
  15. package/batch/pickup_command.nako3 +110 -110
  16. package/batch/pickup_reserved_words.nako3 +11 -11
  17. package/batch/publish_version.nako3 +46 -46
  18. package/batch/show_agents.js +14 -14
  19. package/batch/turtle2js.nako3 +21 -21
  20. package/bin/cnako3 +10 -10
  21. package/core/LICENSE +21 -21
  22. package/core/README.md +66 -66
  23. package/core/batch/build_nako_version.nako3 +42 -42
  24. package/core/command/snako.mjs +105 -105
  25. package/core/command/snako.mts +116 -116
  26. package/core/index.mjs +21 -21
  27. package/core/package.json +47 -47
  28. package/core/sample/hello.nako3 +7 -7
  29. package/core/sample/hoge.mjs +4 -4
  30. package/core/sample/hoge.mts +6 -6
  31. package/core/src/nako3.mjs +864 -858
  32. package/core/src/nako3.mts +976 -967
  33. package/core/src/nako_colors.mjs +78 -78
  34. package/core/src/nako_colors.mts +86 -86
  35. package/core/src/nako_core_version.mjs +8 -8
  36. package/core/src/nako_core_version.mts +19 -19
  37. package/core/src/nako_csv.mjs +185 -185
  38. package/core/src/nako_csv.mts +188 -188
  39. package/core/src/nako_errors.mjs +173 -173
  40. package/core/src/nako_errors.mts +197 -197
  41. package/core/src/nako_from_dncl.mjs +255 -255
  42. package/core/src/nako_from_dncl.mts +250 -250
  43. package/core/src/nako_gen.mjs +1647 -1648
  44. package/core/src/nako_gen.mts +1718 -1719
  45. package/core/src/nako_gen_async.mjs +1659 -1659
  46. package/core/src/nako_gen_async.mts +1732 -1732
  47. package/core/src/nako_global.mjs +107 -107
  48. package/core/src/nako_global.mts +138 -138
  49. package/core/src/nako_indent.mjs +445 -445
  50. package/core/src/nako_indent.mts +492 -492
  51. package/core/src/nako_josi_list.mjs +38 -38
  52. package/core/src/nako_josi_list.mts +45 -45
  53. package/core/src/nako_lex_rules.mjs +253 -253
  54. package/core/src/nako_lex_rules.mts +260 -260
  55. package/core/src/nako_lexer.mjs +609 -609
  56. package/core/src/nako_lexer.mts +612 -612
  57. package/core/src/nako_logger.mjs +199 -199
  58. package/core/src/nako_logger.mts +232 -232
  59. package/core/src/nako_parser3.mjs +2439 -2439
  60. package/core/src/nako_parser3.mts +2195 -2195
  61. package/core/src/nako_parser_base.mjs +370 -370
  62. package/core/src/nako_parser_base.mts +370 -370
  63. package/core/src/nako_parser_const.mjs +37 -37
  64. package/core/src/nako_parser_const.mts +37 -37
  65. package/core/src/nako_prepare.mjs +304 -304
  66. package/core/src/nako_prepare.mts +315 -315
  67. package/core/src/nako_reserved_words.mjs +38 -38
  68. package/core/src/nako_reserved_words.mts +38 -38
  69. package/core/src/nako_source_mapping.mjs +207 -207
  70. package/core/src/nako_source_mapping.mts +262 -262
  71. package/core/src/nako_test.mjs +37 -37
  72. package/core/src/nako_types.mjs +25 -25
  73. package/core/src/nako_types.mts +151 -151
  74. package/core/src/plugin_csv.mjs +49 -49
  75. package/core/src/plugin_csv.mts +50 -50
  76. package/core/src/plugin_math.mjs +328 -328
  77. package/core/src/plugin_math.mts +326 -326
  78. package/core/src/plugin_promise.mjs +91 -91
  79. package/core/src/plugin_promise.mts +91 -91
  80. package/core/src/plugin_system.mjs +2832 -2832
  81. package/core/src/plugin_system.mts +2690 -2690
  82. package/core/src/plugin_test.mjs +34 -34
  83. package/core/src/plugin_test.mts +34 -34
  84. package/demo/.DS_Store +0 -0
  85. package/demo/ace_editor.html +89 -89
  86. package/demo/ace_editor_tabs.html +161 -161
  87. package/demo/basic.html +71 -71
  88. package/demo/browsers.html +10 -9
  89. package/demo/css/basic.css +3 -3
  90. package/demo/css/common.css +157 -157
  91. package/demo/css/editor.css +8 -8
  92. package/demo/css/flow.css +3 -3
  93. package/demo/css/index.css +3 -3
  94. package/demo/extlib/.DS_Store +0 -0
  95. package/demo/flow.html +98 -98
  96. package/demo/graph.html +53 -53
  97. package/demo/image/nakopad-icon256.png +0 -0
  98. package/demo/index.html +133 -133
  99. package/demo/js/common.js +17 -17
  100. package/demo/js/turtle3d_test.js +44 -44
  101. package/demo/js/turtle_test.js +45 -45
  102. package/demo/nako3/calc.nako3 +4 -4
  103. package/demo/runscript.html +47 -47
  104. package/demo/runscript2.html +33 -33
  105. package/demo/runscript3.html +35 -35
  106. package/demo/runscript4.html +33 -33
  107. package/demo/turtle.html +58 -58
  108. package/demo/turtle2.html +141 -141
  109. package/demo/turtle3.html +279 -279
  110. package/demo/turtle3d.html +58 -58
  111. package/demo/turtle3d2.html +107 -107
  112. package/demo/version.html +24 -24
  113. package/doc/SETUP.md +157 -157
  114. package/doc/about.md +17 -17
  115. package/doc/browsers.md +26 -26
  116. package/doc/docgen.md +21 -21
  117. package/doc/editor.md +44 -44
  118. package/doc/files.md +39 -39
  119. package/doc/plugins.md +234 -234
  120. package/doc/release.md +79 -79
  121. package/doc/textlint.md +43 -43
  122. package/doc/win32.md +57 -57
  123. package/package.json +195 -195
  124. package/release/_hash.txt +28 -28
  125. package/release/_script-tags.txt +14 -14
  126. package/release/command.json +1 -1
  127. package/release/command.json.js +1 -1
  128. package/release/command_cnako3.json +1 -1
  129. package/release/command_list.json +1 -1
  130. package/release/editor.js +1 -1
  131. package/release/nako_gen_async.js +1 -1
  132. package/release/nako_gen_async.js.LICENSE.txt +35 -0
  133. package/release/plugin_caniuse.js.LICENSE.txt +11 -0
  134. package/release/plugin_csv.js +1 -1
  135. package/release/plugin_csv.js.LICENSE.txt +15 -0
  136. package/release/plugin_datetime.js.LICENSE.txt +15 -0
  137. package/release/plugin_kansuji.js.LICENSE.txt +3 -0
  138. package/release/plugin_markup.js.LICENSE.txt +11 -0
  139. package/release/plugin_turtle.js.LICENSE.txt +15 -0
  140. package/release/plugin_webworker.js.LICENSE.txt +3 -0
  141. package/release/plugin_weykturtle3d.js.LICENSE.txt +3 -0
  142. package/release/stats.json +1 -1
  143. package/release/version.js +1 -1
  144. package/release/wnako3.js +1 -1
  145. package/release/wnako3webworker.js +1 -1
  146. package/release/wnako3webworker.js.LICENSE.txt +131 -0
  147. package/src/.DS_Store +0 -0
  148. package/src/browsers.txt +12 -11
  149. package/src/browsers_agents.json +2 -2
  150. package/src/browsers_agents.mjs +1 -1
  151. package/src/cnako3.mjs +17 -17
  152. package/src/cnako3.mts +18 -18
  153. package/src/cnako3mod.mjs +707 -707
  154. package/src/cnako3mod.mts +712 -712
  155. package/src/commander_ja.mjs +164 -164
  156. package/src/commander_ja.mts +161 -161
  157. package/src/enako3.mjs +68 -68
  158. package/src/era.mjs +22 -22
  159. package/src/image_turtle-elephant.mjs +2 -2
  160. package/src/image_turtle-panda.mjs +2 -2
  161. package/src/image_turtle64.mjs +2 -2
  162. package/src/index.mjs +9 -9
  163. package/src/index.mts +10 -10
  164. package/src/nako3editorfix.sfd +106 -106
  165. package/src/nako_version.mjs +8 -8
  166. package/src/nako_version.mts +2 -2
  167. package/src/plugin_browser.mjs +213 -213
  168. package/src/plugin_browser.mts +206 -206
  169. package/src/plugin_browser_ajax.mjs +399 -399
  170. package/src/plugin_browser_audio.mjs +109 -109
  171. package/src/plugin_browser_canvas.mjs +449 -449
  172. package/src/plugin_browser_chart.mjs +294 -294
  173. package/src/plugin_browser_color.mjs +49 -49
  174. package/src/plugin_browser_crypto.mjs +26 -26
  175. package/src/plugin_browser_dialog.mjs +53 -53
  176. package/src/plugin_browser_dom_basic.mjs +336 -336
  177. package/src/plugin_browser_dom_event.mjs +193 -193
  178. package/src/plugin_browser_dom_parts.mjs +396 -396
  179. package/src/plugin_browser_geolocation.mjs +51 -51
  180. package/src/plugin_browser_hotkey.mjs +25 -25
  181. package/src/plugin_browser_html.mjs +59 -59
  182. package/src/plugin_browser_in_worker.mjs +45 -45
  183. package/src/plugin_browser_location.mjs +21 -21
  184. package/src/plugin_browser_speech.mjs +111 -111
  185. package/src/plugin_browser_storage.mjs +121 -121
  186. package/src/plugin_browser_system.mjs +31 -31
  187. package/src/plugin_browser_websocket.mjs +73 -73
  188. package/src/plugin_caniuse.mjs +29 -29
  189. package/src/plugin_datetime.mjs +394 -394
  190. package/src/plugin_httpserver.mjs +277 -277
  191. package/src/plugin_httpserver.mts +286 -286
  192. package/src/plugin_kansuji.mjs +224 -224
  193. package/src/plugin_keigo.mjs +55 -55
  194. package/src/plugin_markup.mjs +32 -32
  195. package/src/plugin_node.mjs +1047 -1047
  196. package/src/plugin_node.mts +980 -980
  197. package/src/plugin_turtle.mjs +647 -647
  198. package/src/plugin_webworker.mjs +334 -334
  199. package/src/plugin_weykturtle3d.mjs +1214 -1214
  200. package/src/plugin_worker.mjs +95 -95
  201. package/src/repl.nako3 +63 -63
  202. package/src/wnako3.mjs +12 -12
  203. package/src/wnako3.mts +11 -11
  204. package/src/wnako3_editor.css +215 -215
  205. package/src/wnako3_editor.mjs +1542 -1542
  206. package/src/wnako3_editor.mts +1658 -1657
  207. package/src/wnako3mod.mjs +213 -213
  208. package/src/wnako3mod.mts +214 -214
  209. package/src/wnako3webworker.mjs +69 -69
  210. package/test/.DS_Store +0 -0
  211. package/test/ace_editor/karma.config.js +94 -94
  212. package/test/ace_editor/test/.babelrc.json +3 -3
  213. package/test/ace_editor/test/ace_editor_test.js +178 -178
  214. package/test/ace_editor/test/html/custom_context.html +139 -139
  215. package/test/async/async_basic_test.mjs +122 -122
  216. package/test/browser/.DS_Store +0 -0
  217. package/test/browser/karma.config.js +221 -221
  218. package/test/browser/test/.babelrc.json +3 -3
  219. package/test/browser/test/compare_util.js +50 -50
  220. package/test/browser/test/html/div_basic.html +2 -2
  221. package/test/browser/test/html/event_dom_form.html +4 -4
  222. package/test/browser/test/html/event_dom_scrolldiv.html +5 -5
  223. package/test/browser/test/import_plugin_checker.js +24 -24
  224. package/test/browser/test/plugin_browser_test.js +51 -51
  225. package/test/browser/test/plugin_browser_test_ajax.js +123 -123
  226. package/test/browser/test/plugin_browser_test_color.js +18 -18
  227. package/test/browser/test/plugin_browser_test_dialog.js +72 -72
  228. package/test/browser/test/plugin_browser_test_dom_event.js +598 -598
  229. package/test/browser/test/plugin_browser_test_dom_parts.js +125 -125
  230. package/test/browser/test/plugin_browser_test_system.js +9 -9
  231. package/test/browser/test/plugin_turtle_test.js +817 -817
  232. package/test/browser/test/plugin_webworker_test.js +86 -86
  233. package/test/browser/test/require_test.js +68 -68
  234. package/test/bundled/.DS_Store +0 -0
  235. package/test/bundled/karma.config.base.js +117 -117
  236. package/test/bundled/karma.config.js +86 -86
  237. package/test/bundled/test/.babelrc.json +3 -3
  238. package/test/bundled/test/bundled_test.js +69 -69
  239. package/test/bundled/test/html/custom_context.html +65 -65
  240. package/test/bundled/test/html/custom_debug.html +66 -66
  241. package/test/bundled/test4b.cmd +52 -52
  242. package/test/bundled/test_base/.DS_Store +0 -0
  243. package/test/bundled/test_base/.babelrc.json +3 -3
  244. package/test/bundled/test_base/_checktool_test.js +25 -25
  245. package/test/bundled/test_base/basic_ajax_test.js +56 -56
  246. package/test/bundled/test_base/basic_async_test.js +18 -18
  247. package/test/bundled/test_base/basic_test.js +153 -153
  248. package/test/bundled/test_base/calc_test.js +132 -132
  249. package/test/bundled/test_base/css/browsers_box.css +114 -114
  250. package/test/bundled/test_base/html/custom_context.html +69 -69
  251. package/test/bundled/test_base/html/custom_debug.html +71 -71
  252. package/test/bundled/test_base/js/browsers_box.js +72 -72
  253. package/test/bundled/test_base/plugin_csv_test.js +37 -37
  254. package/test/bundled/test_base/plugin_datetime_test.js +115 -115
  255. package/test/bundled/test_base/plugin_kansuji_test.js +49 -49
  256. package/test/bundled/test_base/plugin_system_test.js +410 -410
  257. package/test/bundled/test_base/plugin_webworker_test.js +53 -53
  258. package/test/bundled/test_base/test_utils.js +191 -191
  259. package/test/common/.DS_Store +0 -0
  260. package/test/common/plugin_browser_test.mjs +22 -22
  261. package/test/common/plugin_browser_ut_audio_test.mjs +108 -108
  262. package/test/common/plugin_browser_ut_color_test.mjs +21 -21
  263. package/test/common/plugin_browser_ut_dialog_test.mjs +100 -100
  264. package/test/common/plugin_browser_ut_html_test.mjs +13 -13
  265. package/test/common/plugin_browser_ut_system_test.mjs +10 -10
  266. package/test/common/plugin_markup_test.mjs +23 -23
  267. package/test/jsconfig.json +19 -19
  268. package/test/karma.config.js +91 -91
  269. package/test/node/.DS_Store +0 -0
  270. package/test/node/async_test.mjs +96 -96
  271. package/test/node/commander_ja_test.mjs +89 -89
  272. package/test/node/error_message_test.mjs +243 -243
  273. package/test/node/kai_test.nako3 +6 -6
  274. package/test/node/node_test.mjs +60 -60
  275. package/test/node/plugin_broken.js.txt +3 -3
  276. package/test/node/plugin_browser_ut_ajax_test.mjs.todo +357 -357
  277. package/test/node/plugin_browser_ut_location_test.mjs +42 -42
  278. package/test/node/plugin_markup_test.mjs +47 -47
  279. package/test/node/plugin_math_test.mjs +45 -45
  280. package/test/node/plugin_node_test.mjs +98 -98
  281. package/test/node/plugin_test.mjs +44 -44
  282. package/test/node/relative_import_test_1.nako3 +1 -1
  283. package/test/node/relative_import_test_2.nako3 +2 -2
  284. package/test/node/require_nako3_test.mjs +67 -67
  285. package/test/node/requiretest.nako3 +4 -4
  286. package/test/node/requiretest_indirect.nako3 +1 -1
  287. package/test/node/requiretest_name.nako3 +5 -5
  288. package/test/node/runtime_error.nako3 +2 -2
  289. package/test/node/scope1.nako3 +10 -10
  290. package/test/node/scope2.nako3 +12 -12
  291. package/test/node/side_effects_test.mjs +39 -39
  292. package/test/node/sjis.txt +5 -5
  293. package/test/node/syntax_error.nako3 +1 -1
  294. package/test/node/wnako3_editor_test.mjs +384 -384
  295. package/tools/.DS_Store +0 -0
  296. package/tools/README.md +12 -12
  297. package/tools/check_new_version.nako3 +25 -25
  298. package/tools/nako3edit/.DS_Store +0 -0
  299. package/tools/nako3edit/a.sqlite3 +0 -0
  300. package/tools/nako3edit/html/.DS_Store +0 -0
  301. package/tools/nako3edit/html/daisyui/LICENSE +22 -22
  302. package/tools/nako3edit/html/daisyui/version_2.14.1 +1 -1
  303. package/tools/nako3edit/html/edit.html +170 -170
  304. package/tools/nako3edit/html/edit_plugin.js +6 -6
  305. package/tools/nako3edit/html/files.html +125 -125
  306. package/tools/nako3edit/html/nako3edit.css +65 -65
  307. package/tools/nako3edit/index.mjs +248 -248
  308. package/tools/nako3server/index.html +10 -10
  309. package/tools/nako3server/index.mjs +116 -116
  310. package/tools/nako3server/index.nako3 +34 -34
  311. package/core/.editorconfig +0 -6
  312. package/core/.eslintrc.cjs +0 -33
  313. package/core/.github/dependabot.yml +0 -7
  314. package/core/.github/workflows/nodejs.yml +0 -37
  315. package/core/.github/workflows/super-linter.yml +0 -61
  316. package/core/.github/workflows/textlint.yml +0 -199
  317. package/core/index.mts +0 -21
  318. package/core/test/array_test.mjs +0 -34
  319. package/core/test/basic_test.mjs +0 -344
  320. package/core/test/calc_test.mjs +0 -140
  321. package/core/test/core_module_test.mjs +0 -23
  322. package/core/test/debug_test.mjs +0 -16
  323. package/core/test/dncl_test.mjs +0 -94
  324. package/core/test/error_message_test.mjs +0 -210
  325. package/core/test/error_test.mjs +0 -16
  326. package/core/test/flow_test.mjs +0 -373
  327. package/core/test/func_call.mjs +0 -160
  328. package/core/test/func_test.mjs +0 -149
  329. package/core/test/indent_test.mjs +0 -364
  330. package/core/test/lex_test.mjs +0 -168
  331. package/core/test/literal_test.mjs +0 -73
  332. package/core/test/nako_lexer_test.mjs +0 -35
  333. package/core/test/nako_logger_test.mjs +0 -76
  334. package/core/test/nako_logger_test.mts +0 -78
  335. package/core/test/plugin_csv_test.mjs +0 -38
  336. package/core/test/plugin_promise_test.mjs +0 -18
  337. package/core/test/plugin_system_test.mjs +0 -630
  338. package/core/test/prepare_test.mjs +0 -96
  339. package/core/test/re_test.mjs +0 -22
  340. package/core/test/side_effects_test.mjs +0 -92
  341. package/core/test/variable_scope_test.mjs +0 -149
  342. package/core/tsconfig.json +0 -101
@@ -1,384 +1,384 @@
1
- /* eslint-disable @typescript-eslint/no-empty-function */
2
- // @ts-nocheck
3
- /* eslint-disable no-undef */
4
- import assert from 'assert'
5
- import fs from 'fs'
6
- import path from 'path'
7
- import { expect } from 'chai'
8
-
9
- import { NakoCompiler } from '../../core/src/nako3.mjs'
10
- import { tokenize, LanguageFeatures, BackgroundTokenizer } from '../../src/wnako3_editor.mjs'
11
- import { CNako3 } from '../../src/cnako3mod.mjs'
12
- import { NakoLexerError } from '../../core/src/nako_errors.mjs'
13
-
14
- // __dirname のために
15
- import url from 'url'
16
- // @ts-ignore
17
- const __filename = url.fileURLToPath(import.meta.url)
18
- const __dirname = path.dirname(__filename)
19
-
20
- describe('wnako3_editor_test', () => {
21
- class AceRange {
22
- constructor (/** @type {number} */startLine, /** @type {number} */startColumn, /** @type {number} */endLine, /** @type {number} */endColumn) {
23
- this.startLine = startLine
24
- this.startColumn = startColumn
25
- this.endLine = endLine
26
- this.endColumn = endColumn
27
- }
28
- }
29
- /** @implements {IAceDocument} */
30
- class AceDocument {
31
- constructor (/** @type {string} */text) {
32
- this.lines = text.split('\n')
33
- /** @type {any[]} */
34
- this.log = []
35
- }
36
-
37
- getLine (/** @type {number} */row) { return this.lines[row] }
38
- getLength () { return this.lines.length }
39
- getAllLines () { return [...this.lines] }
40
- insertInLine (/** @type {{ row: number, column: number }} */position, /** @type {string} */text) { this.log.push(['insertInLine', position, text]) }
41
- removeInLine (/** @type {number} */row, /** @type {number} */columnStart, /** @type {number} */columnEnd) { this.log.push(['removeInLine', row, columnStart, columnEnd]) }
42
- replace (/** @type {AceRange} */range, /** @type {string} */text) { this.log.push(['replace', range, text]) }
43
- /** @returns {ISession} */
44
- asSession () { // テスト用
45
- // @ts-ignore
46
- return { doc: this }
47
- }
48
- }
49
- /** @returns {Promise<BackgroundTokenizer>} */
50
- const createBackgroundTokenizer = (/** @type {string} */text, compiler = new NakoCompiler()) => {
51
- return new Promise((resolve, reject) => {
52
- const tokenizer = new BackgroundTokenizer(
53
- new AceDocument(text),
54
- compiler,
55
- () => { resolve(tokenizer) }, // ok
56
- (_, err) => { reject(err) }, // err
57
- true
58
- )
59
- })
60
- }
61
- describe('シンタックスハイライト', () => {
62
- it('コードを分割する', () => {
63
- const tokens = tokenize('A=1\nA+1を表示'.split('\n'), new NakoCompiler(), false).editorTokens
64
-
65
- // 1行目
66
- assert.strictEqual(tokens[0][0].value, 'A')
67
- assert.strictEqual(tokens[0][1].value, '=')
68
- assert.strictEqual(tokens[0][2].value, '1')
69
-
70
- // 2行目
71
- assert.strictEqual(tokens[1][0].value, 'A')
72
- assert.strictEqual(tokens[1][1].value, '+')
73
- assert.strictEqual(tokens[1][2].value, '1を')
74
- assert.strictEqual(tokens[1][3].value, '表示')
75
- })
76
- it('scopeを割り当てる', () => {
77
- const tokens = tokenize('A=1\nA+1を表示'.split('\n'), new NakoCompiler(), false).editorTokens
78
-
79
- // 1行目
80
- assert(tokens[0][0].type.includes('variable'))
81
- assert(tokens[0][1].type.includes('operator'))
82
- assert(tokens[0][2].type.includes('numeric'))
83
-
84
- // 2行目
85
- assert(tokens[1][0].type.includes('variable'))
86
- assert(tokens[1][1].type.includes('operator'))
87
- assert(tokens[1][2].type.includes('numeric'))
88
- assert(tokens[1][3].type.includes('function'))
89
- })
90
- it('取り込み文を無視する', () => {
91
- tokenize('!「http://www.example.com/non_existent_file.nako3」を取り込む。'.split('\n'), new NakoCompiler(), false)
92
- })
93
- it('助詞に下線を引く', () => {
94
- const tokens = tokenize('「\n」を表示'.split('\n'), new NakoCompiler(), true).editorTokens
95
- assert.strictEqual(tokens[1][0].value, '」')
96
- assert(tokens[1][0].type.includes('string'))
97
-
98
- assert.strictEqual(tokens[1][1].value, 'を')
99
- assert(tokens[1][1].type.includes('underline'))
100
-
101
- assert.strictEqual(tokens[1][2].value, '表示')
102
- assert(tokens[1][2].type.includes('function'))
103
- })
104
- // todo
105
- /*
106
- it('依存ファイルのキャッシュを利用する', () => {
107
- const nako3 = new CNako3()
108
- const code = '!「./requiretest_indirect.nako3」を取り込む\n1と2の痕跡演算'
109
- const file = path.join(__dirname, 'main.nako3')
110
- nako3.loadDependencies(code, file, '')
111
- const tokens = tokenize(code.split('\n'), nako3, true)
112
-
113
- // 「痕跡演算」が関数として認識されていることを確認する。
114
- const token = tokens.editorTokens[1].find((token) => token.value === '痕跡演算')
115
- expect(token).to.have.property('type').and.to.include('function')
116
- })
117
- it('シンタックスハイライトにかかる時間が依存ファイルの行数に依存しないことを確認', () => {
118
- // 一時的に大きいファイルを作成
119
- const largeFile = path.join(__dirname, 'large_file.nako3')
120
- assert(!fs.existsSync(largeFile))
121
- fs.writeFileSync(largeFile, '●(Aを)large_fileとは\nここまで\nA=1+2+3+4+5\n'.repeat(1000))
122
- try {
123
- // 大きいファイルを取り込むコードを実行
124
- const code = '!「./large_file.nako3」を取り込む\n1をlarge_file'
125
- const file = path.join(__dirname, 'main.nako3')
126
-
127
- const nako3 = new CNako3()
128
- console.time('loadDependencies')
129
- nako3.loadDependencies(code, file, '') // この行は遅いが、取り込み文に変更が合った時しか呼ばれない
130
- console.timeEnd('loadDependencies')
131
-
132
- const startTime = process.hrtime.bigint()
133
- console.time('tokenize')
134
- const tokens = tokenize(code.split('\n'), nako3, true) // この行は速い必要がある
135
- const delta = process.hrtime.bigint() - startTime
136
- console.timeEnd('tokenize')
137
-
138
- // 200ms以下で終わることを確認
139
- // GitHub Actions で10〜40msくらいかかる。
140
- assert(delta <= BigInt(200000000))
141
-
142
- // 取り込みが行われたことを確認する
143
- const token = tokens.editorTokens[1].find((token) => token.value === 'large_file')
144
- expect(token).to.have.property('type').and.to.include('function')
145
- } finally {
146
- fs.unlinkSync(largeFile)
147
- }
148
- })
149
- */
150
- it('明示的に取り込んだプラグインの関数', async () => {
151
- const compiler = new CNako3()
152
- const code = '!「plugin_csv.mjs」を取り込む\n「1」のCSV取得'
153
- await compiler.loadDependencies(code, '', '')
154
- const token = tokenize(code.split('\n'), compiler, false).editorTokens[1][1]
155
- expect(token.type).to.include('function')
156
- expect(token.docHTML).to.include('CSV取得')
157
- expect(token.value).to.equal('CSV取得')
158
- })
159
- })
160
- describe('ドキュメントのホバー', () => {
161
- it('プラグイン関数の助詞のドキュメントを表示する', () => {
162
- const nako3 = new NakoCompiler()
163
- nako3.addPluginObject('PluginEditorTest', {
164
- 'プラグイン関数テスト': {
165
- type: 'func',
166
- josi: [['を', 'と'], ['に', 'は']],
167
- fn: () => {}
168
- }
169
- })
170
-
171
- const token = tokenize('XをYにプラグイン関数テスト'.split('\n'), nako3, false)
172
- .editorTokens[0]
173
- .find((t) => t.value === 'プラグイン関数テスト')
174
- expect(token).to.have.property('docHTML').and.to.include('(Aを|Aと、Bに|Bは)')
175
- expect(token).to.have.property('docHTML').and.to.include('PluginEditorTest')
176
- })
177
- it('ユーザー定義関数の助詞のドキュメントを表示する', () => {
178
- const token = tokenize('●(Aを)Fとは\nここまで\n1をF'.split('\n'), new NakoCompiler(), false)
179
- .editorTokens[2]
180
- .find((t) => t.value === 'F')
181
- expect(token).to.have.property('docHTML').and.to.include('(Aを)')
182
- })
183
- it('前回の実行結果の影響を受けない', () => {
184
- const nako3 = new NakoCompiler()
185
- tokenize('●(Aを)Fとは\nここまで\n1をF'.split('\n'), nako3, false)
186
- const token = tokenize('1をF'.split('\n'), nako3, false)
187
- .editorTokens[0]
188
- .find((t) => t.value === 'F')
189
- // eslint-disable-next-line no-unused-expressions
190
- expect(token).to.have.property('docHTML').and.is.null
191
- })
192
- })
193
- describe('行コメントのトグル', () => {
194
- it('コメントアウト', () => {
195
- const doc = new AceDocument('abc\n')
196
- LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 1)
197
- assert.deepStrictEqual(doc.log, [
198
- ['insertInLine', { row: 0, column: 0 }, '// '],
199
- ['insertInLine', { row: 1, column: 0 }, '// ']
200
- ])
201
- })
202
- it('アンコメント', () => {
203
- const doc = new AceDocument('// abc\n\n※def')
204
- LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 2)
205
- assert.deepStrictEqual(doc.log, [
206
- ['removeInLine', 0, 0, 3], // '// ' を削除
207
- ['removeInLine', 2, 0, 1] // '※' を削除
208
- ])
209
- })
210
- it('中黒のある場合', () => {
211
- const doc = new AceDocument('・・abc')
212
- LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 0)
213
- assert.deepStrictEqual(doc.log, [
214
- ['insertInLine', { row: 0, column: 2 }, '// '] // 'abc' の直前に挿入
215
- ])
216
- })
217
- })
218
- describe('auto outdent', () => {
219
- it('「ここまで」を入力し終わった瞬間に発火する', () => {
220
- assert(!LanguageFeatures.checkOutdent('start', ' ここ', 'ま'))
221
- assert(LanguageFeatures.checkOutdent('start', ' ここま', 'で'))
222
- assert(!LanguageFeatures.checkOutdent('start', ' ここまで', '\n'))
223
-
224
- assert(!LanguageFeatures.checkOutdent('start', '・ここ', 'ま'))
225
- assert(LanguageFeatures.checkOutdent('start', '・ここま', 'で'))
226
- assert(!LanguageFeatures.checkOutdent('start', '・ここまで', '\n'))
227
- })
228
- it('1つ前の行がブロックの開始行なら、その行に合わせる', () => {
229
- const doc = new AceDocument(' もしはいならば\n ここまで')
230
- // 2行目にauto outdentを実行
231
- new LanguageFeatures(AceRange, new NakoCompiler()).autoOutdent('start', doc.asSession(), 1)
232
- // 2行目の0-8文字目が ' ' で置換される
233
- assert.deepStrictEqual(doc.log, [['replace', new AceRange(1, 0, 1, 8), ' ']])
234
- })
235
- it('1つ前の行がブロックの開始行でなければ、1段階インデントを下げる', () => {
236
- const doc = new AceDocument('もしはいならば\n もしはいならば\n 1を表示\n ここまで')
237
- // 4行目にauto outdentを実行
238
- new LanguageFeatures(AceRange, new NakoCompiler()).autoOutdent('start', doc.asSession(), 3)
239
- // 2行目の0-8文字目が ' ' で置換される
240
- assert.deepStrictEqual(doc.log, [['replace', new AceRange(3, 0, 3, 8), ' ']])
241
- })
242
- })
243
- describe('auto indent', () => {
244
- it('0列目の場合', () => {
245
- // 1段階インデントする
246
- assert.strictEqual(
247
- LanguageFeatures.getNextLineIndent('start', 'もしはいならば', ' '),
248
- ' '
249
- )
250
- })
251
- it('4列目の場合', () => {
252
- // 1段階インデントする
253
- assert.strictEqual(
254
- LanguageFeatures.getNextLineIndent('start', ' もしはいならば', ' '),
255
- ' '
256
- )
257
- })
258
- it('ブロックの開始行ではない場合', () => {
259
- // 1つ前の行と同じインデント幅を返す
260
- assert.strictEqual(
261
- LanguageFeatures.getNextLineIndent('start', ' もしはい', ' '),
262
- ' '
263
- )
264
- })
265
- })
266
- describe('バックグラウンドでコードをトークン化する', () => {
267
- it('成功時', async () => {
268
- const t = await createBackgroundTokenizer('1を表示')
269
- // 0行目の0、1、2個目のトークン
270
- expect(t.lines[0][0]).to.include({ type: 'constant.numeric', docHTML: null, value: '1' })
271
- expect(t.lines[0][1]).to.include({ type: 'constant.numeric.markup.underline', value: 'を' })
272
- expect(t.lines[0][2]).to.include({ type: 'entity.name.function', value: '表示' })
273
- })
274
- it('失敗時', async () => {
275
- let ok = false
276
- try {
277
- await createBackgroundTokenizer('「{」')
278
- } catch (err) {
279
- expect(err).to.be.instanceOf(NakoLexerError)
280
- ok = true
281
- }
282
- if (!ok) { throw new Error() }
283
- })
284
- })
285
- describe('オートコンプリート', () => {
286
- // todo
287
- /*
288
- it('同一ファイル内の関数', async () => {
289
- const compiler = new NakoCompiler()
290
- const tokenizer = await createBackgroundTokenizer('●(Aを)テスト用関数とは\nここまで\n', compiler)
291
- expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
292
- caption: "(Aを)テスト用関数",
293
- value: "テスト用関数",
294
- meta: "関数",
295
- score: 0,
296
- })
297
- })
298
- */
299
- it('同一ファイルの変数', async () => {
300
- const compiler = new NakoCompiler()
301
- const tokenizer = await createBackgroundTokenizer('テスト用変数=10\nここまで\n', compiler)
302
- expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
303
- caption: 'テスト用変数',
304
- value: 'テスト用変数',
305
- meta: '変数',
306
- score: 0
307
- })
308
- })
309
- it('組み込みのプラグイン関数', async () => {
310
- const compiler = new NakoCompiler()
311
- compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン関数': { type: 'func', josi: [['を'], ['に']], pure: true, fn: () => {} } })
312
- const tokenizer = await createBackgroundTokenizer('', compiler)
313
- expect(LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)).to.deep.include({
314
- caption: '(Aを、Bに)テスト用プラグイン関数',
315
- value: 'テスト用プラグイン関数',
316
- meta: 'PluginEditorTest',
317
- score: 0
318
- })
319
- })
320
- it('組み込みのプラグイン変数', async () => {
321
- const compiler = new NakoCompiler()
322
- compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン変数': { type: 'var', value: 0 } })
323
- const tokenizer = await createBackgroundTokenizer('', compiler)
324
- expect(LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)).to.deep.include({
325
- caption: 'テスト用プラグイン変数',
326
- value: 'テスト用プラグイン変数',
327
- meta: 'PluginEditorTest',
328
- score: 0
329
- })
330
- })
331
- // todo
332
- /*
333
- it('別ファイルの関数', async () => {
334
- const compiler = new CNako3()
335
- const code = `!「${__dirname}/requiretest.nako3」を取り込む\n`
336
- compiler.loadDependencies(code, '', '')
337
- const tokenizer = await createBackgroundTokenizer(code, compiler)
338
- const result = LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)
339
- assert(result.some((v) => v.caption === '(Aと、Bを)痕跡演算'))
340
- })
341
- */
342
- it('関数の呼び出しはmetaの値に影響を与えない', async () => {
343
- const compiler = new NakoCompiler()
344
- compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン関数': { type: 'func', josi: [['を'], ['に']], pure: true, fn: () => {} } })
345
- const tokenizer = await createBackgroundTokenizer('テスト用プラグイン関数\n', compiler)
346
- const result = LanguageFeatures.getCompletionItems(1, '', compiler, tokenizer)
347
- assert.deepStrictEqual(result.filter((v) => v.value === 'テスト用プラグイン関数'), [
348
- {
349
- caption: '(Aを、Bに)テスト用プラグイン関数',
350
- value: 'テスト用プラグイン関数',
351
- meta: 'PluginEditorTest', // ここに `関数` が表示されないことを確認する
352
- score: 0
353
- }
354
- ])
355
- })
356
- // todo
357
- /*
358
- it('同一名の関数の定義が複数あるとき、候補には1つしか表示しない', async () => {
359
- const compiler = new NakoCompiler()
360
- const tokenizer = await createBackgroundTokenizer('●(Aを)テスト用関数とは\nここまで\n●(Aを)テスト用関数とは\nここまで\n', compiler)
361
- expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
362
- caption: "(Aを)テスト用関数",
363
- value: "テスト用関数",
364
- meta: "関数", // `関数, 関数` にならないことを確認する
365
- score: 0,
366
- })
367
- })
368
- */
369
- })
370
- it('テスト定義に実行ボタンを表示する', () => {
371
- const out = LanguageFeatures.getCodeLens(new AceDocument(
372
- '●テスト:足すとは\n' +
373
- 'ここまで\n' +
374
- '●(AとBを)足すとは\n' +
375
- 'ここまで\n' +
376
- '●テスト:引くとは\n' +
377
- 'ここまで\n'
378
- ))
379
- assert.deepStrictEqual(out, [
380
- { start: { row: 0 }, command: { title: 'テストを実行', id: 'runTest', arguments: ['足す'] } },
381
- { start: { row: 4 }, command: { title: 'テストを実行', id: 'runTest', arguments: ['引く'] } }
382
- ])
383
- })
384
- })
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ // @ts-nocheck
3
+ /* eslint-disable no-undef */
4
+ import assert from 'assert'
5
+ import fs from 'fs'
6
+ import path from 'path'
7
+ import { expect } from 'chai'
8
+
9
+ import { NakoCompiler } from '../../core/src/nako3.mjs'
10
+ import { tokenize, LanguageFeatures, BackgroundTokenizer } from '../../src/wnako3_editor.mjs'
11
+ import { CNako3 } from '../../src/cnako3mod.mjs'
12
+ import { NakoLexerError } from '../../core/src/nako_errors.mjs'
13
+
14
+ // __dirname のために
15
+ import url from 'url'
16
+ // @ts-ignore
17
+ const __filename = url.fileURLToPath(import.meta.url)
18
+ const __dirname = path.dirname(__filename)
19
+
20
+ describe('wnako3_editor_test', () => {
21
+ class AceRange {
22
+ constructor (/** @type {number} */startLine, /** @type {number} */startColumn, /** @type {number} */endLine, /** @type {number} */endColumn) {
23
+ this.startLine = startLine
24
+ this.startColumn = startColumn
25
+ this.endLine = endLine
26
+ this.endColumn = endColumn
27
+ }
28
+ }
29
+ /** @implements {IAceDocument} */
30
+ class AceDocument {
31
+ constructor (/** @type {string} */text) {
32
+ this.lines = text.split('\n')
33
+ /** @type {any[]} */
34
+ this.log = []
35
+ }
36
+
37
+ getLine (/** @type {number} */row) { return this.lines[row] }
38
+ getLength () { return this.lines.length }
39
+ getAllLines () { return [...this.lines] }
40
+ insertInLine (/** @type {{ row: number, column: number }} */position, /** @type {string} */text) { this.log.push(['insertInLine', position, text]) }
41
+ removeInLine (/** @type {number} */row, /** @type {number} */columnStart, /** @type {number} */columnEnd) { this.log.push(['removeInLine', row, columnStart, columnEnd]) }
42
+ replace (/** @type {AceRange} */range, /** @type {string} */text) { this.log.push(['replace', range, text]) }
43
+ /** @returns {ISession} */
44
+ asSession () { // テスト用
45
+ // @ts-ignore
46
+ return { doc: this }
47
+ }
48
+ }
49
+ /** @returns {Promise<BackgroundTokenizer>} */
50
+ const createBackgroundTokenizer = (/** @type {string} */text, compiler = new NakoCompiler()) => {
51
+ return new Promise((resolve, reject) => {
52
+ const tokenizer = new BackgroundTokenizer(
53
+ new AceDocument(text),
54
+ compiler,
55
+ () => { resolve(tokenizer) }, // ok
56
+ (_, err) => { reject(err) }, // err
57
+ true
58
+ )
59
+ })
60
+ }
61
+ describe('シンタックスハイライト', () => {
62
+ it('コードを分割する', () => {
63
+ const tokens = tokenize('A=1\nA+1を表示'.split('\n'), new NakoCompiler(), false).editorTokens
64
+
65
+ // 1行目
66
+ assert.strictEqual(tokens[0][0].value, 'A')
67
+ assert.strictEqual(tokens[0][1].value, '=')
68
+ assert.strictEqual(tokens[0][2].value, '1')
69
+
70
+ // 2行目
71
+ assert.strictEqual(tokens[1][0].value, 'A')
72
+ assert.strictEqual(tokens[1][1].value, '+')
73
+ assert.strictEqual(tokens[1][2].value, '1を')
74
+ assert.strictEqual(tokens[1][3].value, '表示')
75
+ })
76
+ it('scopeを割り当てる', () => {
77
+ const tokens = tokenize('A=1\nA+1を表示'.split('\n'), new NakoCompiler(), false).editorTokens
78
+
79
+ // 1行目
80
+ assert(tokens[0][0].type.includes('variable'))
81
+ assert(tokens[0][1].type.includes('operator'))
82
+ assert(tokens[0][2].type.includes('numeric'))
83
+
84
+ // 2行目
85
+ assert(tokens[1][0].type.includes('variable'))
86
+ assert(tokens[1][1].type.includes('operator'))
87
+ assert(tokens[1][2].type.includes('numeric'))
88
+ assert(tokens[1][3].type.includes('function'))
89
+ })
90
+ it('取り込み文を無視する', () => {
91
+ tokenize('!「http://www.example.com/non_existent_file.nako3」を取り込む。'.split('\n'), new NakoCompiler(), false)
92
+ })
93
+ it('助詞に下線を引く', () => {
94
+ const tokens = tokenize('「\n」を表示'.split('\n'), new NakoCompiler(), true).editorTokens
95
+ assert.strictEqual(tokens[1][0].value, '」')
96
+ assert(tokens[1][0].type.includes('string'))
97
+
98
+ assert.strictEqual(tokens[1][1].value, 'を')
99
+ assert(tokens[1][1].type.includes('underline'))
100
+
101
+ assert.strictEqual(tokens[1][2].value, '表示')
102
+ assert(tokens[1][2].type.includes('function'))
103
+ })
104
+ // todo
105
+ /*
106
+ it('依存ファイルのキャッシュを利用する', () => {
107
+ const nako3 = new CNako3()
108
+ const code = '!「./requiretest_indirect.nako3」を取り込む\n1と2の痕跡演算'
109
+ const file = path.join(__dirname, 'main.nako3')
110
+ nako3.loadDependencies(code, file, '')
111
+ const tokens = tokenize(code.split('\n'), nako3, true)
112
+
113
+ // 「痕跡演算」が関数として認識されていることを確認する。
114
+ const token = tokens.editorTokens[1].find((token) => token.value === '痕跡演算')
115
+ expect(token).to.have.property('type').and.to.include('function')
116
+ })
117
+ it('シンタックスハイライトにかかる時間が依存ファイルの行数に依存しないことを確認', () => {
118
+ // 一時的に大きいファイルを作成
119
+ const largeFile = path.join(__dirname, 'large_file.nako3')
120
+ assert(!fs.existsSync(largeFile))
121
+ fs.writeFileSync(largeFile, '●(Aを)large_fileとは\nここまで\nA=1+2+3+4+5\n'.repeat(1000))
122
+ try {
123
+ // 大きいファイルを取り込むコードを実行
124
+ const code = '!「./large_file.nako3」を取り込む\n1をlarge_file'
125
+ const file = path.join(__dirname, 'main.nako3')
126
+
127
+ const nako3 = new CNako3()
128
+ console.time('loadDependencies')
129
+ nako3.loadDependencies(code, file, '') // この行は遅いが、取り込み文に変更が合った時しか呼ばれない
130
+ console.timeEnd('loadDependencies')
131
+
132
+ const startTime = process.hrtime.bigint()
133
+ console.time('tokenize')
134
+ const tokens = tokenize(code.split('\n'), nako3, true) // この行は速い必要がある
135
+ const delta = process.hrtime.bigint() - startTime
136
+ console.timeEnd('tokenize')
137
+
138
+ // 200ms以下で終わることを確認
139
+ // GitHub Actions で10〜40msくらいかかる。
140
+ assert(delta <= BigInt(200000000))
141
+
142
+ // 取り込みが行われたことを確認する
143
+ const token = tokens.editorTokens[1].find((token) => token.value === 'large_file')
144
+ expect(token).to.have.property('type').and.to.include('function')
145
+ } finally {
146
+ fs.unlinkSync(largeFile)
147
+ }
148
+ })
149
+ */
150
+ it('明示的に取り込んだプラグインの関数', async () => {
151
+ const compiler = new CNako3()
152
+ const code = '!「plugin_csv.mjs」を取り込む\n「1」のCSV取得'
153
+ await compiler.loadDependencies(code, '', '')
154
+ const token = tokenize(code.split('\n'), compiler, false).editorTokens[1][1]
155
+ expect(token.type).to.include('function')
156
+ expect(token.docHTML).to.include('CSV取得')
157
+ expect(token.value).to.equal('CSV取得')
158
+ })
159
+ })
160
+ describe('ドキュメントのホバー', () => {
161
+ it('プラグイン関数の助詞のドキュメントを表示する', () => {
162
+ const nako3 = new NakoCompiler()
163
+ nako3.addPluginObject('PluginEditorTest', {
164
+ 'プラグイン関数テスト': {
165
+ type: 'func',
166
+ josi: [['を', 'と'], ['に', 'は']],
167
+ fn: () => {}
168
+ }
169
+ })
170
+
171
+ const token = tokenize('XをYにプラグイン関数テスト'.split('\n'), nako3, false)
172
+ .editorTokens[0]
173
+ .find((t) => t.value === 'プラグイン関数テスト')
174
+ expect(token).to.have.property('docHTML').and.to.include('(Aを|Aと、Bに|Bは)')
175
+ expect(token).to.have.property('docHTML').and.to.include('PluginEditorTest')
176
+ })
177
+ it('ユーザー定義関数の助詞のドキュメントを表示する', () => {
178
+ const token = tokenize('●(Aを)Fとは\nここまで\n1をF'.split('\n'), new NakoCompiler(), false)
179
+ .editorTokens[2]
180
+ .find((t) => t.value === 'F')
181
+ expect(token).to.have.property('docHTML').and.to.include('(Aを)')
182
+ })
183
+ it('前回の実行結果の影響を受けない', () => {
184
+ const nako3 = new NakoCompiler()
185
+ tokenize('●(Aを)Fとは\nここまで\n1をF'.split('\n'), nako3, false)
186
+ const token = tokenize('1をF'.split('\n'), nako3, false)
187
+ .editorTokens[0]
188
+ .find((t) => t.value === 'F')
189
+ // eslint-disable-next-line no-unused-expressions
190
+ expect(token).to.have.property('docHTML').and.is.null
191
+ })
192
+ })
193
+ describe('行コメントのトグル', () => {
194
+ it('コメントアウト', () => {
195
+ const doc = new AceDocument('abc\n')
196
+ LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 1)
197
+ assert.deepStrictEqual(doc.log, [
198
+ ['insertInLine', { row: 0, column: 0 }, '// '],
199
+ ['insertInLine', { row: 1, column: 0 }, '// ']
200
+ ])
201
+ })
202
+ it('アンコメント', () => {
203
+ const doc = new AceDocument('// abc\n\n※def')
204
+ LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 2)
205
+ assert.deepStrictEqual(doc.log, [
206
+ ['removeInLine', 0, 0, 3], // '// ' を削除
207
+ ['removeInLine', 2, 0, 1] // '※' を削除
208
+ ])
209
+ })
210
+ it('中黒のある場合', () => {
211
+ const doc = new AceDocument('・・abc')
212
+ LanguageFeatures.toggleCommentLines('', doc.asSession(), 0, 0)
213
+ assert.deepStrictEqual(doc.log, [
214
+ ['insertInLine', { row: 0, column: 2 }, '// '] // 'abc' の直前に挿入
215
+ ])
216
+ })
217
+ })
218
+ describe('auto outdent', () => {
219
+ it('「ここまで」を入力し終わった瞬間に発火する', () => {
220
+ assert(!LanguageFeatures.checkOutdent('start', ' ここ', 'ま'))
221
+ assert(LanguageFeatures.checkOutdent('start', ' ここま', 'で'))
222
+ assert(!LanguageFeatures.checkOutdent('start', ' ここまで', '\n'))
223
+
224
+ assert(!LanguageFeatures.checkOutdent('start', '・ここ', 'ま'))
225
+ assert(LanguageFeatures.checkOutdent('start', '・ここま', 'で'))
226
+ assert(!LanguageFeatures.checkOutdent('start', '・ここまで', '\n'))
227
+ })
228
+ it('1つ前の行がブロックの開始行なら、その行に合わせる', () => {
229
+ const doc = new AceDocument(' もしはいならば\n ここまで')
230
+ // 2行目にauto outdentを実行
231
+ new LanguageFeatures(AceRange, new NakoCompiler()).autoOutdent('start', doc.asSession(), 1)
232
+ // 2行目の0-8文字目が ' ' で置換される
233
+ assert.deepStrictEqual(doc.log, [['replace', new AceRange(1, 0, 1, 8), ' ']])
234
+ })
235
+ it('1つ前の行がブロックの開始行でなければ、1段階インデントを下げる', () => {
236
+ const doc = new AceDocument('もしはいならば\n もしはいならば\n 1を表示\n ここまで')
237
+ // 4行目にauto outdentを実行
238
+ new LanguageFeatures(AceRange, new NakoCompiler()).autoOutdent('start', doc.asSession(), 3)
239
+ // 2行目の0-8文字目が ' ' で置換される
240
+ assert.deepStrictEqual(doc.log, [['replace', new AceRange(3, 0, 3, 8), ' ']])
241
+ })
242
+ })
243
+ describe('auto indent', () => {
244
+ it('0列目の場合', () => {
245
+ // 1段階インデントする
246
+ assert.strictEqual(
247
+ LanguageFeatures.getNextLineIndent('start', 'もしはいならば', ' '),
248
+ ' '
249
+ )
250
+ })
251
+ it('4列目の場合', () => {
252
+ // 1段階インデントする
253
+ assert.strictEqual(
254
+ LanguageFeatures.getNextLineIndent('start', ' もしはいならば', ' '),
255
+ ' '
256
+ )
257
+ })
258
+ it('ブロックの開始行ではない場合', () => {
259
+ // 1つ前の行と同じインデント幅を返す
260
+ assert.strictEqual(
261
+ LanguageFeatures.getNextLineIndent('start', ' もしはい', ' '),
262
+ ' '
263
+ )
264
+ })
265
+ })
266
+ describe('バックグラウンドでコードをトークン化する', () => {
267
+ it('成功時', async () => {
268
+ const t = await createBackgroundTokenizer('1を表示')
269
+ // 0行目の0、1、2個目のトークン
270
+ expect(t.lines[0][0]).to.include({ type: 'constant.numeric', docHTML: null, value: '1' })
271
+ expect(t.lines[0][1]).to.include({ type: 'constant.numeric.markup.underline', value: 'を' })
272
+ expect(t.lines[0][2]).to.include({ type: 'entity.name.function', value: '表示' })
273
+ })
274
+ it('失敗時', async () => {
275
+ let ok = false
276
+ try {
277
+ await createBackgroundTokenizer('「{」')
278
+ } catch (err) {
279
+ expect(err).to.be.instanceOf(NakoLexerError)
280
+ ok = true
281
+ }
282
+ if (!ok) { throw new Error() }
283
+ })
284
+ })
285
+ describe('オートコンプリート', () => {
286
+ // todo
287
+ /*
288
+ it('同一ファイル内の関数', async () => {
289
+ const compiler = new NakoCompiler()
290
+ const tokenizer = await createBackgroundTokenizer('●(Aを)テスト用関数とは\nここまで\n', compiler)
291
+ expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
292
+ caption: "(Aを)テスト用関数",
293
+ value: "テスト用関数",
294
+ meta: "関数",
295
+ score: 0,
296
+ })
297
+ })
298
+ */
299
+ it('同一ファイルの変数', async () => {
300
+ const compiler = new NakoCompiler()
301
+ const tokenizer = await createBackgroundTokenizer('テスト用変数=10\nここまで\n', compiler)
302
+ expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
303
+ caption: 'テスト用変数',
304
+ value: 'テスト用変数',
305
+ meta: '変数',
306
+ score: 0
307
+ })
308
+ })
309
+ it('組み込みのプラグイン関数', async () => {
310
+ const compiler = new NakoCompiler()
311
+ compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン関数': { type: 'func', josi: [['を'], ['に']], pure: true, fn: () => {} } })
312
+ const tokenizer = await createBackgroundTokenizer('', compiler)
313
+ expect(LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)).to.deep.include({
314
+ caption: '(Aを、Bに)テスト用プラグイン関数',
315
+ value: 'テスト用プラグイン関数',
316
+ meta: 'PluginEditorTest',
317
+ score: 0
318
+ })
319
+ })
320
+ it('組み込みのプラグイン変数', async () => {
321
+ const compiler = new NakoCompiler()
322
+ compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン変数': { type: 'var', value: 0 } })
323
+ const tokenizer = await createBackgroundTokenizer('', compiler)
324
+ expect(LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)).to.deep.include({
325
+ caption: 'テスト用プラグイン変数',
326
+ value: 'テスト用プラグイン変数',
327
+ meta: 'PluginEditorTest',
328
+ score: 0
329
+ })
330
+ })
331
+ // todo
332
+ /*
333
+ it('別ファイルの関数', async () => {
334
+ const compiler = new CNako3()
335
+ const code = `!「${__dirname}/requiretest.nako3」を取り込む\n`
336
+ compiler.loadDependencies(code, '', '')
337
+ const tokenizer = await createBackgroundTokenizer(code, compiler)
338
+ const result = LanguageFeatures.getCompletionItems(0, '', compiler, tokenizer)
339
+ assert(result.some((v) => v.caption === '(Aと、Bを)痕跡演算'))
340
+ })
341
+ */
342
+ it('関数の呼び出しはmetaの値に影響を与えない', async () => {
343
+ const compiler = new NakoCompiler()
344
+ compiler.addPluginObject('PluginEditorTest', { 'テスト用プラグイン関数': { type: 'func', josi: [['を'], ['に']], pure: true, fn: () => {} } })
345
+ const tokenizer = await createBackgroundTokenizer('テスト用プラグイン関数\n', compiler)
346
+ const result = LanguageFeatures.getCompletionItems(1, '', compiler, tokenizer)
347
+ assert.deepStrictEqual(result.filter((v) => v.value === 'テスト用プラグイン関数'), [
348
+ {
349
+ caption: '(Aを、Bに)テスト用プラグイン関数',
350
+ value: 'テスト用プラグイン関数',
351
+ meta: 'PluginEditorTest', // ここに `関数` が表示されないことを確認する
352
+ score: 0
353
+ }
354
+ ])
355
+ })
356
+ // todo
357
+ /*
358
+ it('同一名の関数の定義が複数あるとき、候補には1つしか表示しない', async () => {
359
+ const compiler = new NakoCompiler()
360
+ const tokenizer = await createBackgroundTokenizer('●(Aを)テスト用関数とは\nここまで\n●(Aを)テスト用関数とは\nここまで\n', compiler)
361
+ expect(LanguageFeatures.getCompletionItems(2, '', compiler, tokenizer)).to.deep.include({
362
+ caption: "(Aを)テスト用関数",
363
+ value: "テスト用関数",
364
+ meta: "関数", // `関数, 関数` にならないことを確認する
365
+ score: 0,
366
+ })
367
+ })
368
+ */
369
+ })
370
+ it('テスト定義に実行ボタンを表示する', () => {
371
+ const out = LanguageFeatures.getCodeLens(new AceDocument(
372
+ '●テスト:足すとは\n' +
373
+ 'ここまで\n' +
374
+ '●(AとBを)足すとは\n' +
375
+ 'ここまで\n' +
376
+ '●テスト:引くとは\n' +
377
+ 'ここまで\n'
378
+ ))
379
+ assert.deepStrictEqual(out, [
380
+ { start: { row: 0 }, command: { title: 'テストを実行', id: 'runTest', arguments: ['足す'] } },
381
+ { start: { row: 4 }, command: { title: 'テストを実行', id: 'runTest', arguments: ['引く'] } }
382
+ ])
383
+ })
384
+ })