diff --git a/package-lock.json b/package-lock.json index ba6e532..24fa72a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "prettier-plugin-motoko", - "version": "0.8.3", + "version": "0.8.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "prettier-plugin-motoko", - "version": "0.8.3", + "version": "0.8.4", "license": "Apache-2.0", "dependencies": { "out-of-character": "^1.2.1" diff --git a/package.json b/package.json index 797fc98..85a2814 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prettier-plugin-motoko", - "version": "0.8.3", + "version": "0.8.4", "description": "A code formatter for the Motoko smart contract language.", "main": "lib/environments/node.js", "browser": "lib/environments/web.js", diff --git a/packages/mo-fmt/package-lock.json b/packages/mo-fmt/package-lock.json index 1291314..202edb8 100644 --- a/packages/mo-fmt/package-lock.json +++ b/packages/mo-fmt/package-lock.json @@ -1,18 +1,18 @@ { "name": "mo-fmt", - "version": "0.8.3", + "version": "0.8.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mo-fmt", - "version": "0.8.3", + "version": "0.8.4", "license": "Apache-2.0", "dependencies": { "commander": "^9.4.0", "fast-glob": "^3.2.11", "prettier": "^3.0", - "prettier-plugin-motoko": "^0.8.3" + "prettier-plugin-motoko": "^0.8.4" }, "bin": { "mo-fmt": "bin/mo-fmt.js" @@ -4663,9 +4663,9 @@ } }, "node_modules/prettier-plugin-motoko": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-motoko/-/prettier-plugin-motoko-0.8.3.tgz", - "integrity": "sha512-En6HO9QJrLg5rIxQYfQgHycAi6hNnc+VIqMhVFDf+T/7B1U1iQCU2kTr7rkCMfqsjZ8Mm5DqZ13SD56a9zT21g==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/prettier-plugin-motoko/-/prettier-plugin-motoko-0.8.4.tgz", + "integrity": "sha512-LfCyp93m+Sgfu1CmZEYmeE89tJm2aLbAJ7Yy5NlJx0GOZjWqFDGE441bZSuHxxL8LKuJ4CpnLgP0FOc7CqTXow==", "dependencies": { "out-of-character": "^1.2.1" }, @@ -9283,9 +9283,9 @@ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==" }, "prettier-plugin-motoko": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-motoko/-/prettier-plugin-motoko-0.8.3.tgz", - "integrity": "sha512-En6HO9QJrLg5rIxQYfQgHycAi6hNnc+VIqMhVFDf+T/7B1U1iQCU2kTr7rkCMfqsjZ8Mm5DqZ13SD56a9zT21g==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/prettier-plugin-motoko/-/prettier-plugin-motoko-0.8.4.tgz", + "integrity": "sha512-LfCyp93m+Sgfu1CmZEYmeE89tJm2aLbAJ7Yy5NlJx0GOZjWqFDGE441bZSuHxxL8LKuJ4CpnLgP0FOc7CqTXow==", "requires": { "out-of-character": "^1.2.1" } diff --git a/packages/mo-fmt/package.json b/packages/mo-fmt/package.json index c8bab84..4f939df 100644 --- a/packages/mo-fmt/package.json +++ b/packages/mo-fmt/package.json @@ -1,6 +1,6 @@ { "name": "mo-fmt", - "version": "0.8.3", + "version": "0.8.4", "description": "An easy-to-use Motoko formatter command.", "main": "src/cli.js", "bin": { @@ -22,7 +22,7 @@ "commander": "^9.4.0", "fast-glob": "^3.2.11", "prettier": "^3.0", - "prettier-plugin-motoko": "^0.8.3" + "prettier-plugin-motoko": "^0.8.4" }, "devDependencies": { "@rollup/plugin-commonjs": "^22.0.2", diff --git a/src/parsers/motoko-tt-parse/preprocess.ts b/src/parsers/motoko-tt-parse/preprocess.ts index 328584d..aba9ceb 100644 --- a/src/parsers/motoko-tt-parse/preprocess.ts +++ b/src/parsers/motoko-tt-parse/preprocess.ts @@ -2,6 +2,8 @@ import { ParserOptions } from 'prettier'; import outOfCharacter from 'out-of-character'; import wasm from '../../wasm'; +const skipAutomaticSemiForNextLinePrefixes = ['.', '|>', ')', '}', ']']; + function getLineIndices(code: string): number[] { const indices = []; for (let i = 0; i < code.length; i++) { @@ -67,6 +69,7 @@ export default function preprocess( .map((line, i) => { const trimmedLine = line.trim(); if (!trimmedLine) { + nextIndent = -1; return line; } @@ -83,8 +86,14 @@ export default function preprocess( if ( trimmedLine === '}' && - // Skip when part of a path expression - !nextLineMaskedCommentsTrimmed.startsWith('.') && + // Skip if prefix found on next line + (!nextLineMaskedCommentsTrimmed || + skipAutomaticSemiForNextLinePrefixes.every( + (prefix) => + !nextLineMaskedCommentsTrimmed.startsWith( + prefix, + ), + )) && // Skip first block for if/else, try/catch !/^(else|catch)([^a-zA-Z0-9_]|$)/.test( nextLineMaskedCommentsTrimmed, diff --git a/tests/formatter.test.ts b/tests/formatter.test.ts index 3f5816d..98771af 100644 --- a/tests/formatter.test.ts +++ b/tests/formatter.test.ts @@ -354,6 +354,11 @@ describe('Motoko formatter', () => { 'if () {} else {};\n', ); expect(await format('{\n}\n.A')).toStrictEqual('{}.A;\n'); + expect( + await format('[\n {\n abc;\n }\n { 123 }\n];\n', { + trailingComma: 'none', + }), + ).toStrictEqual('[\n {\n abc;\n },\n { 123 }\n];\n'); }); test('automatic semicolons with line comment', async () => { @@ -424,6 +429,34 @@ describe('Motoko formatter', () => { expect(await format('[\na,b]')).toStrictEqual('[\n a,\n b,\n];\n'); expect(await format('[\na,]')).toStrictEqual('[\n a,\n];\n'); expect(await format('x : [\nT\n]')).toStrictEqual('x : [\n T\n];\n'); + expect(await format('x : [\n { abc; }\n];\n')).toEqual( + 'x : [{ abc }];\n', + ); + await expectFormatted('x : [{\n abc;\n}] = 1;\n'); + await expectFormatted('x : [{\n abc;\n}] = 1;\n'); + await expectFormatted('type T = [{\n abc;\n}];\n'); + await expectFormatted('let x = [\n {\n abc;\n },\n];\n'); + expect( + await format( + ` +public type T = { + x : [ + { + a : A; + fn : shared query A -> async T; + } + ]; +}`, + ), + ).toEqual( + ` +public type T = { + x : [{ + a : A; + fn : shared query A -> async T; + }]; +};`.trim() + '\n', + ); }); test('comma-parentheses', async () => {