Skip to content

Commit

Permalink
check if there is at least 1 valid version in the ranges before compa…
Browse files Browse the repository at this point in the history
…ring it against the supported versions.
  • Loading branch information
Janther committed Sep 27, 2024
1 parent 176d481 commit 0510e17
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
8 changes: 7 additions & 1 deletion src/slang-utils/infer-language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { VersionExpressionSets as SlangVersionExpressionSets } from '@nomicfound
import { NonterminalKind } from '@nomicfoundation/slang/kinds/index.js';
import { Language } from '@nomicfoundation/slang/language/index.js';
import { Query } from '@nomicfoundation/slang/query/index.js';
import { maxSatisfying, minSatisfying, minor, major } from 'semver';
import { maxSatisfying, minSatisfying, minor, major, minVersion } from 'semver';
import { VersionExpressionSets } from '../slang-nodes/VersionExpressionSets.js';

import type { NonterminalNode } from '@nomicfoundation/slang/cst';
Expand Down Expand Up @@ -30,6 +30,12 @@ export function inferLanguage(text: string): Language {
break;
} catch {}
}

if (!minVersion(inferredRange)) {
throw new Error(
"Couldn't infer any version from the ranges in the pragmas."
);
}
const maxSatisfyingVersion = maxSatisfying(supportedVersions, inferredRange);

return maxSatisfyingVersion
Expand Down
105 changes: 74 additions & 31 deletions tests/unit/slang-utils/infer-language.test.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,78 @@
import { Language } from "@nomicfoundation/slang/language/index.js";
import { inferLanguage } from "../../../src/slang-utils/infer-language.js"
import { Language } from '@nomicfoundation/slang/language/index.js';
import { inferLanguage } from '../../../src/slang-utils/infer-language.js';

describe("inferLanguage", function () {
const fixtures = [
{ description: "Caret range", source: `pragma solidity ^0.7.0;`, version: "0.7.6" },
{ description: "Pinned version", source: `pragma solidity 0.8.1;`, version: "0.8.1" },
{ description: "Caret range and pinned version", source: `pragma solidity ^0.8.0; pragma solidity 0.8.2;`, version: "0.8.2" },
{ description: "With multiline comment before the range", source: `pragma solidity /* comment */ 0.8.2;`, version: "0.8.2" },
{ description: "With natspec comment before the range", source: `pragma solidity /** comment */ 0.8.2;`, version: "0.8.2" },
{ description: "With multiline comment after the range", source: `pragma solidity 0.8.2 /* comment */;`, version: "0.8.2" },
{ description: "With natspec comment after the range", source: `pragma solidity 0.8.2 /** comment */;`, version: "0.8.2" },
{ description: "With tracing line comment", source: `pragma solidity 0.8.2; // line comment`, version: "0.8.2" },
]

for (const { description, source, version } of fixtures) {
test(description, function () {
const inferredLanguage = inferLanguage(source);
expect(inferredLanguage.version).toEqual(version);
})
describe('inferLanguage', function () {
const fixtures = [
{
description: 'Caret range',
source: `pragma solidity ^0.7.0;`,
version: '0.7.6'
},
{
description: 'Pinned version',
source: `pragma solidity 0.8.1;`,
version: '0.8.1'
},
{
description: 'Caret range and pinned version',
source: `pragma solidity ^0.8.0; pragma solidity 0.8.2;`,
version: '0.8.2'
},
{
description: 'With multiline comment before the range',
source: `pragma solidity /* comment */ 0.8.2;`,
version: '0.8.2'
},
{
description: 'With natspec comment before the range',
source: `pragma solidity /** comment */ 0.8.2;`,
version: '0.8.2'
},
{
description: 'With multiline comment after the range',
source: `pragma solidity 0.8.2 /* comment */;`,
version: '0.8.2'
},
{
description: 'With natspec comment after the range',
source: `pragma solidity 0.8.2 /** comment */;`,
version: '0.8.2'
},
{
description: 'With tracing line comment',
source: `pragma solidity 0.8.2; // line comment`,
version: '0.8.2'
}
];

for (const { description, source, version } of fixtures) {
test(description, function () {
const inferredLanguage = inferLanguage(source);
expect(inferredLanguage.version).toEqual(version);
});
}

test('should use the latest valid version if the source has no pragmas', function () {
const supportedVersions = Language.supportedVersions();
const latestSupportedVersion =
supportedVersions[supportedVersions.length - 1];
let inferredLanguage = inferLanguage(`contract Foo {}`);
expect(inferredLanguage.version).toEqual(latestSupportedVersion);
inferredLanguage = inferLanguage(`contract Foo {byte bar;}`);
expect(inferredLanguage.version).toEqual('0.7.6');
});

test("should use the latest valid version if the source has no pragmas", function () {
const supportedVersions = Language.supportedVersions();
const latestSupportedVersion = supportedVersions[supportedVersions.length - 1];
let inferredLanguage = inferLanguage(`contract Foo {}`);
expect(inferredLanguage.version).toEqual(latestSupportedVersion);
inferredLanguage = inferLanguage(`contract Foo {byte bar;}`);
expect(inferredLanguage.version).toEqual('0.7.6');
})
test('should use the latest version if the range is outside the supported versions', function () {
const supportedVersions = Language.supportedVersions();
const latestSupportedVersion =
supportedVersions[supportedVersions.length - 1];
const inferredLanguage = inferLanguage(`pragma solidity ^0.8.27;`);
expect(inferredLanguage.version).toEqual(latestSupportedVersion);
});

test.skip('should throw an error if there are incompatible ranges', function () {
expect(() => inferLanguage(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`)).toThrow();
})
})
test('should throw an error if there are incompatible ranges', function () {
expect(() =>
inferLanguage(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`)
).toThrow();
});
});

0 comments on commit 0510e17

Please sign in to comment.