ic-mops 2.0.1 → 2.2.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 (189) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/RELEASE.md +198 -0
  3. package/bundle/cli.tgz +0 -0
  4. package/check-requirements.ts +3 -8
  5. package/cli.ts +94 -11
  6. package/commands/bench/bench-canister.mo +17 -6
  7. package/commands/bench.ts +13 -16
  8. package/commands/build.ts +5 -6
  9. package/commands/check.ts +121 -0
  10. package/commands/format.ts +3 -18
  11. package/commands/lint.ts +92 -0
  12. package/commands/sync.ts +2 -8
  13. package/commands/test/test.ts +10 -20
  14. package/commands/toolchain/index.ts +21 -8
  15. package/commands/toolchain/lintoko.ts +54 -0
  16. package/commands/toolchain/toolchain-utils.ts +2 -0
  17. package/commands/watch/error-checker.ts +8 -2
  18. package/commands/watch/warning-checker.ts +8 -2
  19. package/constants.ts +23 -0
  20. package/dist/check-requirements.js +3 -8
  21. package/dist/cli.js +73 -11
  22. package/dist/commands/bench/bench-canister.mo +17 -6
  23. package/dist/commands/bench.js +7 -15
  24. package/dist/commands/build.js +5 -6
  25. package/dist/commands/check.d.ts +6 -0
  26. package/dist/commands/check.js +82 -0
  27. package/dist/commands/format.js +3 -16
  28. package/dist/commands/lint.d.ts +7 -0
  29. package/dist/commands/lint.js +69 -0
  30. package/dist/commands/sync.js +2 -7
  31. package/dist/commands/test/test.js +10 -18
  32. package/dist/commands/toolchain/index.d.ts +2 -2
  33. package/dist/commands/toolchain/index.js +18 -7
  34. package/dist/commands/toolchain/lintoko.d.ts +8 -0
  35. package/dist/commands/toolchain/lintoko.js +36 -0
  36. package/dist/commands/toolchain/toolchain-utils.d.ts +1 -0
  37. package/dist/commands/toolchain/toolchain-utils.js +1 -0
  38. package/dist/commands/watch/error-checker.js +8 -2
  39. package/dist/commands/watch/warning-checker.js +8 -2
  40. package/dist/constants.d.ts +15 -0
  41. package/dist/constants.js +21 -0
  42. package/dist/environments/nodejs/cli.js +6 -1
  43. package/dist/error.d.ts +1 -1
  44. package/dist/helpers/autofix-motoko.d.ts +26 -0
  45. package/dist/helpers/autofix-motoko.js +150 -0
  46. package/dist/helpers/get-moc-version.d.ts +2 -0
  47. package/dist/helpers/get-moc-version.js +10 -1
  48. package/dist/mops.d.ts +1 -0
  49. package/dist/mops.js +12 -1
  50. package/dist/package.json +3 -2
  51. package/dist/tests/build-no-dfx.test.d.ts +1 -0
  52. package/dist/tests/build-no-dfx.test.js +9 -0
  53. package/dist/tests/build.test.d.ts +1 -0
  54. package/dist/tests/build.test.js +18 -0
  55. package/dist/tests/check-candid.test.d.ts +1 -0
  56. package/dist/tests/check-candid.test.js +20 -0
  57. package/dist/tests/check-fix.test.d.ts +1 -0
  58. package/dist/tests/check-fix.test.js +89 -0
  59. package/dist/tests/check.test.d.ts +1 -0
  60. package/dist/tests/check.test.js +37 -0
  61. package/dist/tests/cli.test.js +4 -57
  62. package/dist/tests/helpers.d.ts +22 -0
  63. package/dist/tests/helpers.js +43 -0
  64. package/dist/tests/lint.test.d.ts +1 -0
  65. package/dist/tests/lint.test.js +15 -0
  66. package/dist/tests/moc-args.test.d.ts +1 -0
  67. package/dist/tests/moc-args.test.js +17 -0
  68. package/dist/tests/toolchain.test.d.ts +1 -0
  69. package/dist/tests/toolchain.test.js +11 -0
  70. package/dist/types.d.ts +8 -1
  71. package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  72. package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
  73. package/environments/nodejs/cli.ts +7 -1
  74. package/error.ts +1 -1
  75. package/helpers/autofix-motoko.ts +240 -0
  76. package/helpers/get-moc-version.ts +12 -1
  77. package/mops.ts +15 -1
  78. package/package.json +3 -2
  79. package/tests/__snapshots__/build-no-dfx.test.ts.snap +11 -0
  80. package/tests/__snapshots__/build.test.ts.snap +77 -0
  81. package/tests/__snapshots__/check-candid.test.ts.snap +73 -0
  82. package/tests/__snapshots__/check-fix.test.ts.snap +261 -0
  83. package/tests/__snapshots__/check.test.ts.snap +81 -0
  84. package/tests/__snapshots__/lint.test.ts.snap +78 -0
  85. package/tests/build/no-dfx/mops.toml +5 -0
  86. package/tests/build/no-dfx/src/Main.mo +5 -0
  87. package/tests/build-no-dfx.test.ts +10 -0
  88. package/tests/build.test.ts +24 -0
  89. package/tests/check/error/Error.mo +7 -0
  90. package/tests/check/error/mops.toml +2 -0
  91. package/tests/check/fix/M0223.mo +11 -0
  92. package/tests/check/fix/M0236.mo +11 -0
  93. package/tests/check/fix/M0237.mo +11 -0
  94. package/tests/check/fix/Ok.mo +7 -0
  95. package/tests/check/fix/edit-suggestions.mo +143 -0
  96. package/tests/check/fix/mops.toml +5 -0
  97. package/tests/check/fix/overlapping.mo +10 -0
  98. package/tests/check/fix/transitive-lib.mo +9 -0
  99. package/tests/check/fix/transitive-main.mo +9 -0
  100. package/tests/check/moc-args/Warning.mo +5 -0
  101. package/tests/check/moc-args/mops.toml +2 -0
  102. package/tests/check/success/Ok.mo +5 -0
  103. package/tests/check/success/Warning.mo +5 -0
  104. package/tests/check/success/mops.toml +2 -0
  105. package/tests/check-candid.test.ts +22 -0
  106. package/tests/check-fix.test.ts +134 -0
  107. package/tests/check.test.ts +51 -0
  108. package/tests/cli.test.ts +4 -74
  109. package/tests/helpers.ts +58 -0
  110. package/tests/lint/lints/no-bool-switch.toml +9 -0
  111. package/tests/lint/mops.toml +4 -0
  112. package/tests/lint/src/NoBoolSwitch.mo +8 -0
  113. package/tests/lint/src/Ok.mo +5 -0
  114. package/tests/lint.test.ts +17 -0
  115. package/tests/moc-args.test.ts +19 -0
  116. package/tests/toolchain/mock +2 -0
  117. package/tests/toolchain/mops.toml +2 -0
  118. package/tests/toolchain.test.ts +12 -0
  119. package/types.ts +8 -1
  120. package/wasm/Cargo.lock +101 -54
  121. package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  122. package/wasm/pkg/web/wasm_bg.wasm +0 -0
  123. package/.DS_Store +0 -0
  124. package/bundle/bench/bench-canister.mo +0 -121
  125. package/bundle/bench/user-bench.mo +0 -10
  126. package/bundle/bin/moc-wrapper.sh +0 -40
  127. package/bundle/bin/mops.js +0 -3
  128. package/bundle/cli.js +0 -2144
  129. package/bundle/declarations/bench/bench.did +0 -30
  130. package/bundle/declarations/bench/bench.did.d.ts +0 -33
  131. package/bundle/declarations/bench/bench.did.js +0 -30
  132. package/bundle/declarations/bench/index.d.ts +0 -50
  133. package/bundle/declarations/bench/index.js +0 -40
  134. package/bundle/declarations/main/index.d.ts +0 -50
  135. package/bundle/declarations/main/index.js +0 -40
  136. package/bundle/declarations/main/main.did +0 -428
  137. package/bundle/declarations/main/main.did.d.ts +0 -348
  138. package/bundle/declarations/main/main.did.js +0 -406
  139. package/bundle/declarations/storage/index.d.ts +0 -50
  140. package/bundle/declarations/storage/index.js +0 -30
  141. package/bundle/declarations/storage/storage.did +0 -46
  142. package/bundle/declarations/storage/storage.did.d.ts +0 -40
  143. package/bundle/declarations/storage/storage.did.js +0 -38
  144. package/bundle/package.json +0 -36
  145. package/bundle/templates/README.md +0 -13
  146. package/bundle/templates/licenses/Apache-2.0 +0 -202
  147. package/bundle/templates/licenses/Apache-2.0-NOTICE +0 -13
  148. package/bundle/templates/licenses/MIT +0 -21
  149. package/bundle/templates/mops-publish.yml +0 -17
  150. package/bundle/templates/mops-test.yml +0 -24
  151. package/bundle/templates/src/lib.mo +0 -15
  152. package/bundle/templates/test/lib.test.mo +0 -4
  153. package/bundle/wasm_bg.wasm +0 -0
  154. package/bundle/xhr-sync-worker.js +0 -59
  155. package/dist/wasm/pkg/bundler/package.json +0 -20
  156. package/dist/wasm/pkg/bundler/wasm.d.ts +0 -3
  157. package/dist/wasm/pkg/bundler/wasm.js +0 -5
  158. package/dist/wasm/pkg/bundler/wasm_bg.js +0 -93
  159. package/dist/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  160. package/dist/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
  161. package/tests/__snapshots__/cli.test.ts.snap +0 -202
  162. package/tests/build/success/.dfx/local/canister_ids.json +0 -17
  163. package/tests/build/success/.dfx/local/canisters/bar/bar.did +0 -3
  164. package/tests/build/success/.dfx/local/canisters/bar/bar.most +0 -4
  165. package/tests/build/success/.dfx/local/canisters/bar/bar.wasm +0 -0
  166. package/tests/build/success/.dfx/local/canisters/bar/constructor.did +0 -3
  167. package/tests/build/success/.dfx/local/canisters/bar/index.js +0 -42
  168. package/tests/build/success/.dfx/local/canisters/bar/init_args.txt +0 -1
  169. package/tests/build/success/.dfx/local/canisters/bar/service.did +0 -3
  170. package/tests/build/success/.dfx/local/canisters/bar/service.did.d.ts +0 -7
  171. package/tests/build/success/.dfx/local/canisters/bar/service.did.js +0 -4
  172. package/tests/build/success/.dfx/local/canisters/foo/constructor.did +0 -3
  173. package/tests/build/success/.dfx/local/canisters/foo/foo.did +0 -3
  174. package/tests/build/success/.dfx/local/canisters/foo/foo.most +0 -4
  175. package/tests/build/success/.dfx/local/canisters/foo/foo.wasm +0 -0
  176. package/tests/build/success/.dfx/local/canisters/foo/index.js +0 -42
  177. package/tests/build/success/.dfx/local/canisters/foo/init_args.txt +0 -1
  178. package/tests/build/success/.dfx/local/canisters/foo/service.did +0 -3
  179. package/tests/build/success/.dfx/local/canisters/foo/service.did.d.ts +0 -7
  180. package/tests/build/success/.dfx/local/canisters/foo/service.did.js +0 -4
  181. package/tests/build/success/.dfx/local/lsp/ucwa4-rx777-77774-qaada-cai.did +0 -3
  182. package/tests/build/success/.dfx/local/lsp/ulvla-h7777-77774-qaacq-cai.did +0 -3
  183. package/tests/build/success/.dfx/local/network-id +0 -4
  184. package/wasm/pkg/bundler/package.json +0 -20
  185. package/wasm/pkg/bundler/wasm.d.ts +0 -3
  186. package/wasm/pkg/bundler/wasm.js +0 -5
  187. package/wasm/pkg/bundler/wasm_bg.js +0 -93
  188. package/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  189. package/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
