From 0510e17423b92a7afeda2014ea84dff5e7b1449a Mon Sep 17 00:00:00 2001 From: Klaus Date: Sat, 28 Sep 2024 11:04:39 +1200 Subject: [PATCH] check if there is at least 1 valid version in the ranges before comparing it against the supported versions. --- src/slang-utils/infer-language.ts | 8 +- tests/unit/slang-utils/infer-language.test.js | 105 ++++++++++++------ 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/src/slang-utils/infer-language.ts b/src/slang-utils/infer-language.ts index 45d58e0c..62a3a7e5 100644 --- a/src/slang-utils/infer-language.ts +++ b/src/slang-utils/infer-language.ts @@ -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'; @@ -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 diff --git a/tests/unit/slang-utils/infer-language.test.js b/tests/unit/slang-utils/infer-language.test.js index 3aa6217c..a7e3d95e 100644 --- a/tests/unit/slang-utils/infer-language.test.js +++ b/tests/unit/slang-utils/infer-language.test.js @@ -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(); - }) -}) \ No newline at end of file + test('should throw an error if there are incompatible ranges', function () { + expect(() => + inferLanguage(`pragma solidity ^0.8.0; pragma solidity 0.7.6;`) + ).toThrow(); + }); +});