ic-mops 2.0.0 → 2.1.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/CHANGELOG.md +13 -0
- package/RELEASE.md +179 -0
- package/bundle/cli.tgz +0 -0
- package/check-requirements.ts +3 -8
- package/cli.ts +79 -11
- package/commands/bench/bench-canister.mo +17 -6
- package/commands/bench.ts +2 -13
- package/commands/build.ts +42 -17
- package/commands/check.ts +117 -0
- package/commands/format.ts +3 -18
- package/commands/lint.ts +92 -0
- package/commands/sync.ts +2 -8
- package/commands/test/test.ts +7 -19
- package/commands/toolchain/index.ts +21 -8
- package/commands/toolchain/lintoko.ts +54 -0
- package/commands/toolchain/toolchain-utils.ts +2 -0
- package/constants.ts +23 -0
- package/dist/check-requirements.js +3 -8
- package/dist/cli.js +60 -10
- package/dist/commands/bench/bench-canister.mo +17 -6
- package/dist/commands/bench.js +2 -11
- package/dist/commands/build.js +38 -16
- package/dist/commands/check.d.ts +6 -0
- package/dist/commands/check.js +78 -0
- package/dist/commands/format.js +3 -16
- package/dist/commands/lint.d.ts +7 -0
- package/dist/commands/lint.js +69 -0
- package/dist/commands/sync.js +2 -7
- package/dist/commands/test/test.js +7 -17
- package/dist/commands/toolchain/index.d.ts +2 -2
- package/dist/commands/toolchain/index.js +18 -7
- package/dist/commands/toolchain/lintoko.d.ts +8 -0
- package/dist/commands/toolchain/lintoko.js +36 -0
- package/dist/commands/toolchain/toolchain-utils.d.ts +1 -0
- package/dist/commands/toolchain/toolchain-utils.js +1 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.js +21 -0
- package/dist/environments/nodejs/cli.js +6 -1
- package/dist/helpers/autofix-motoko.d.ts +26 -0
- package/dist/helpers/autofix-motoko.js +105 -0
- package/dist/helpers/get-moc-version.d.ts +2 -0
- package/dist/helpers/get-moc-version.js +10 -1
- package/dist/mops.js +2 -1
- package/dist/package.json +4 -3
- package/dist/tests/build-no-dfx.test.d.ts +1 -0
- package/dist/tests/build-no-dfx.test.js +9 -0
- package/dist/tests/build.test.d.ts +1 -0
- package/dist/tests/build.test.js +18 -0
- package/dist/tests/check-candid.test.d.ts +1 -0
- package/dist/tests/check-candid.test.js +20 -0
- package/dist/tests/check-fix.test.d.ts +1 -0
- package/dist/tests/check-fix.test.js +73 -0
- package/dist/tests/check.test.d.ts +1 -0
- package/dist/tests/check.test.js +33 -0
- package/dist/tests/cli.test.js +4 -57
- package/dist/tests/helpers.d.ts +22 -0
- package/dist/tests/helpers.js +43 -0
- package/dist/tests/lint.test.d.ts +1 -0
- package/dist/tests/lint.test.js +15 -0
- package/dist/tests/toolchain.test.d.ts +1 -0
- package/dist/tests/toolchain.test.js +11 -0
- package/dist/types.d.ts +6 -1
- package/dist/wasm/pkg/nodejs/wasm.d.ts +3 -0
- package/dist/wasm/pkg/nodejs/wasm.js +323 -17
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +6 -1
- package/dist/wasm/pkg/web/wasm.d.ts +10 -1
- package/dist/wasm/pkg/web/wasm.js +300 -21
- package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +6 -1
- package/dist/wasm.d.ts +6 -1
- package/environments/nodejs/cli.ts +7 -1
- package/helpers/autofix-motoko.ts +170 -0
- package/helpers/get-moc-version.ts +12 -1
- package/mops.ts +2 -1
- package/package.json +4 -3
- package/tests/__snapshots__/build-no-dfx.test.ts.snap +11 -0
- package/tests/__snapshots__/build.test.ts.snap +77 -0
- package/tests/__snapshots__/check-candid.test.ts.snap +73 -0
- package/tests/__snapshots__/check-fix.test.ts.snap +242 -0
- package/tests/__snapshots__/check.test.ts.snap +72 -0
- package/tests/__snapshots__/lint.test.ts.snap +78 -0
- package/tests/build/error/src/Bar.mo +2 -2
- package/tests/build/no-dfx/mops.toml +5 -0
- package/tests/build/no-dfx/src/Main.mo +5 -0
- package/tests/build/success/candid/bar.did +1 -0
- package/tests/build/success/mops.toml +8 -3
- package/tests/build-no-dfx.test.ts +10 -0
- package/tests/build.test.ts +24 -0
- package/tests/check/error/Error.mo +7 -0
- package/tests/check/error/mops.toml +2 -0
- package/tests/check/fix/M0223.mo +11 -0
- package/tests/check/fix/M0236.mo +11 -0
- package/tests/check/fix/M0237.mo +11 -0
- package/tests/check/fix/Ok.mo +7 -0
- package/tests/check/fix/edit-suggestions.mo +143 -0
- package/tests/check/fix/mops.toml +5 -0
- package/tests/check/fix/transitive-lib.mo +9 -0
- package/tests/check/fix/transitive-main.mo +9 -0
- package/tests/check/success/Ok.mo +5 -0
- package/tests/check/success/Warning.mo +5 -0
- package/tests/check/success/mops.toml +2 -0
- package/tests/check-candid.test.ts +22 -0
- package/tests/check-fix.test.ts +111 -0
- package/tests/check.test.ts +46 -0
- package/tests/cli.test.ts +4 -74
- package/tests/helpers.ts +58 -0
- package/tests/lint/lints/no-bool-switch.toml +9 -0
- package/tests/lint/mops.toml +4 -0
- package/tests/lint/src/NoBoolSwitch.mo +8 -0
- package/tests/lint/src/Ok.mo +5 -0
- package/tests/lint.test.ts +17 -0
- package/tests/toolchain/mock +2 -0
- package/tests/toolchain/mops.toml +2 -0
- package/tests/toolchain.test.ts +12 -0
- package/types.ts +6 -1
- package/wasm/Cargo.lock +101 -54
- package/wasm/Cargo.toml +2 -5
- package/wasm/pkg/nodejs/wasm.d.ts +3 -0
- package/wasm/pkg/nodejs/wasm.js +323 -17
- package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
- package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +6 -1
- package/wasm/pkg/web/wasm.d.ts +10 -1
- package/wasm/pkg/web/wasm.js +300 -21
- package/wasm/pkg/web/wasm_bg.wasm +0 -0
- package/wasm/pkg/web/wasm_bg.wasm.d.ts +6 -1
- package/wasm/src/lib.rs +10 -5
- package/wasm/src/utils.rs +15 -0
- package/wasm/src/wasm_utils.rs +79 -0
- package/wasm.ts +10 -1
- package/.DS_Store +0 -0
- package/bundle/bench/bench-canister.mo +0 -121
- package/bundle/bench/user-bench.mo +0 -10
- package/bundle/bin/moc-wrapper.sh +0 -40
- package/bundle/bin/mops.js +0 -3
- package/bundle/cli.js +0 -2144
- package/bundle/declarations/bench/bench.did +0 -30
- package/bundle/declarations/bench/bench.did.d.ts +0 -33
- package/bundle/declarations/bench/bench.did.js +0 -30
- package/bundle/declarations/bench/index.d.ts +0 -50
- package/bundle/declarations/bench/index.js +0 -40
- package/bundle/declarations/main/index.d.ts +0 -50
- package/bundle/declarations/main/index.js +0 -40
- package/bundle/declarations/main/main.did +0 -428
- package/bundle/declarations/main/main.did.d.ts +0 -348
- package/bundle/declarations/main/main.did.js +0 -406
- package/bundle/declarations/storage/index.d.ts +0 -50
- package/bundle/declarations/storage/index.js +0 -30
- package/bundle/declarations/storage/storage.did +0 -46
- package/bundle/declarations/storage/storage.did.d.ts +0 -40
- package/bundle/declarations/storage/storage.did.js +0 -38
- package/bundle/package.json +0 -36
- package/bundle/templates/README.md +0 -13
- package/bundle/templates/licenses/Apache-2.0 +0 -202
- package/bundle/templates/licenses/Apache-2.0-NOTICE +0 -13
- package/bundle/templates/licenses/MIT +0 -21
- package/bundle/templates/mops-publish.yml +0 -17
- package/bundle/templates/mops-test.yml +0 -24
- package/bundle/templates/src/lib.mo +0 -15
- package/bundle/templates/test/lib.test.mo +0 -4
- package/bundle/wasm_bg.wasm +0 -0
- package/bundle/xhr-sync-worker.js +0 -59
- package/dist/wasm/pkg/bundler/package.json +0 -20
- package/dist/wasm/pkg/bundler/wasm.d.ts +0 -3
- package/dist/wasm/pkg/bundler/wasm.js +0 -5
- package/dist/wasm/pkg/bundler/wasm_bg.js +0 -93
- package/dist/wasm/pkg/bundler/wasm_bg.wasm +0 -0
- package/dist/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
- package/tests/__snapshots__/cli.test.ts.snap +0 -202
- package/tests/build/success/.dfx/local/canister_ids.json +0 -17
- package/tests/build/success/.dfx/local/canisters/bar/bar.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/bar.most +0 -4
- package/tests/build/success/.dfx/local/canisters/bar/bar.wasm +0 -0
- package/tests/build/success/.dfx/local/canisters/bar/constructor.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/index.js +0 -42
- package/tests/build/success/.dfx/local/canisters/bar/init_args.txt +0 -1
- package/tests/build/success/.dfx/local/canisters/bar/service.did +0 -3
- package/tests/build/success/.dfx/local/canisters/bar/service.did.d.ts +0 -7
- package/tests/build/success/.dfx/local/canisters/bar/service.did.js +0 -4
- package/tests/build/success/.dfx/local/canisters/foo/constructor.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/foo.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/foo.most +0 -4
- package/tests/build/success/.dfx/local/canisters/foo/foo.wasm +0 -0
- package/tests/build/success/.dfx/local/canisters/foo/index.js +0 -42
- package/tests/build/success/.dfx/local/canisters/foo/init_args.txt +0 -1
- package/tests/build/success/.dfx/local/canisters/foo/service.did +0 -3
- package/tests/build/success/.dfx/local/canisters/foo/service.did.d.ts +0 -7
- package/tests/build/success/.dfx/local/canisters/foo/service.did.js +0 -4
- package/tests/build/success/.dfx/local/lsp/ucwa4-rx777-77774-qaada-cai.did +0 -3
- package/tests/build/success/.dfx/local/lsp/ulvla-h7777-77774-qaacq-cai.did +0 -3
- package/tests/build/success/.dfx/local/network-id +0 -4
- package/wasm/pkg/bundler/package.json +0 -20
- package/wasm/pkg/bundler/wasm.d.ts +0 -3
- package/wasm/pkg/bundler/wasm.js +0 -5
- package/wasm/pkg/bundler/wasm_bg.js +0 -93
- package/wasm/pkg/bundler/wasm_bg.wasm +0 -0
- package/wasm/pkg/bundler/wasm_bg.wasm.d.ts +0 -8
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common ignore patterns for glob operations across Motoko files.
|
|
3
|
+
*/
|
|
4
|
+
export const MOTOKO_IGNORE_PATTERNS = [
|
|
5
|
+
"**/node_modules/**",
|
|
6
|
+
"**/.mops/**",
|
|
7
|
+
"**/.vessel/**",
|
|
8
|
+
"**/.git/**",
|
|
9
|
+
"**/dist/**",
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* Common glob configuration for Motoko file operations
|
|
13
|
+
*/
|
|
14
|
+
export const MOTOKO_GLOB_CONFIG = {
|
|
15
|
+
nocase: true,
|
|
16
|
+
ignore: MOTOKO_IGNORE_PATTERNS,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Regex to match a file path for dependency and toolchain versions
|
|
20
|
+
*/
|
|
21
|
+
export const FILE_PATH_REGEX = /^(\.?\.)?\//;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import { setWasmBindings } from "../../wasm.js";
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const wasm = require(path.join(__dirname, "../../wasm/pkg/nodejs/wasm.js"));
|
|
3
8
|
setWasmBindings(wasm);
|
|
4
9
|
export * from "../../cli.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface MocSpan {
|
|
2
|
+
file: string;
|
|
3
|
+
line_start: number;
|
|
4
|
+
column_start: number;
|
|
5
|
+
line_end: number;
|
|
6
|
+
column_end: number;
|
|
7
|
+
is_primary: boolean;
|
|
8
|
+
label: string | null;
|
|
9
|
+
suggested_replacement: string | null;
|
|
10
|
+
suggestion_applicability: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface MocDiagnostic {
|
|
13
|
+
message: string;
|
|
14
|
+
code: string;
|
|
15
|
+
level: string;
|
|
16
|
+
spans: MocSpan[];
|
|
17
|
+
notes: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function parseDiagnostics(stdout: string): MocDiagnostic[];
|
|
20
|
+
export interface AutofixResult {
|
|
21
|
+
/** Map of file path → diagnostic codes fixed in that file */
|
|
22
|
+
fixedFiles: Map<string, string[]>;
|
|
23
|
+
totalFixCount: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function autofixMotoko(mocPath: string, files: string[], mocArgs: string[]): Promise<AutofixResult | null>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { execa } from "execa";
|
|
4
|
+
import { TextDocument, } from "vscode-languageserver-textdocument";
|
|
5
|
+
export function parseDiagnostics(stdout) {
|
|
6
|
+
return stdout
|
|
7
|
+
.split("\n")
|
|
8
|
+
.filter((l) => l.trim())
|
|
9
|
+
.map((l) => {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(l);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
.filter((d) => d !== null);
|
|
18
|
+
}
|
|
19
|
+
function extractFixes(diagnostics) {
|
|
20
|
+
const fixes = [];
|
|
21
|
+
for (const diag of diagnostics) {
|
|
22
|
+
for (const span of diag.spans) {
|
|
23
|
+
if (span.suggestion_applicability === "MachineApplicable" &&
|
|
24
|
+
span.suggested_replacement !== null) {
|
|
25
|
+
fixes.push({
|
|
26
|
+
file: span.file,
|
|
27
|
+
code: diag.code,
|
|
28
|
+
edit: {
|
|
29
|
+
range: {
|
|
30
|
+
start: {
|
|
31
|
+
line: span.line_start - 1,
|
|
32
|
+
character: span.column_start - 1,
|
|
33
|
+
},
|
|
34
|
+
end: {
|
|
35
|
+
line: span.line_end - 1,
|
|
36
|
+
character: span.column_end - 1,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
newText: span.suggested_replacement,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return fixes;
|
|
46
|
+
}
|
|
47
|
+
const MAX_FIX_ITERATIONS = 10;
|
|
48
|
+
export async function autofixMotoko(mocPath, files, mocArgs) {
|
|
49
|
+
const fixedFilesCodes = new Map();
|
|
50
|
+
for (let iteration = 0; iteration < MAX_FIX_ITERATIONS; iteration++) {
|
|
51
|
+
const allFixes = [];
|
|
52
|
+
for (const file of files) {
|
|
53
|
+
const result = await execa(mocPath, [file, "--error-format=json", ...mocArgs], { stdio: "pipe", reject: false });
|
|
54
|
+
const diagnostics = parseDiagnostics(result.stdout);
|
|
55
|
+
allFixes.push(...extractFixes(diagnostics));
|
|
56
|
+
}
|
|
57
|
+
if (allFixes.length === 0) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
const fixesByFile = new Map();
|
|
61
|
+
for (const fix of allFixes) {
|
|
62
|
+
const normalizedPath = resolve(fix.file);
|
|
63
|
+
const existing = fixesByFile.get(normalizedPath) ?? [];
|
|
64
|
+
existing.push(fix);
|
|
65
|
+
fixesByFile.set(normalizedPath, existing);
|
|
66
|
+
}
|
|
67
|
+
let progress = false;
|
|
68
|
+
for (const [file, fixes] of fixesByFile) {
|
|
69
|
+
const original = await readFile(file, "utf-8");
|
|
70
|
+
const doc = TextDocument.create(`file://${file}`, "motoko", 0, original);
|
|
71
|
+
let result;
|
|
72
|
+
try {
|
|
73
|
+
result = TextDocument.applyEdits(doc, fixes.map((f) => f.edit));
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.warn(`Warning: could not apply fixes to ${file}: ${err}`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (result === original) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
await writeFile(file, result, "utf-8");
|
|
83
|
+
progress = true;
|
|
84
|
+
const existing = fixedFilesCodes.get(file) ?? [];
|
|
85
|
+
for (const fix of fixes) {
|
|
86
|
+
existing.push(fix.code);
|
|
87
|
+
}
|
|
88
|
+
fixedFilesCodes.set(file, existing);
|
|
89
|
+
}
|
|
90
|
+
if (!progress) {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (fixedFilesCodes.size === 0) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let totalFixCount = 0;
|
|
98
|
+
for (const codes of fixedFilesCodes.values()) {
|
|
99
|
+
totalFixCount += codes.length;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
fixedFiles: fixedFilesCodes,
|
|
103
|
+
totalFixCount,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { parse } from "semver";
|
|
3
|
+
import { readConfig } from "../mops.js";
|
|
2
4
|
import { getMocPath } from "./get-moc-path.js";
|
|
5
|
+
export function getMocSemVer() {
|
|
6
|
+
return parse(getMocVersion(false));
|
|
7
|
+
}
|
|
3
8
|
export function getMocVersion(throwOnError = false) {
|
|
4
|
-
let
|
|
9
|
+
let configVersion = readConfig().toolchain?.moc;
|
|
10
|
+
if (configVersion) {
|
|
11
|
+
return configVersion;
|
|
12
|
+
}
|
|
13
|
+
const mocPath = getMocPath(false);
|
|
5
14
|
if (!mocPath) {
|
|
6
15
|
return "";
|
|
7
16
|
}
|
package/dist/mops.js
CHANGED
|
@@ -10,6 +10,7 @@ import { mainActor, storageActor } from "./api/actors.js";
|
|
|
10
10
|
import { getNetwork } from "./api/network.js";
|
|
11
11
|
import { getHighestVersion } from "./api/getHighestVersion.js";
|
|
12
12
|
import { getPackageId } from "./helpers/get-package-id.js";
|
|
13
|
+
import { FILE_PATH_REGEX } from "./constants.js";
|
|
13
14
|
if (!globalThis.fetch) {
|
|
14
15
|
globalThis.fetch = fetch;
|
|
15
16
|
}
|
|
@@ -135,7 +136,7 @@ export function getDependencyType(version) {
|
|
|
135
136
|
if (version.startsWith("https://github.com/")) {
|
|
136
137
|
return "github";
|
|
137
138
|
}
|
|
138
|
-
else if (version.match(
|
|
139
|
+
else if (version.match(FILE_PATH_REGEX)) {
|
|
139
140
|
return "local";
|
|
140
141
|
}
|
|
141
142
|
else {
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ic-mops",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mops": "bin/mops.js",
|
|
@@ -70,8 +70,9 @@
|
|
|
70
70
|
"semver": "7.7.1",
|
|
71
71
|
"stream-to-promise": "3.0.0",
|
|
72
72
|
"string-width": "7.2.0",
|
|
73
|
-
"tar": "7.
|
|
74
|
-
"terminal-size": "4.0.0"
|
|
73
|
+
"tar": "7.5.6",
|
|
74
|
+
"terminal-size": "4.0.0",
|
|
75
|
+
"vscode-languageserver-textdocument": "1.0.12"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
77
78
|
"@tsconfig/strictest": "2.0.5",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { describe, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cliSnapshot } from "./helpers";
|
|
4
|
+
describe("build without dfx", () => {
|
|
5
|
+
test("builds using mops toolchain moc", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "build/no-dfx");
|
|
7
|
+
await cliSnapshot(["build"], { cwd }, 0);
|
|
8
|
+
}, 120_000);
|
|
9
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cliSnapshot } from "./helpers";
|
|
4
|
+
describe("build", () => {
|
|
5
|
+
test("ok", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "build/success");
|
|
7
|
+
await cliSnapshot(["build", "--verbose"], { cwd }, 0);
|
|
8
|
+
await cliSnapshot(["build", "foo"], { cwd }, 0);
|
|
9
|
+
await cliSnapshot(["build", "bar"], { cwd }, 0);
|
|
10
|
+
await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
|
|
11
|
+
});
|
|
12
|
+
test("error", async () => {
|
|
13
|
+
const cwd = path.join(import.meta.dirname, "build/error");
|
|
14
|
+
await cliSnapshot(["build", "foo", "--verbose"], { cwd }, 0);
|
|
15
|
+
expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
16
|
+
expect((await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cliSnapshot } from "./helpers";
|
|
4
|
+
describe("check-candid", () => {
|
|
5
|
+
test("ok", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "check-candid");
|
|
7
|
+
await cliSnapshot(["check-candid", "a.did", "a.did"], { cwd }, 0);
|
|
8
|
+
await cliSnapshot(["check-candid", "b.did", "b.did"], { cwd }, 0);
|
|
9
|
+
await cliSnapshot(["check-candid", "c.did", "c.did"], { cwd }, 0);
|
|
10
|
+
await cliSnapshot(["check-candid", "a.did", "b.did"], { cwd }, 0);
|
|
11
|
+
await cliSnapshot(["check-candid", "b.did", "a.did"], { cwd }, 0);
|
|
12
|
+
});
|
|
13
|
+
test("error", async () => {
|
|
14
|
+
const cwd = path.join(import.meta.dirname, "check-candid");
|
|
15
|
+
await cliSnapshot(["check-candid", "a.did", "c.did"], { cwd }, 1);
|
|
16
|
+
await cliSnapshot(["check-candid", "c.did", "a.did"], { cwd }, 1);
|
|
17
|
+
await cliSnapshot(["check-candid", "b.did", "c.did"], { cwd }, 1);
|
|
18
|
+
await cliSnapshot(["check-candid", "c.did", "b.did"], { cwd }, 1);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, test } from "@jest/globals";
|
|
2
|
+
import { cpSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { parseDiagnostics } from "../helpers/autofix-motoko";
|
|
5
|
+
import { cli, normalizePaths } from "./helpers";
|
|
6
|
+
function countCodes(stdout) {
|
|
7
|
+
const counts = {};
|
|
8
|
+
for (const diag of parseDiagnostics(stdout)) {
|
|
9
|
+
counts[diag.code] = (counts[diag.code] ?? 0) + 1;
|
|
10
|
+
}
|
|
11
|
+
return counts;
|
|
12
|
+
}
|
|
13
|
+
describe("check --fix", () => {
|
|
14
|
+
const fixDir = path.join(import.meta.dirname, "check/fix");
|
|
15
|
+
const runDir = path.join(fixDir, "run");
|
|
16
|
+
const warningFlags = "-W=M0223,M0236,M0237";
|
|
17
|
+
const diagnosticFlags = [warningFlags, "--error-format=json"];
|
|
18
|
+
beforeAll(() => {
|
|
19
|
+
for (const file of readdirSync(runDir).filter((f) => f.endsWith(".mo"))) {
|
|
20
|
+
unlinkSync(path.join(runDir, file));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
function copyFixture(file) {
|
|
24
|
+
const dest = path.join(runDir, file);
|
|
25
|
+
cpSync(path.join(fixDir, file), dest);
|
|
26
|
+
return dest;
|
|
27
|
+
}
|
|
28
|
+
async function testCheckFix(file, expectedDiagnostics, expectedAfterDiagnostics = {}) {
|
|
29
|
+
const runFilePath = copyFixture(file);
|
|
30
|
+
const beforeResult = await cli(["check", runFilePath, "--", ...diagnosticFlags], { cwd: fixDir });
|
|
31
|
+
expect(countCodes(beforeResult.stdout)).toEqual(expectedDiagnostics);
|
|
32
|
+
const fixResult = await cli(["check", runFilePath, "--fix", "--", warningFlags], { cwd: fixDir });
|
|
33
|
+
expect(normalizePaths(fixResult.stdout)).toMatchSnapshot("fix output");
|
|
34
|
+
expect(readFileSync(runFilePath, "utf-8")).toMatchSnapshot();
|
|
35
|
+
const afterResult = await cli(["check", runFilePath, "--", ...diagnosticFlags], { cwd: fixDir });
|
|
36
|
+
expect(countCodes(afterResult.stdout)).toEqual(expectedAfterDiagnostics);
|
|
37
|
+
return runFilePath;
|
|
38
|
+
}
|
|
39
|
+
test("M0223", async () => {
|
|
40
|
+
await testCheckFix("M0223.mo", { M0223: 1 });
|
|
41
|
+
});
|
|
42
|
+
test("M0236", async () => {
|
|
43
|
+
await testCheckFix("M0236.mo", { M0236: 1 });
|
|
44
|
+
});
|
|
45
|
+
test("M0237", async () => {
|
|
46
|
+
await testCheckFix("M0237.mo", { M0237: 1 });
|
|
47
|
+
});
|
|
48
|
+
test("edit-suggestions", async () => {
|
|
49
|
+
await testCheckFix("edit-suggestions.mo", {
|
|
50
|
+
M0223: 2,
|
|
51
|
+
M0236: 11,
|
|
52
|
+
M0237: 17,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
test("transitive imports", async () => {
|
|
56
|
+
const runMainPath = copyFixture("transitive-main.mo");
|
|
57
|
+
const runLibPath = copyFixture("transitive-lib.mo");
|
|
58
|
+
const fixResult = await cli(["check", runMainPath, "--fix", "--", warningFlags], { cwd: fixDir });
|
|
59
|
+
expect(normalizePaths(fixResult.stdout)).toMatchSnapshot("fix output");
|
|
60
|
+
expect(readFileSync(runMainPath, "utf-8")).toMatchSnapshot("main file");
|
|
61
|
+
expect(readFileSync(runLibPath, "utf-8")).toMatchSnapshot("lib file");
|
|
62
|
+
const afterResult = await cli(["check", runMainPath, "--", ...diagnosticFlags], { cwd: fixDir });
|
|
63
|
+
expect(countCodes(afterResult.stdout)).toEqual({});
|
|
64
|
+
});
|
|
65
|
+
test("verbose", async () => {
|
|
66
|
+
const result = await cli(["check", "Ok.mo", "--fix", "--verbose"], {
|
|
67
|
+
cwd: fixDir,
|
|
68
|
+
});
|
|
69
|
+
expect(result.exitCode).toBe(0);
|
|
70
|
+
expect(result.stdout).toContain("Attempting to fix files");
|
|
71
|
+
expect(result.stdout).toContain("No fixes were needed");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cliSnapshot } from "./helpers";
|
|
4
|
+
describe("check", () => {
|
|
5
|
+
test("ok", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "check/success");
|
|
7
|
+
await cliSnapshot(["check", "Ok.mo"], { cwd }, 0);
|
|
8
|
+
await cliSnapshot(["check", "Ok.mo", "--verbose"], { cwd }, 0);
|
|
9
|
+
});
|
|
10
|
+
test("error", async () => {
|
|
11
|
+
const cwd = path.join(import.meta.dirname, "check/error");
|
|
12
|
+
await cliSnapshot(["check", "Error.mo"], { cwd }, 1);
|
|
13
|
+
await cliSnapshot(["check", "Ok.mo", "Error.mo"], { cwd }, 1);
|
|
14
|
+
});
|
|
15
|
+
test("warning", async () => {
|
|
16
|
+
const cwd = path.join(import.meta.dirname, "check/success");
|
|
17
|
+
const result = await cliSnapshot(["check", "Warning.mo"], { cwd }, 0);
|
|
18
|
+
expect(result.stderr).toMatch(/warning \[M0194\]/);
|
|
19
|
+
expect(result.stderr).toMatch(/unused identifier/);
|
|
20
|
+
});
|
|
21
|
+
test("warning verbose", async () => {
|
|
22
|
+
const cwd = path.join(import.meta.dirname, "check/success");
|
|
23
|
+
const result = await cliSnapshot(["check", "Warning.mo", "--verbose"], { cwd }, 0);
|
|
24
|
+
expect(result.stderr).toMatch(/warning \[M0194\]/);
|
|
25
|
+
expect(result.stderr).toMatch(/unused identifier/);
|
|
26
|
+
});
|
|
27
|
+
test("warning with -Werror flag", async () => {
|
|
28
|
+
const cwd = path.join(import.meta.dirname, "check/success");
|
|
29
|
+
const result = await cliSnapshot(["check", "Warning.mo", "--", "-Werror"], { cwd }, 1);
|
|
30
|
+
expect(result.stderr).toMatch(/warning \[M0194\]/);
|
|
31
|
+
expect(result.stderr).toMatch(/unused identifier/);
|
|
32
|
+
});
|
|
33
|
+
});
|
package/dist/tests/cli.test.js
CHANGED
|
@@ -1,63 +1,10 @@
|
|
|
1
1
|
import { describe, expect, test } from "@jest/globals";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return await execa("npm", ["run", "mops", "--", ...args], {
|
|
6
|
-
env: { MOPS_CWD: cwd },
|
|
7
|
-
stdio: "pipe",
|
|
8
|
-
reject: false,
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
const cliSnapshot = async (args, options, exitCode) => {
|
|
12
|
-
const result = await cli(args, options);
|
|
13
|
-
expect({
|
|
14
|
-
command: result.command,
|
|
15
|
-
exitCode: result.exitCode,
|
|
16
|
-
timedOut: result.timedOut,
|
|
17
|
-
stdio: Boolean(result.stdout || result.stderr),
|
|
18
|
-
}).toEqual({
|
|
19
|
-
command: result.command,
|
|
20
|
-
exitCode,
|
|
21
|
-
timedOut: false,
|
|
22
|
-
stdio: true,
|
|
23
|
-
});
|
|
24
|
-
expect({
|
|
25
|
-
exitCode: result.exitCode,
|
|
26
|
-
stdout: result.stdout,
|
|
27
|
-
stderr: result.stderr,
|
|
28
|
-
}).toMatchSnapshot();
|
|
29
|
-
return result;
|
|
30
|
-
};
|
|
31
|
-
describe("mops", () => {
|
|
32
|
-
test("version", async () => {
|
|
2
|
+
import { cli } from "./helpers";
|
|
3
|
+
describe("cli", () => {
|
|
4
|
+
test("--version", async () => {
|
|
33
5
|
expect((await cli(["--version"])).stdout).toMatch(/CLI \d+\.\d+\.\d+/);
|
|
34
6
|
});
|
|
35
|
-
test("help", async () => {
|
|
7
|
+
test("--help", async () => {
|
|
36
8
|
expect((await cli(["--help"])).stdout).toMatch(/^Usage: mops/m);
|
|
37
9
|
});
|
|
38
|
-
test("build success", async () => {
|
|
39
|
-
const cwd = path.join(import.meta.dirname, "build/success");
|
|
40
|
-
await cliSnapshot(["build"], { cwd }, 0);
|
|
41
|
-
await cliSnapshot(["build", "foo"], { cwd }, 0);
|
|
42
|
-
await cliSnapshot(["build", "bar"], { cwd }, 0);
|
|
43
|
-
await cliSnapshot(["build", "foo", "bar"], { cwd }, 0);
|
|
44
|
-
});
|
|
45
|
-
test("build error", async () => {
|
|
46
|
-
const cwd = path.join(import.meta.dirname, "build/error");
|
|
47
|
-
await cliSnapshot(["build", "foo"], { cwd }, 0);
|
|
48
|
-
expect((await cliSnapshot(["build", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
49
|
-
expect((await cliSnapshot(["build", "foo", "bar"], { cwd }, 1)).stderr).toMatch("Candid compatibility check failed for canister bar");
|
|
50
|
-
});
|
|
51
|
-
test("check-candid", async () => {
|
|
52
|
-
const cwd = path.join(import.meta.dirname, "check-candid");
|
|
53
|
-
await cliSnapshot(["check-candid", "a.did", "a.did"], { cwd }, 0);
|
|
54
|
-
await cliSnapshot(["check-candid", "b.did", "b.did"], { cwd }, 0);
|
|
55
|
-
await cliSnapshot(["check-candid", "c.did", "c.did"], { cwd }, 0);
|
|
56
|
-
await cliSnapshot(["check-candid", "a.did", "b.did"], { cwd }, 0);
|
|
57
|
-
await cliSnapshot(["check-candid", "b.did", "a.did"], { cwd }, 0);
|
|
58
|
-
await cliSnapshot(["check-candid", "a.did", "c.did"], { cwd }, 1);
|
|
59
|
-
await cliSnapshot(["check-candid", "c.did", "a.did"], { cwd }, 1);
|
|
60
|
-
await cliSnapshot(["check-candid", "b.did", "c.did"], { cwd }, 1);
|
|
61
|
-
await cliSnapshot(["check-candid", "c.did", "b.did"], { cwd }, 1);
|
|
62
|
-
});
|
|
63
10
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CliOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
}
|
|
4
|
+
export declare const cli: (args: string[], { cwd }?: CliOptions) => Promise<import("execa").Result<{
|
|
5
|
+
stdio: "pipe";
|
|
6
|
+
reject: false;
|
|
7
|
+
cwd?: string | undefined;
|
|
8
|
+
env: {
|
|
9
|
+
MOPS_CWD?: string | undefined;
|
|
10
|
+
TZ?: string;
|
|
11
|
+
};
|
|
12
|
+
}>>;
|
|
13
|
+
export declare const normalizePaths: (text: string) => string;
|
|
14
|
+
export declare const cliSnapshot: (args: string[], options: CliOptions, exitCode: number) => Promise<import("execa").Result<{
|
|
15
|
+
stdio: "pipe";
|
|
16
|
+
reject: false;
|
|
17
|
+
cwd?: string | undefined;
|
|
18
|
+
env: {
|
|
19
|
+
MOPS_CWD?: string | undefined;
|
|
20
|
+
TZ?: string;
|
|
21
|
+
};
|
|
22
|
+
}>>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { expect } from "@jest/globals";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
export const cli = async (args, { cwd } = {}) => {
|
|
6
|
+
return await execa("npm", ["run", "--silent", "mops", "--", ...args], {
|
|
7
|
+
env: { ...process.env, ...(cwd != null && { MOPS_CWD: cwd }) },
|
|
8
|
+
...(cwd != null && { cwd }),
|
|
9
|
+
stdio: "pipe",
|
|
10
|
+
reject: false,
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
// Strip ANSI escape codes for portable snapshots (avoid control char in regex literal)
|
|
14
|
+
const stripAnsi = (s) => s.replace(new RegExp(`\u001b\\[[0-9;]*m`, "g"), "");
|
|
15
|
+
export const normalizePaths = (text) => {
|
|
16
|
+
// Replace absolute paths with placeholders for CI
|
|
17
|
+
return stripAnsi(text
|
|
18
|
+
.replaceAll(dirname(fileURLToPath(import.meta.url)), "<TEST_DIR>")
|
|
19
|
+
.replace(/\/[^\s"]+\/\.cache\/mops/g, "<CACHE>")
|
|
20
|
+
.replace(/\/[^\s"]+\/Library\/Caches\/mops/g, "<CACHE>")
|
|
21
|
+
.replace(/\/[^\s"[\]]+\/moc(?:-wrapper)?(?=\s|$)/g, "moc-wrapper")
|
|
22
|
+
.replace(/\/[^\s"[\]]+\.motoko\/bin\/moc/g, "moc-wrapper"));
|
|
23
|
+
};
|
|
24
|
+
export const cliSnapshot = async (args, options, exitCode) => {
|
|
25
|
+
const result = await cli(args, options);
|
|
26
|
+
expect({
|
|
27
|
+
command: result.command,
|
|
28
|
+
exitCode: result.exitCode,
|
|
29
|
+
timedOut: result.timedOut,
|
|
30
|
+
stdio: Boolean(result.stdout || result.stderr),
|
|
31
|
+
}).toEqual({
|
|
32
|
+
command: result.command,
|
|
33
|
+
exitCode,
|
|
34
|
+
timedOut: false,
|
|
35
|
+
stdio: true,
|
|
36
|
+
});
|
|
37
|
+
expect({
|
|
38
|
+
exitCode: result.exitCode,
|
|
39
|
+
stdout: normalizePaths(result.stdout),
|
|
40
|
+
stderr: normalizePaths(result.stderr),
|
|
41
|
+
}).toMatchSnapshot();
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cliSnapshot } from "./helpers";
|
|
4
|
+
describe("lint", () => {
|
|
5
|
+
test("ok", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "lint");
|
|
7
|
+
await cliSnapshot(["lint", "Ok", "--verbose"], { cwd }, 0);
|
|
8
|
+
});
|
|
9
|
+
test("error", async () => {
|
|
10
|
+
const cwd = path.join(import.meta.dirname, "lint");
|
|
11
|
+
await cliSnapshot(["lint", "--verbose"], { cwd }, 1);
|
|
12
|
+
await cliSnapshot(["lint", "NoBoolSwitch", "--verbose"], { cwd }, 1);
|
|
13
|
+
await cliSnapshot(["lint", "DoesNotExist"], { cwd }, 1);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { cli } from "./helpers";
|
|
4
|
+
describe("toolchain", () => {
|
|
5
|
+
test("file URI", async () => {
|
|
6
|
+
const cwd = path.join(import.meta.dirname, "toolchain");
|
|
7
|
+
const result = await cli(["toolchain", "bin", "moc"], { cwd });
|
|
8
|
+
expect(result.exitCode).toBe(0);
|
|
9
|
+
expect(result.stdout.trim()).toBe("./mock");
|
|
10
|
+
});
|
|
11
|
+
});
|
package/dist/types.d.ts
CHANGED
|
@@ -24,11 +24,15 @@ export type Config = {
|
|
|
24
24
|
outputDir?: string;
|
|
25
25
|
args?: string[];
|
|
26
26
|
};
|
|
27
|
+
lint?: {
|
|
28
|
+
args?: string[];
|
|
29
|
+
};
|
|
27
30
|
};
|
|
28
31
|
export type CanisterConfig = {
|
|
29
32
|
main: string;
|
|
30
33
|
args?: string[];
|
|
31
34
|
candid?: string;
|
|
35
|
+
initArg?: string;
|
|
32
36
|
};
|
|
33
37
|
export type Dependencies = Record<string, Dependency>;
|
|
34
38
|
export type Dependency = {
|
|
@@ -41,8 +45,9 @@ export type Toolchain = {
|
|
|
41
45
|
moc?: string;
|
|
42
46
|
wasmtime?: string;
|
|
43
47
|
"pocket-ic"?: string;
|
|
48
|
+
lintoko?: string;
|
|
44
49
|
};
|
|
45
|
-
export type Tool = "moc" | "wasmtime" | "pocket-ic";
|
|
50
|
+
export type Tool = "moc" | "wasmtime" | "pocket-ic" | "lintoko";
|
|
46
51
|
export type Requirements = {
|
|
47
52
|
moc?: string;
|
|
48
53
|
};
|