Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 45 additions & 63 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
27 changes: 18 additions & 9 deletions src/slang-utils/create-parser.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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();

Expand All @@ -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) {
Expand All @@ -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) =>
Expand All @@ -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()
)
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/slangSolidityParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {}
}

================================================================================
`;
1 change: 1 addition & 0 deletions tests/format/FunctionDefinitionsV0.5.0/format.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
runFormatTest(import.meta, ['slang-solidity']);
30 changes: 28 additions & 2 deletions tests/unit/slang-utils/create-parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ describe('inferLanguage', function () {
const supportedVersions = Parser.supportedVersions();
const latestSupportedVersion =
supportedVersions[supportedVersions.length - 1];
const options = { filepath: 'test.sol' };

const fixtures = [
{
Expand Down Expand Up @@ -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();
});
});
Loading