diff --git a/package-lock.json b/package-lock.json index 09efb2b6..b939bdff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,16 +11,14 @@ "dependencies": { "@nomicfoundation/slang": "0.18.3", "@solidity-parser/parser": "^0.18.0", - "semver": "^7.6.3", - "strip-comments": "^2.0.1" + "semver": "^7.6.3" }, "devDependencies": { "@babel/code-frame": "^7.26.2", "@types/jest": "^29.5.14", "@types/semver": "^7.5.8", - "@types/strip-comments": "^2.0.4", - "@typescript-eslint/eslint-plugin": "^8.12.2", - "@typescript-eslint/parser": "^8.12.2", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", "c8": "^9.1.0", "cross-env": "^7.0.3", "eslint": "^9.14.0", @@ -1764,13 +1762,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "node_modules/@types/strip-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/strip-comments/-/strip-comments-2.0.4.tgz", - "integrity": "sha512-YwcQqIGy90zEHrReYrMTpZfq003Um77WayeE8UwJTHvaM9g9XR9N7GMVSnjRhhDzQYVX375JnB5P6q5kAg221g==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/yargs": { "version": "17.0.17", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", @@ -1787,17 +1778,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", - "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/type-utils": "8.12.2", - "@typescript-eslint/utils": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1821,16 +1812,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", - "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" }, "engines": { @@ -1850,14 +1841,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1868,14 +1859,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", - "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1893,9 +1884,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true, "license": "MIT", "engines": { @@ -1907,14 +1898,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1962,16 +1953,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1985,13 +1976,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -6567,15 +6558,6 @@ "node": ">=8" } }, - "node_modules/strip-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", diff --git a/package.json b/package.json index e026f0d8..6458d996 100644 --- a/package.json +++ b/package.json @@ -86,9 +86,8 @@ "@babel/code-frame": "^7.26.2", "@types/jest": "^29.5.14", "@types/semver": "^7.5.8", - "@types/strip-comments": "^2.0.4", - "@typescript-eslint/eslint-plugin": "^8.12.2", - "@typescript-eslint/parser": "^8.12.2", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", "c8": "^9.1.0", "cross-env": "^7.0.3", "eslint": "^9.14.0", @@ -111,8 +110,7 @@ "dependencies": { "@nomicfoundation/slang": "0.18.3", "@solidity-parser/parser": "^0.18.0", - "semver": "^7.6.3", - "strip-comments": "^2.0.1" + "semver": "^7.6.3" }, "peerDependencies": { "prettier": ">=3.0.0" diff --git a/src/slang-utils/create-parser.ts b/src/slang-utils/create-parser.ts index 6adbf067..0d1d1c1d 100644 --- a/src/slang-utils/create-parser.ts +++ b/src/slang-utils/create-parser.ts @@ -1,6 +1,6 @@ +import { VersionExpressionSets as SlangVersionExpressionSets } from '@nomicfoundation/slang/ast'; import { NonterminalKind, Query } from '@nomicfoundation/slang/cst'; import { Parser } from '@nomicfoundation/slang/parser'; -import strip from 'strip-comments'; import { maxSatisfying, minSatisfying, @@ -9,6 +9,9 @@ import { satisfies, validRange } from 'semver'; +import { VersionExpressionSets } from '../slang-nodes/VersionExpressionSets.js'; + +import type { ParserOptions } from 'prettier'; const supportedVersions = Parser.supportedVersions(); @@ -25,10 +28,14 @@ const milestoneVersions = Array.from( return versions; }, []); +const query = Query.parse( + '[VersionPragma @versionRanges [VersionExpressionSets]]' +); + // TODO if we ended up selecting the same version that the pragmas were parsed with, // should we be able to reuse/just return the already parsed CST, instead of // returning a Parser and forcing user to parse it again? -export function createParser(text: string): Parser { +export function createParser(text: string, options: ParserOptions): Parser { let inferredRanges: string[] = []; for (const version of milestoneVersions) { @@ -42,7 +49,7 @@ export function createParser(text: string): Parser { (versions, inferredRange) => { if (!validRange(inferredRange)) { throw new Error( - "Couldn't infer any version from the ranges in the pragmas." + `Couldn't infer any version from the ranges in the pragmas${options.filepath ? ` for file ${options.filepath}` : ''}` ); } return versions.filter((supportedVersion) => @@ -60,18 +67,20 @@ export function createParser(text: string): Parser { function tryToCollectPragmas(text: string, version: string): string[] { const language = Parser.create(version); const parseOutput = language.parse(NonterminalKind.SourceUnit, text); - const query = Query.parse( - '[VersionPragma @versionRanges [VersionExpressionSets]]' - ); const matches = parseOutput.createTreeCursor().query([query]); const ranges: string[] = []; let match; while ((match = matches.next())) { + const versionRange = new SlangVersionExpressionSets( + match.captures.versionRanges[0].node.asNonterminalNode()! + ); ranges.push( - strip(match.captures.versionRanges[0].node.unparse(), { - keepProtected: true - }) + // Replace all comments that could be in the expression with whitespace + new VersionExpressionSets(versionRange).comments.reduce( + (range, comment) => range.replace(comment.value, ' '), + versionRange.cst.unparse() + ) ); } diff --git a/src/slangSolidityParser.ts b/src/slangSolidityParser.ts index 2450f643..342d3a9f 100644 --- a/src/slangSolidityParser.ts +++ b/src/slangSolidityParser.ts @@ -22,7 +22,7 @@ export default function parse( const parser = compiler && supportedVersions.includes(compiler) ? Parser.create(compiler) - : createParser(text); + : createParser(text, options); const parseOutput = parser.parse(NonterminalKind.SourceUnit, text); printWarning( diff --git a/tests/format/FunctionDefinitionsV0.5.0/__snapshots__/format.test.js.snap b/tests/format/FunctionDefinitionsV0.5.0/__snapshots__/format.test.js.snap new file mode 100644 index 00000000..d369db5d --- /dev/null +++ b/tests/format/FunctionDefinitionsV0.5.0/__snapshots__/format.test.js.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FunctionDefinitions.sol format 1`] = ` +====================================options===================================== +parsers: ["slang-solidity"] +printWidth: 80 + | printWidth +=====================================input====================================== +contract FunctionDefinitions { + function () external {} + function () external payable {} +} + +=====================================output===================================== +contract FunctionDefinitions { + function() external {} + function() external payable {} +} + +================================================================================ +`; diff --git a/tests/format/FunctionDefinitionsV0.5.0/format.test.js b/tests/format/FunctionDefinitionsV0.5.0/format.test.js new file mode 100644 index 00000000..903b20e0 --- /dev/null +++ b/tests/format/FunctionDefinitionsV0.5.0/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ['slang-solidity']); diff --git a/tests/unit/slang-utils/create-parser.test.js b/tests/unit/slang-utils/create-parser.test.js index 96810629..5e4c0f07 100644 --- a/tests/unit/slang-utils/create-parser.test.js +++ b/tests/unit/slang-utils/create-parser.test.js @@ -5,6 +5,7 @@ describe('inferLanguage', function () { const supportedVersions = Parser.supportedVersions(); const latestSupportedVersion = supportedVersions[supportedVersions.length - 1]; + const options = { filepath: 'test.sol' }; const fixtures = [ { @@ -90,14 +91,39 @@ describe('inferLanguage', function () { for (const { description, source, version } of fixtures) { test(description, function () { - const parser = createParser(source); + const parser = createParser(source, options); expect(parser.version).toEqual(version); }); } + test('should throw when a pragma is broken by new lines, whitespace and comments', function () { + expect(() => + createParser( + `pragma solidity 0. + // comment 1 + 7. + /* comment 2*/ + 3;`, + options + ) + ).toThrow( + "Couldn't infer any version from the ranges in the pragmas for file test.sol" + ); + expect(() => + createParser( + `pragma solidity 0. + // comment 1 + 7. + /* comment 2*/ + 3;`, + {} + ) + ).toThrow("Couldn't infer any version from the ranges in the pragmas"); + }); + test.skip('should throw an error if there are incompatible ranges', function () { expect(() => - createParser(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`) + createParser(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`, options) ).toThrow(); }); });