package/mops.ts CHANGED
@@ -8,11 +8,13 @@ import prompts from "prompts";
8
8
  import fetch from "node-fetch";
9
9
 
10
10
  import { decodeFile } from "./pem.js";
11
+ import { cliError } from "./error.js";
11
12
  import { Config, Dependency } from "./types.js";
12
13
  import { mainActor, storageActor } from "./api/actors.js";
13
14
  import { getNetwork } from "./api/network.js";
14
15
  import { getHighestVersion } from "./api/getHighestVersion.js";
15
16
  import { getPackageId } from "./helpers/get-package-id.js";
17
+ import { FILE_PATH_REGEX } from "./constants.js";
16
18
 
17
19
  if (!globalThis.fetch) {
18
20
  globalThis.fetch = fetch as any;
@@ -157,7 +159,7 @@ export function getDependencyType(version: string) {
157
159
  }
158
160
  if (version.startsWith("https://github.com/")) {
159
161
  return "github";
160
- } else if (version.match(/^(\.?\.)?\//)) {
162
+ } else if (version.match(FILE_PATH_REGEX)) {
161
163
  return "local";
162
164
  } else {
163
165
  return "mops";
@@ -203,6 +205,18 @@ export function readConfig(configFile = getClosestConfigFile()): Config {
203
205
  return config;
204
206
  }
205
207
 
208
+ export function getGlobalMocArgs(config: Config): string[] {
209
+ if (!config.moc?.args) {
210
+ return [];
211
+ }
212
+ if (typeof config.moc.args === "string") {
213
+ cliError(
214
+ `[moc] config 'args' should be an array of strings in mops.toml config file`,
215
+ );
216
+ }
217
+ return config.moc.args;
218
+ }
219
+
206
220
  export function writeConfig(
207
221
  config: Config,
208
222
  configFile = getClosestConfigFile(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ic-mops",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mops": "dist/bin/mops.js",
@@ -92,7 +92,8 @@
92
92
  "stream-to-promise": "3.0.0",
93
93
  "string-width": "7.2.0",
94
94
  "tar": "7.5.6",
95
- "terminal-size": "4.0.0"
95
+ "terminal-size": "4.0.0",
96
+ "vscode-languageserver-textdocument": "1.0.12"
96
97
  },
97
98
  "devDependencies": {
98
99
  "@tsconfig/strictest": "2.0.5",
@@ -0,0 +1,11 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`build without dfx builds using mops toolchain moc 1`] = `
4
+ {
5
+ "exitCode": 0,
6
+ "stderr": "",
7
+ "stdout": "build canister main
8
+
9
+ ✓ Built 1 canister successfully",
10
+ }
11
+ `;
@@ -0,0 +1,77 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`build error 1`] = `
4
+ {
5
+ "exitCode": 0,
6
+ "stderr": "",
7
+ "stdout": "build canister foo
8
+ moc-wrapper ["-c","--idl","-o",".mops/.build/foo.wasm","src/Foo.mo","--package","core",".mops/core@1.0.0/src","--release","--public-metadata","candid:service","--public-metadata","candid:args"]
9
+ Adding metadata to .mops/.build/foo.wasm
10
+
11
+ ✓ Built 1 canister successfully",
12
+ }
13
+ `;
14
+
15
+ exports[`build error 2`] = `
16
+ {
17
+ "exitCode": 1,
18
+ "stderr": "Candid compatibility check failed for canister bar",
19
+ "stdout": "build canister bar",
20
+ }
21
+ `;
22
+
23
+ exports[`build error 3`] = `
24
+ {
25
+ "exitCode": 1,
26
+ "stderr": "Candid compatibility check failed for canister bar",
27
+ "stdout": "build canister foo
28
+ build canister bar",
29
+ }
30
+ `;
31
+
32
+ exports[`build ok 1`] = `
33
+ {
34
+ "exitCode": 0,
35
+ "stderr": "",
36
+ "stdout": "build canister foo
37
+ moc-wrapper ["-c","--idl","-o",".mops/.build/foo.wasm","src/Foo.mo","--package","core",".mops/core@1.0.0/src","--release","--public-metadata","candid:service","--public-metadata","candid:args"]
38
+ Adding metadata to .mops/.build/foo.wasm
39
+ build canister bar
40
+ moc-wrapper ["-c","--idl","-o",".mops/.build/bar.wasm","src/Bar.mo","--package","core",".mops/core@1.0.0/src","--release","--incremental-gc","--public-metadata","candid:service","--public-metadata","candid:args"]
41
+ Candid compatibility check passed for canister bar
42
+ Adding metadata to .mops/.build/bar.wasm
43
+
44
+ ✓ Built 2 canisters successfully",
45
+ }
46
+ `;
47
+
48
+ exports[`build ok 2`] = `
49
+ {
50
+ "exitCode": 0,
51
+ "stderr": "",
52
+ "stdout": "build canister foo
53
+
54
+ ✓ Built 1 canister successfully",
55
+ }
56
+ `;
57
+
58
+ exports[`build ok 3`] = `
59
+ {
60
+ "exitCode": 0,
61
+ "stderr": "",
62
+ "stdout": "build canister bar
63
+
64
+ ✓ Built 1 canister successfully",
65
+ }
66
+ `;
67
+
68
+ exports[`build ok 4`] = `
69
+ {
70
+ "exitCode": 0,
71
+ "stderr": "",
72
+ "stdout": "build canister foo
73
+ build canister bar
74
+
75
+ ✓ Built 2 canisters successfully",
76
+ }
77
+ `;
@@ -0,0 +1,73 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`check-candid error 1`] = `
4
+ {
5
+ "exitCode": 1,
6
+ "stderr": "✖ Candid compatibility check failed",
7
+ "stdout": "",
8
+ }
9
+ `;
10
+
11
+ exports[`check-candid error 2`] = `
12
+ {
13
+ "exitCode": 1,
14
+ "stderr": "✖ Candid compatibility check failed",
15
+ "stdout": "",
16
+ }
17
+ `;
18
+
19
+ exports[`check-candid error 3`] = `
20
+ {
21
+ "exitCode": 1,
22
+ "stderr": "✖ Candid compatibility check failed",
23
+ "stdout": "",
24
+ }
25
+ `;
26
+
27
+ exports[`check-candid error 4`] = `
28
+ {
29
+ "exitCode": 1,
30
+ "stderr": "✖ Candid compatibility check failed",
31
+ "stdout": "",
32
+ }
33
+ `;
34
+
35
+ exports[`check-candid ok 1`] = `
36
+ {
37
+ "exitCode": 0,
38
+ "stderr": "",
39
+ "stdout": "✓ Candid compatibility check passed",
40
+ }
41
+ `;
42
+
43
+ exports[`check-candid ok 2`] = `
44
+ {
45
+ "exitCode": 0,
46
+ "stderr": "",
47
+ "stdout": "✓ Candid compatibility check passed",
48
+ }
49
+ `;
50
+
51
+ exports[`check-candid ok 3`] = `
52
+ {
53
+ "exitCode": 0,
54
+ "stderr": "",
55
+ "stdout": "✓ Candid compatibility check passed",
56
+ }
57
+ `;
58
+
59
+ exports[`check-candid ok 4`] = `
60
+ {
61
+ "exitCode": 0,
62
+ "stderr": "",
63
+ "stdout": "✓ Candid compatibility check passed",
64
+ }
65
+ `;
66
+
67
+ exports[`check-candid ok 5`] = `
68
+ {
69
+ "exitCode": 0,
70
+ "stderr": "",
71
+ "stdout": "✓ Candid compatibility check passed",
72
+ }
73
+ `;
@@ -0,0 +1,261 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`check --fix M0223 1`] = `
4
+ "// M0223: Redundant type instantiation
5
+ // The type annotation is not needed when it can be inferred
6
+
7
+ persistent actor {
8
+ public func testM0223() : async () {
9
+ func identity<T>(x : T) : T = x;
10
+ let varArray : [var Nat] = [var 1];
11
+ let nat = identity(1);
12
+ varArray[0] := nat;
13
+ };
14
+ };
15
+ "
16
+ `;
17
+
18
+ exports[`check --fix M0223: fix output 1`] = `
19
+ "Fixed run/M0223.mo (1 fix: M0223)
20
+
21
+ ✓ 1 fix applied to 1 file"
22
+ `;
23
+
24
+ exports[`check --fix M0236 1`] = `
25
+ "// M0236: Suggested to use dot notation
26
+ // Function calls can be rewritten using dot notation
27
+ import List "mo:core/List";
28
+ import Nat "mo:core/Nat";
29
+
30
+ persistent actor {
31
+ public func testM0236() : async () {
32
+ let list = List.fromArray<Nat>([1, 2, 3]);
33
+ list.sortInPlace();
34
+ };
35
+ };
36
+ "
37
+ `;
38
+
39
+ exports[`check --fix M0236: fix output 1`] = `
40
+ "Fixed run/M0236.mo (1 fix: M0236)
41
+
42
+ ✓ 1 fix applied to 1 file"
43
+ `;
44
+
45
+ exports[`check --fix M0237 1`] = `
46
+ "// M0237: Redundant explicit implicit argument
47
+ // Some arguments can be inferred and don't need to be specified
48
+ import List "mo:core/List";
49
+ import Nat "mo:core/Nat";
50
+
51
+ persistent actor {
52
+ public func testM0237() : async () {
53
+ let list = List.fromArray<Nat>([3, 2, 1]);
54
+ list.sortInPlace();
55
+ };
56
+ };
57
+ "
58
+ `;
59
+
60
+ exports[`check --fix M0237: fix output 1`] = `
61
+ "Fixed run/M0237.mo (1 fix: M0237)
62
+
63
+ ✓ 1 fix applied to 1 file"
64
+ `;
65
+
66
+ exports[`check --fix edit-suggestions 1`] = `
67
+ "import Map "mo:core/Map";
68
+ import Nat "mo:core/Nat";
69
+ import Text "mo:core/Text";
70
+ import { type Order } "mo:core/Order";
71
+
72
+ // --- M0223: redundant type instantiation ---
73
+
74
+ do {
75
+ func inferred<T>(x : T) : T = x;
76
+ let n1 = inferred(1);
77
+ ignore n1;
78
+ };
79
+
80
+ // --- M0236: contextual dot notation ---
81
+
82
+ do {
83
+ let m = Map.empty<Nat, Text>();
84
+ // single arg
85
+ ignore m.size(); // warn M0236
86
+
87
+ // multi arg with implicit -> M0236 + M0237
88
+ ignore m.get(1); // warn M0236 + M0237
89
+
90
+ // complex receiver
91
+ ignore Map.empty<Nat, Text>().size(
92
+
93
+ ); // warn M0236
94
+
95
+ // multiline call -> M0236 + M0237
96
+ m.add(
97
+ 1,
98
+ "John",
99
+ ); // warn M0236 + M0237
100
+ };
101
+
102
+ // --- M0237: implicit argument removal ---
103
+
104
+ do {
105
+ let m = Map.empty<Nat, Text>();
106
+
107
+ // single line
108
+ ignore m.get(1); // warn M0237
109
+
110
+ // multiline
111
+ ignore m.get(
112
+ 1,
113
+ ); // warn M0237
114
+ };
115
+
116
+ // --- M0237: complex implicit patterns ---
117
+
118
+ module Impl {
119
+ // implicit in the middle: f(self, implicit, key)
120
+ public func get<K, V>(
121
+ self : [(K, V)],
122
+ _cmp : (implicit : (compare : (K, K) -> Order)),
123
+ key : K,
124
+ ) : ?V { ignore self; ignore key; null };
125
+
126
+ // two adjacent implicits: f(self, implicit1, implicit2, key, value)
127
+ public func put<K, V>(
128
+ self : [(K, V)],
129
+ _cmpK : (implicit : (compare : (K, K) -> Order)),
130
+ _cmpV : (implicit : (compare : (V, V) -> Order)),
131
+ key : K,
132
+ value : V,
133
+ ) : [(K, V)] { ignore key; ignore value; self };
134
+
135
+ // implicit at the end
136
+ public func find<K, V>(
137
+ self : [(K, V)],
138
+ key : K,
139
+ _cmp : (implicit : (compare : (K, K) -> Order)),
140
+ ) : ?V { ignore self; ignore key; null };
141
+ public func sort1<K, V>(
142
+ self : [(K, V)],
143
+ _cmp : (implicit : (compare : (K, K) -> Order)),
144
+ ) : [(K, V)] { self };
145
+ public func sort2<K, V>(
146
+ notSelf : [(K, V)],
147
+ _cmp : (implicit : (compare : (K, K) -> Order)),
148
+ ) : [(K, V)] { notSelf };
149
+
150
+ // all implicits: f(implicit1, implicit2)
151
+ public func make<K, V>(
152
+ _cmpK : (implicit : (compare : (K, K) -> Order)),
153
+ _cmpV : (implicit : (compare : (V, V) -> Order)),
154
+ ) : [(K, V)] { [] };
155
+
156
+ // non-adjacent implicits: f(self, implicit1, key, implicit2, value)
157
+ public func update<K, V>(
158
+ self : [(K, V)],
159
+ _cmpK : (implicit : (compare : (K, K) -> Order)),
160
+ key : K,
161
+ _cmpV : (implicit : (compare : (V, V) -> Order)),
162
+ value : V,
163
+ ) : [(K, V)] { ignore key; ignore value; self };
164
+ };
165
+
166
+ do {
167
+ let data : [(Nat, Text)] = [];
168
+
169
+ // implicit in the middle -> M0236 + M0237
170
+ ignore data.get(1);
171
+
172
+ // two adjacent implicits -> M0236 + M0237 x2
173
+ ignore data.put(1, "a");
174
+
175
+ // implicit at the end -> M0236 + M0237
176
+ ignore data.find(1, );
177
+ ignore data.sort1(); // -> M0236 + M0237
178
+ ignore Impl.sort2(data, ); // no dot suggestion (notSelf), M0237 only
179
+
180
+ // all implicits -> M0237 x2
181
+ let _ = Impl.make<Nat, Text>();
182
+
183
+ // non-adjacent implicits -> M0236 + M0237 x2
184
+ ignore data.update(1, "a");
185
+
186
+ // multiline: two adjacent implicits -> M0236 + M0237 x2
187
+ ignore data.put(
188
+ 1,
189
+ "a",
190
+ );
191
+ };
192
+
193
+ // --- Mix: M0223 + M0236 + M0237 ---
194
+
195
+ do {
196
+ // NB: Must use \`let _ = ...\` to get the 'redundant type instantiation' error
197
+ let _ = Map.empty<Nat, Text>().insert(
198
+ 1,
199
+ "John",
200
+ ); // warn M0223 + M0236 + M0237
201
+ };
202
+ "
203
+ `;
204
+
205
+ exports[`check --fix edit-suggestions: fix output 1`] = `
206
+ "Fixed run/edit-suggestions.mo (30 fixes: M0223, M0236, M0237)
207
+
208
+ ✓ 30 fixes applied to 1 file"
209
+ `;
210
+
211
+ exports[`check --fix overlapping edits 1`] = `
212
+ "import Array "mo:core/Array";
213
+
214
+ // Overlapping fixable errors (nested calls produce overlapping M0223 + M0236 edits)
215
+ do {
216
+ let ar = [1, 2, 3];
217
+ let _ = ar.filter(func(x) { x > 0 }).filter(
218
+ func(x) { x > 0 },
219
+ );
220
+ };
221
+ "
222
+ `;
223
+
224
+ exports[`check --fix overlapping edits: fix output 1`] = `
225
+ "Fixed run/overlapping.mo (4 fixes: M0223, M0236)
226
+
227
+ ✓ 4 fixes applied to 1 file"
228
+ `;
229
+
230
+ exports[`check --fix transitive imports: fix output 1`] = `
231
+ "Fixed run/transitive-lib.mo (1 fix: M0236)
232
+ Fixed run/transitive-main.mo (1 fix: M0223)
233
+
234
+ ✓ 2 fixes applied to 2 files"
235
+ `;
236
+
237
+ exports[`check --fix transitive imports: lib file 1`] = `
238
+ "import List "mo:core/List";
239
+ import Nat "mo:core/Nat";
240
+
241
+ module {
242
+ public func test() {
243
+ let list = List.fromArray<Nat>([3, 2, 1]);
244
+ list.sortInPlace();
245
+ };
246
+ };
247
+ "
248
+ `;
249
+
250
+ exports[`check --fix transitive imports: main file 1`] = `
251
+ "import Lib "./transitive-lib";
252
+
253
+ persistent actor {
254
+ public func run() : async () {
255
+ func identity<T>(x : T) : T = x;
256
+ let _ = identity(1);
257
+ Lib.test();
258
+ };
259
+ };
260
+ "
261
+ `;
@@ -0,0 +1,81 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`check [moc] args are passed to moc 1`] = `
4
+ {
5
+ "exitCode": 1,
6
+ "stderr": "Warning.mo:3.9-3.15: warning [M0194], unused identifier unused (delete or rename to wildcard \`_\` or \`_unused\`)
7
+ ✗ Check failed for file Warning.mo (exit code: 1)",
8
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing",
9
+ }
10
+ `;
11
+
12
+ exports[`check error 1`] = `
13
+ {
14
+ "exitCode": 1,
15
+ "stderr": "Error.mo:1.1-5.2: type error [M0096], expression of type
16
+ actor {hello : shared () -> async Text}
17
+ cannot produce expected type
18
+ ()
19
+ Error.mo:7.1-7.21: type error [M0057], unbound variable thisshouldnotcompile
20
+ ✗ Check failed for file Error.mo (exit code: 1)",
21
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing",
22
+ }
23
+ `;
24
+
25
+ exports[`check error 2`] = `
26
+ {
27
+ "exitCode": 1,
28
+ "stderr": "Ok.mo: No such file or directory
29
+ ✗ Check failed for file Ok.mo (exit code: 1)",
30
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing",
31
+ }
32
+ `;
33
+
34
+ exports[`check ok 1`] = `
35
+ {
36
+ "exitCode": 0,
37
+ "stderr": "",
38
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing
39
+ ✓ Ok.mo",
40
+ }
41
+ `;
42
+
43
+ exports[`check ok 2`] = `
44
+ {
45
+ "exitCode": 0,
46
+ "stderr": "",
47
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing
48
+ check Running moc:
49
+ moc-wrapper ["Ok.mo","--check","--package","core",".mops/core@2.0.0/src"]
50
+ ✓ Ok.mo",
51
+ }
52
+ `;
53
+
54
+ exports[`check warning 1`] = `
55
+ {
56
+ "exitCode": 0,
57
+ "stderr": "Warning.mo:3.9-3.15: warning [M0194], unused identifier unused (delete or rename to wildcard \`_\` or \`_unused\`)",
58
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing
59
+ ✓ Warning.mo",
60
+ }
61
+ `;
62
+
63
+ exports[`check warning verbose 1`] = `
64
+ {
65
+ "exitCode": 0,
66
+ "stderr": "Warning.mo:3.9-3.15: warning [M0194], unused identifier unused (delete or rename to wildcard \`_\` or \`_unused\`)",
67
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing
68
+ check Running moc:
69
+ moc-wrapper ["Warning.mo","--check","--package","core",".mops/core@2.0.0/src"]
70
+ ✓ Warning.mo",
71
+ }
72
+ `;
73
+
74
+ exports[`check warning with -Werror flag 1`] = `
75
+ {
76
+ "exitCode": 1,
77
+ "stderr": "Warning.mo:3.9-3.15: warning [M0194], unused identifier unused (delete or rename to wildcard \`_\` or \`_unused\`)
78
+ ✗ Check failed for file Warning.mo (exit code: 1)",
79
+ "stdout": "moc < 1.3.0: some diagnostic hints may be missing",
80
+ }
81
+ `;
@@ -0,0 +1,78 @@
1
+ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2
+
3
+ exports[`lint error 1`] = `
4
+ {
5
+ "exitCode": 1,
6
+ "stderr": " × [ERROR]: no-bool-switch
7
+ ╭─[<TEST_DIR>/lint/src/NoBoolSwitch.mo:3:5]
8
+ 2 │ public func boolSwitch(b : Bool) : Bool {
9
+ 3 │ ╭─▶ switch (b) {
10
+ 4 │ │ case false { false };
11
+ 5 │ │ case true { true };
12
+ 6 │ ├─▶ };
13
+ · ╰──── Don't switch on boolean values, use if instead
14
+ 7 │ };
15
+ ╰────
16
+
17
+ Error: Found 1 errors
18
+ Lint failed with exit code 1",
19
+ "stdout": "lint Running lintoko:
20
+ <CACHE>/lintoko/0.7.0/lintoko
21
+ ["--verbose","--rules","lints","<TEST_DIR>/lint/src/Ok.mo","<TEST_DIR>/lint/src/NoBoolSwitch.mo"]
22
+ DEBUG file input: <TEST_DIR>/lint/src/Ok.mo
23
+ DEBUG file input: <TEST_DIR>/lint/src/NoBoolSwitch.mo
24
+ DEBUG Loading rules from: lints
25
+ DEBUG Parsing extra rule at: lints/no-bool-switch.toml
26
+ DEBUG Linting file: <TEST_DIR>/lint/src/NoBoolSwitch.mo
27
+ DEBUG Linting file: <TEST_DIR>/lint/src/Ok.mo",
28
+ }
29
+ `;
30
+
31
+ exports[`lint error 2`] = `
32
+ {
33
+ "exitCode": 1,
34
+ "stderr": " × [ERROR]: no-bool-switch
35
+ ╭─[<TEST_DIR>/lint/src/NoBoolSwitch.mo:3:5]
36
+ 2 │ public func boolSwitch(b : Bool) : Bool {
37
+ 3 │ ╭─▶ switch (b) {
38
+ 4 │ │ case false { false };
39
+ 5 │ │ case true { true };
40
+ 6 │ ├─▶ };
41
+ · ╰──── Don't switch on boolean values, use if instead
42
+ 7 │ };
43
+ ╰────
44
+
45
+ Error: Found 1 errors
46
+ Lint failed with exit code 1",
47
+ "stdout": "lint Running lintoko:
48
+ <CACHE>/lintoko/0.7.0/lintoko
49
+ ["--verbose","--rules","lints","<TEST_DIR>/lint/src/NoBoolSwitch.mo"]
50
+ DEBUG file input: <TEST_DIR>/lint/src/NoBoolSwitch.mo
51
+ DEBUG Loading rules from: lints
52
+ DEBUG Parsing extra rule at: lints/no-bool-switch.toml
53
+ DEBUG Linting file: <TEST_DIR>/lint/src/NoBoolSwitch.mo",
54
+ }
55
+ `;
56
+
57
+ exports[`lint error 3`] = `
58
+ {
59
+ "exitCode": 1,
60
+ "stderr": "No files found for filter 'DoesNotExist'",
61
+ "stdout": "",
62
+ }
63
+ `;
64
+
65
+ exports[`lint ok 1`] = `
66
+ {
67
+ "exitCode": 0,
68
+ "stderr": "",
69
+ "stdout": "lint Running lintoko:
70
+ <CACHE>/lintoko/0.7.0/lintoko
71
+ ["--verbose","--rules","lints","<TEST_DIR>/lint/src/Ok.mo"]
72
+ DEBUG file input: <TEST_DIR>/lint/src/Ok.mo
73
+ DEBUG Loading rules from: lints
74
+ DEBUG Parsing extra rule at: lints/no-bool-switch.toml
75
+ DEBUG Linting file: <TEST_DIR>/lint/src/Ok.mo
76
+ ✓ Lint succeeded",
77
+ }
78
+ `;
@@ -0,0 +1,5 @@
1
+ [toolchain]
2
+ moc = "1.3.0"
3
+
4
+ [canisters.main]
5
+ main = "src/Main.mo"
@@ -0,0 +1,5 @@
1
+ persistent actor {
2
+ public func greet(name : Text) : async Text {
3
+ "Hello, " # name # "!";
4
+ };
5
+ };
@@ -0,0 +1,10 @@
1
+ import { describe, test } from "@jest/globals";
2
+ import path from "path";
3
+ import { cliSnapshot } from "./helpers";
4
+
5
+ describe("build without dfx", () => {
6
+ test("builds using mops toolchain moc", async () => {
7
+ const cwd = path.join(import.meta.dirname, "build/no-dfx");
8
+ await cliSnapshot(["build"], { cwd }, 0);
9
+ }, 120_000);
10
+ });
@@ -0,0 +1,24 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import path from "path";
3
+ import { cliSnapshot } from "./helpers";
4
+
5
+ describe("build", () => {
6
+ test("ok", async () => {
7
+ const cwd = path.join(import.meta.dirname, "build/success");
8
+ await cliSnapshot(["build", "--verbose"], { cwd }, 0);
9
+ await cliSnapshot(["build", "foo"], { cwd }, 0);
10
+ await cliSnapshot(["build", "bar"], { cwd }, 0);
11
+ await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
12
+ });
13
+
14
+ test("error", async () => {
15
+ const cwd = path.join(import.meta.dirname, "build/error");
16
+ await cliSnapshot(["build", "foo", "--verbose"], { cwd }, 0);
17
+ expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch(
18
+ "Candid compatibility check failed for canister bar",
19
+ );
20
+ expect(
21
+ (await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr,
22
+ ).toMatch("Candid compatibility check failed for canister bar");
23
+ });
24
+ });