Skip to content

Commit 434a16c

Browse files
committed
removing strip-comments and using prettier to clean pragma versions
1 parent 7641856 commit 434a16c

File tree

5 files changed

+73
-43
lines changed

5 files changed

+73
-43
lines changed

package-lock.json

Lines changed: 1 addition & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
"@babel/code-frame": "^7.26.2",
8787
"@types/jest": "^29.5.14",
8888
"@types/semver": "^7.5.8",
89-
"@types/strip-comments": "^2.0.4",
9089
"@typescript-eslint/eslint-plugin": "^8.12.2",
9190
"@typescript-eslint/parser": "^8.12.2",
9291
"c8": "^9.1.0",
@@ -111,8 +110,7 @@
111110
"dependencies": {
112111
"@nomicfoundation/slang": "0.18.3",
113112
"@solidity-parser/parser": "^0.18.0",
114-
"semver": "^7.6.3",
115-
"strip-comments": "^2.0.1"
113+
"semver": "^7.6.3"
116114
},
117115
"peerDependencies": {
118116
"prettier": ">=3.0.0"

src/slang-utils/create-parser.ts

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { VersionExpressionSets as SlangVersionExpressionSets } from '@nomicfoundation/slang/ast';
12
import { NonterminalKind, Query } from '@nomicfoundation/slang/cst';
23
import { Parser } from '@nomicfoundation/slang/parser';
3-
import strip from 'strip-comments';
4+
import prettier from 'prettier';
45
import {
56
maxSatisfying,
67
minSatisfying,
@@ -9,6 +10,12 @@ import {
910
satisfies,
1011
validRange
1112
} from 'semver';
13+
import slangPrint from '../slangPrinter.js';
14+
import { locEnd, locStart } from './loc.js';
15+
import { VersionExpressionSets } from '../slang-nodes/VersionExpressionSets.js';
16+
17+
import type { NonterminalNode } from '@nomicfoundation/slang/cst';
18+
import type { Parser as PrettierParser } from 'prettier';
1219

1320
const supportedVersions = Parser.supportedVersions();
1421

@@ -25,15 +32,48 @@ const milestoneVersions = Array.from(
2532
return versions;
2633
}, []);
2734

35+
const bypassParse =
36+
(parseOutput: NonterminalNode) => (): VersionExpressionSets => {
37+
// We don't need to parse the text twice if we already have the
38+
// NonterminalNode.
39+
const parsed = new VersionExpressionSets(
40+
new SlangVersionExpressionSets(parseOutput),
41+
0
42+
);
43+
parsed.comments = [];
44+
return parsed;
45+
};
46+
47+
const options = {
48+
plugins: [
49+
{
50+
languages: [{ name: 'SolidityPragma', parsers: ['slangPragma'] }],
51+
parsers: {
52+
slangPragma: {
53+
astFormat: 'slang-ast',
54+
locStart,
55+
locEnd
56+
} as PrettierParser
57+
},
58+
printers: { ['slang-ast']: { print: slangPrint } }
59+
}
60+
],
61+
parser: 'slangPragma'
62+
};
63+
64+
const query = Query.parse(
65+
'[VersionPragma @versionRanges [VersionExpressionSets]]'
66+
);
67+
2868
// TODO if we ended up selecting the same version that the pragmas were parsed with,
2969
// should we be able to reuse/just return the already parsed CST, instead of
3070
// returning a Parser and forcing user to parse it again?
31-
export function createParser(text: string): Parser {
71+
export async function createParser(text: string): Promise<Parser> {
3272
let inferredRanges: string[] = [];
3373

3474
for (const version of milestoneVersions) {
3575
try {
36-
inferredRanges = tryToCollectPragmas(text, version);
76+
inferredRanges = await tryToCollectPragmas(text, version);
3777
break;
3878
} catch {}
3979
}
@@ -57,22 +97,22 @@ export function createParser(text: string): Parser {
5797
: Parser.create(supportedVersions[supportedVersions.length - 1]);
5898
}
5999

60-
function tryToCollectPragmas(text: string, version: string): string[] {
61-
const language = Parser.create(version);
62-
const parseOutput = language.parse(NonterminalKind.SourceUnit, text);
63-
const query = Query.parse(
64-
'[VersionPragma @versionRanges [VersionExpressionSets]]'
65-
);
100+
async function tryToCollectPragmas(
101+
text: string,
102+
version: string
103+
): Promise<string[]> {
104+
const parser = Parser.create(version);
105+
const parseOutput = parser.parse(NonterminalKind.SourceUnit, text);
106+
66107
const matches = parseOutput.createTreeCursor().query([query]);
67108
const ranges: string[] = [];
68109

69110
let match;
70111
while ((match = matches.next())) {
71-
ranges.push(
72-
strip(match.captures.versionRanges[0].node.unparse(), {
73-
keepProtected: true
74-
})
112+
options.plugins[0].parsers.slangPragma.parse = bypassParse(
113+
match.captures.versionRanges[0].node.asNonterminalNode()!
75114
);
115+
ranges.push(await prettier.format(text, options));
76116
}
77117

78118
if (ranges.length === 0) {

src/slangSolidityParser.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import type { AstNode } from './slang-nodes/types.d.ts';
1212

1313
const supportedVersions = Parser.supportedVersions();
1414

15-
export default function parse(
15+
export default async function parse(
1616
text: string,
1717
options: ParserOptions<AstNode>
18-
): AstNode {
18+
): Promise<AstNode> {
1919
const compiler = maxSatisfying(supportedVersions, options.compiler);
2020

2121
const parser =
2222
compiler && supportedVersions.includes(compiler)
2323
? Parser.create(compiler)
24-
: createParser(text);
24+
: await createParser(text);
2525

2626
const parseOutput = parser.parse(NonterminalKind.SourceUnit, text);
2727
printWarning(

tests/unit/slang-utils/create-parser.test.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,31 @@ describe('inferLanguage', function () {
8383
{
8484
description:
8585
'should use the latest version if the range is outside the supported versions',
86-
source: `pragma solidity ^0.8.27;`,
86+
source: `pragma solidity ^0.9.27;`,
8787
version: latestSupportedVersion
88+
},
89+
{
90+
description: 'broken by new lines, whitespace and comments',
91+
source: `pragma solidity 0.
92+
// comment 1
93+
7.
94+
/* comment 2*/
95+
3;`,
96+
version: '0.7.3'
8897
}
8998
];
9099

91100
for (const { description, source, version } of fixtures) {
92-
test(description, function () {
93-
const parser = createParser(source);
101+
test(description, async function () {
102+
const parser = await createParser(source);
94103
expect(parser.version).toEqual(version);
95104
});
96105
}
97106

98107
test.skip('should throw an error if there are incompatible ranges', function () {
99-
expect(() =>
100-
createParser(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`)
108+
expect(
109+
async () =>
110+
await createParser(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`)
101111
).toThrow();
102112
});
103113
});

0 commit comments

Comments
 (0)