diff --git a/.eslintrc.json b/.eslintrc.json index 4e074a20..f326b306 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,9 +28,9 @@ ] }, "ignorePatterns": [ - "src/types/typeStrings/typeString_parser_header.ts", - "src/types/typeStrings/typeString_parser.ts", "src/compile/inference/file_level_definitions_parser_header.ts", - "src/compile/inference/file_level_definitions_parser.ts" + "src/compile/inference/file_level_definitions_parser.ts", + "test/utils/typeStrings/typeString_parser_header.ts", + "test/utils/typeStrings/typeString_parser.ts" ] } diff --git a/.gitignore b/.gitignore index 943d83bd..199c8328 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ dist docs coverage *.tgz -src/types/typeStrings/typeString_parser.ts src/compile/inference/file_level_definitions_parser.ts +test/utils/typeStrings/typeString_parser.ts diff --git a/.nycrc.json b/.nycrc.json index cf5ecba0..79af7b85 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -7,7 +7,6 @@ "**/coverage/**", "**/docs/**", "**/.compiler_cache/**", - "src/types/typeStrings/typeString_parser*.ts", "src/compile/inference/file_level_definitions_parser*.ts" ], "reporter": ["lcov", "text-summary"], diff --git a/package-lock.json b/package-lock.json index 03763214..6fb2255a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "10.3.0", "license": "Apache-2.0", "dependencies": { - "axios": "^1.1.0", + "axios": "^1.1.3", "commander": "^9.4.1", - "decimal.js": "^10.4.1", + "decimal.js": "^10.4.2", "findup-sync": "^5.0.0", "fs-extra": "^10.1.0", "jsel": "^1.1.6", @@ -26,21 +26,21 @@ "devDependencies": { "@types/fs-extra": "^9.0.13", "@types/mocha": "^10.0.0", - "@types/node": "^16.11.64", + "@types/node": "^16.18.0", "@types/semver": "^7.3.12", - "@typescript-eslint/eslint-plugin": "^5.39.0", - "@typescript-eslint/parser": "^5.39.0", - "eslint": "^8.24.0", + "@typescript-eslint/eslint-plugin": "^5.40.1", + "@typescript-eslint/parser": "^5.40.1", + "eslint": "^8.26.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", - "expect": "^29.1.2", - "mocha": "^10.0.0", + "expect": "^29.2.1", + "mocha": "^10.1.0", "nyc": "^15.1.0", "peggy": "^2.0.1", "prettier": "2.7.1", "ts-node": "^10.9.1", "ts-pegjs": "^2.1.0", - "typedoc": "^0.23.15", + "typedoc": "^0.23.18", "typescript": "^4.8.4" } }, @@ -470,9 +470,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -866,9 +866,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", + "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -879,16 +879,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1017,12 +1007,12 @@ } }, "node_modules/@jest/expect-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", - "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.1.tgz", + "integrity": "sha512-yr4aHNg5Z1CjKby5ozm7sKjgBlCOorlAoFcvrOQ/4rbZRfgZQdnmh7cth192PYIgiPZo2bBXvqdOApnAMWFJZg==", "dev": true, "dependencies": { - "jest-get-type": "^29.0.0" + "jest-get-type": "^29.2.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -1041,9 +1031,9 @@ } }, "node_modules/@jest/types": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", - "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.1.tgz", + "integrity": "sha512-O/QNDQODLnINEPAI0cl9U6zUIDXEWXt6IC1o2N2QENuos7hlGUIthlKyV4p6ki3TvXFX071blj8HUhgLGquPjw==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -1140,9 +1130,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.24.44", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz", - "integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg==", + "version": "0.24.50", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.50.tgz", + "integrity": "sha512-k8ETQOOQDg5FtK7y9KJWpsGLik+QlPmIi8zzl/dGUgshV2QitprkFlCR/AemjWOTyKn9UwSSGRTzLVotvgCjYQ==", "dev": true }, "node_modules/@tsconfig/node10": { @@ -1223,9 +1213,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.11.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.64.tgz", - "integrity": "sha512-z5hPTlVFzNwtJ2LNozTpJcD1Cu44c4LNuzaq1mwxmiHWQh2ULdR6Vjwo1UGldzRpzL0yUEdZddnfqGW2G70z6Q==" + "version": "16.18.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.0.tgz", + "integrity": "sha512-LqYqYzYvnbCaQfLAwRt0zboqnsViwhZm+vjaMSqcfN36vulAg7Pt0T83q4WZO2YOBw3XdyHi8cQ88H22zmULOA==" }, "node_modules/@types/pbkdf2": { "version": "3.1.0", @@ -1271,14 +1261,14 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.39.0.tgz", - "integrity": "sha512-xVfKOkBm5iWMNGKQ2fwX5GVgBuHmZBO1tCRwXmY5oAIsPscfwm2UADDuNB8ZVYCtpQvJK4xpjrK7jEhcJ0zY9A==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", + "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/type-utils": "5.39.0", - "@typescript-eslint/utils": "5.39.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/type-utils": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -1303,14 +1293,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.39.0.tgz", - "integrity": "sha512-PhxLjrZnHShe431sBAGHaNe6BDdxAASDySgsBCGxcBecVCi8NQWxQZMcizNA4g0pN51bBAn/FUfkWG3SDVcGlA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", + "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "debug": "^4.3.4" }, "engines": { @@ -1330,13 +1320,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.39.0.tgz", - "integrity": "sha512-/I13vAqmG3dyqMVSZPjsbuNQlYS082Y7OMkwhCfLXYsmlI0ca4nkL7wJ/4gjX70LD4P8Hnw1JywUVVAwepURBw==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", + "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0" + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1347,13 +1337,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.39.0.tgz", - "integrity": "sha512-KJHJkOothljQWzR3t/GunL0TPKY+fGJtnpl+pX+sJ0YiKTz3q2Zr87SGTmFqsCMFrLt5E0+o+S6eQY0FAXj9uA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", + "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.39.0", - "@typescript-eslint/utils": "5.39.0", + "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1374,9 +1364,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.39.0.tgz", - "integrity": "sha512-gQMZrnfEBFXK38hYqt8Lkwt8f4U6yq+2H5VDSgP/qiTzC8Nw8JO3OuSUOQ2qW37S/dlwdkHDntkZM6SQhKyPhw==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", + "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1387,13 +1377,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.39.0.tgz", - "integrity": "sha512-qLFQP0f398sdnogJoLtd43pUgB18Q50QSA+BTE5h3sUxySzbWDpTSdgt4UyxNSozY/oDK2ta6HVAzvGgq8JYnA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", + "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1414,17 +1404,19 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.39.0.tgz", - "integrity": "sha512-+DnY5jkpOpgj+EBtYPyHRjXampJfC0yUZZzfzLuUWVZvCuKqSdJVC8UhdWipIw7VKNTfwfAPiOWzYkAwuIhiAg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", + "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1438,12 +1430,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.39.0.tgz", - "integrity": "sha512-yyE3RPwOG+XJBLrhvsxAidUgybJVQ/hG8BhiJo0k8JSAYfk/CshVcxf0HwP4Jt7WZZ6vLmxdo1p6EyN3tzFTkg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", + "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.39.0", + "@typescript-eslint/types": "5.40.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1454,12 +1446,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -1610,9 +1596,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.0.tgz", - "integrity": "sha512-hsJgcqz4JY7f+HZ4cWTrPZ6tZNCNFPTRx1MjRqu/hbpgpHdSCUpLVuplc+jE/h7dOvyANtw/ERA3HC2Rz/QoMg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", + "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -1853,9 +1839,9 @@ } }, "node_modules/ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, "node_modules/cipher-base": { @@ -2022,9 +2008,9 @@ } }, "node_modules/decimal.js": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" }, "node_modules/deep-is": { "version": "0.1.4", @@ -2070,9 +2056,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", - "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz", + "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2161,15 +2147,15 @@ } }, "node_modules/eslint": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", - "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2185,14 +2171,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -2494,16 +2480,16 @@ } }, "node_modules/expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.1.tgz", + "integrity": "sha512-BJtA754Fba0YWRWHgjKUMTA3ltWarKgITXHQnbZ2mTxTXC4yMQlR0FI7HkB3fJYkhWBf4qjNiqvg3LDtXCcVRQ==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2" + "@jest/expect-utils": "^29.2.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.2.1", + "jest-message-util": "^29.2.1", + "jest-util": "^29.2.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2522,9 +2508,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3127,6 +3113,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -3283,57 +3278,57 @@ } }, "node_modules/jest-diff": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", - "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.1.tgz", + "integrity": "sha512-gfh/SMNlQmP3MOUgdzxPOd4XETDJifADpT937fN1iUGz+9DgOu2eUPHH25JDkLVcLwwqxv3GzVyK4VBUr9fjfA==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.0.0", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "diff-sequences": "^29.2.0", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.2.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", - "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.1.tgz", + "integrity": "sha512-hUTBh7H/Mnb6GTpihbLh8uF5rjAMdekfW/oZNXUMAXi7bbmym2HiRpzgqf/zzkjgejMrVAkPdVSQj+32enlUww==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-diff": "^29.2.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.2.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", - "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz", + "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.1.2", + "@jest/types": "^29.2.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.2.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3342,12 +3337,12 @@ } }, "node_modules/jest-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", - "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz", + "integrity": "sha512-P5VWDj25r7kj7kl4pN2rG/RN2c1TLfYYYZYULnS/35nFDjBai+hBeo3MDrYZS7p6IoY3YHZnt2vq4L6mKnLk0g==", "dev": true, "dependencies": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.2.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3658,12 +3653,11 @@ } }, "node_modules/mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "dependencies": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -4297,9 +4291,9 @@ } }, "node_modules/pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz", + "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==", "dev": true, "dependencies": { "@jest/schemas": "^29.0.0", @@ -5023,9 +5017,9 @@ } }, "node_modules/typedoc": { - "version": "0.23.15", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.15.tgz", - "integrity": "sha512-x9Zu+tTnwxb9YdVr+zvX7LYzyBl1nieOr6lrSHbHsA22/RJK2m4Y525WIg5Mj4jWCmfL47v6f4hUzY7EIuwS5w==", + "version": "0.23.18", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.18.tgz", + "integrity": "sha512-0Tq/uFkUuWyRYyjOShTkhsOm6u5E8wf0i6L76/k5znEaxvWKHGeT2ywZThGrDrryV/skO/REM824D1gm8ccQuA==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -5695,9 +5689,9 @@ } }, "@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -5905,9 +5899,9 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.6.tgz", + "integrity": "sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -5915,12 +5909,6 @@ "minimatch": "^3.0.4" } }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true - }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -6017,12 +6005,12 @@ "dev": true }, "@jest/expect-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.1.2.tgz", - "integrity": "sha512-4a48bhKfGj/KAH39u0ppzNTABXQ8QPccWAFUFobWBaEMSMp+sB31Z2fK/l47c4a/Mu1po2ffmfAIPxXbVTXdtg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.1.tgz", + "integrity": "sha512-yr4aHNg5Z1CjKby5ozm7sKjgBlCOorlAoFcvrOQ/4rbZRfgZQdnmh7cth192PYIgiPZo2bBXvqdOApnAMWFJZg==", "dev": true, "requires": { - "jest-get-type": "^29.0.0" + "jest-get-type": "^29.2.0" } }, "@jest/schemas": { @@ -6035,9 +6023,9 @@ } }, "@jest/types": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.1.2.tgz", - "integrity": "sha512-DcXGtoTykQB5jiwCmVr8H4vdg2OJhQex3qPkG+ISyDO7xQXbt/4R6dowcRyPemRnkH7JoHvZuxPBdlq+9JxFCg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.1.tgz", + "integrity": "sha512-O/QNDQODLnINEPAI0cl9U6zUIDXEWXt6IC1o2N2QENuos7hlGUIthlKyV4p6ki3TvXFX071blj8HUhgLGquPjw==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -6113,9 +6101,9 @@ } }, "@sinclair/typebox": { - "version": "0.24.44", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.44.tgz", - "integrity": "sha512-ka0W0KN5i6LfrSocduwliMMpqVgohtPFidKdMEOUjoOFCHcOOYkKsPRxfs5f15oPNHTm6ERAm0GV/+/LTKeiWg==", + "version": "0.24.50", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.50.tgz", + "integrity": "sha512-k8ETQOOQDg5FtK7y9KJWpsGLik+QlPmIi8zzl/dGUgshV2QitprkFlCR/AemjWOTyKn9UwSSGRTzLVotvgCjYQ==", "dev": true }, "@tsconfig/node10": { @@ -6196,9 +6184,9 @@ "dev": true }, "@types/node": { - "version": "16.11.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.64.tgz", - "integrity": "sha512-z5hPTlVFzNwtJ2LNozTpJcD1Cu44c4LNuzaq1mwxmiHWQh2ULdR6Vjwo1UGldzRpzL0yUEdZddnfqGW2G70z6Q==" + "version": "16.18.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.0.tgz", + "integrity": "sha512-LqYqYzYvnbCaQfLAwRt0zboqnsViwhZm+vjaMSqcfN36vulAg7Pt0T83q4WZO2YOBw3XdyHi8cQ88H22zmULOA==" }, "@types/pbkdf2": { "version": "3.1.0", @@ -6244,14 +6232,14 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.39.0.tgz", - "integrity": "sha512-xVfKOkBm5iWMNGKQ2fwX5GVgBuHmZBO1tCRwXmY5oAIsPscfwm2UADDuNB8ZVYCtpQvJK4xpjrK7jEhcJ0zY9A==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", + "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/type-utils": "5.39.0", - "@typescript-eslint/utils": "5.39.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/type-utils": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -6260,53 +6248,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.39.0.tgz", - "integrity": "sha512-PhxLjrZnHShe431sBAGHaNe6BDdxAASDySgsBCGxcBecVCi8NQWxQZMcizNA4g0pN51bBAn/FUfkWG3SDVcGlA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", + "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.39.0.tgz", - "integrity": "sha512-/I13vAqmG3dyqMVSZPjsbuNQlYS082Y7OMkwhCfLXYsmlI0ca4nkL7wJ/4gjX70LD4P8Hnw1JywUVVAwepURBw==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", + "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0" + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1" } }, "@typescript-eslint/type-utils": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.39.0.tgz", - "integrity": "sha512-KJHJkOothljQWzR3t/GunL0TPKY+fGJtnpl+pX+sJ0YiKTz3q2Zr87SGTmFqsCMFrLt5E0+o+S6eQY0FAXj9uA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", + "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.39.0", - "@typescript-eslint/utils": "5.39.0", + "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.39.0.tgz", - "integrity": "sha512-gQMZrnfEBFXK38hYqt8Lkwt8f4U6yq+2H5VDSgP/qiTzC8Nw8JO3OuSUOQ2qW37S/dlwdkHDntkZM6SQhKyPhw==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", + "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.39.0.tgz", - "integrity": "sha512-qLFQP0f398sdnogJoLtd43pUgB18Q50QSA+BTE5h3sUxySzbWDpTSdgt4UyxNSozY/oDK2ta6HVAzvGgq8JYnA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", + "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/visitor-keys": "5.39.0", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -6315,35 +6303,31 @@ } }, "@typescript-eslint/utils": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.39.0.tgz", - "integrity": "sha512-+DnY5jkpOpgj+EBtYPyHRjXampJfC0yUZZzfzLuUWVZvCuKqSdJVC8UhdWipIw7VKNTfwfAPiOWzYkAwuIhiAg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", + "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.39.0", - "@typescript-eslint/types": "5.39.0", - "@typescript-eslint/typescript-estree": "5.39.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.39.0.tgz", - "integrity": "sha512-yyE3RPwOG+XJBLrhvsxAidUgybJVQ/hG8BhiJo0k8JSAYfk/CshVcxf0HwP4Jt7WZZ6vLmxdo1p6EyN3tzFTkg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", + "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.39.0", + "@typescript-eslint/types": "5.40.1", "eslint-visitor-keys": "^3.3.0" } }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -6455,9 +6439,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.0.tgz", - "integrity": "sha512-hsJgcqz4JY7f+HZ4cWTrPZ6tZNCNFPTRx1MjRqu/hbpgpHdSCUpLVuplc+jE/h7dOvyANtw/ERA3HC2Rz/QoMg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", + "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6639,9 +6623,9 @@ } }, "ci-info": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, "cipher-base": { @@ -6782,9 +6766,9 @@ "dev": true }, "decimal.js": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz", - "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==" + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", + "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" }, "deep-is": { "version": "0.1.4", @@ -6818,9 +6802,9 @@ "dev": true }, "diff-sequences": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.0.0.tgz", - "integrity": "sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz", + "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==", "dev": true }, "dir-glob": { @@ -6893,15 +6877,15 @@ "dev": true }, "eslint": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", - "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -6917,14 +6901,14 @@ "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", + "glob-parent": "^6.0.2", "globals": "^13.15.0", - "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -7145,16 +7129,16 @@ } }, "expect": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.1.2.tgz", - "integrity": "sha512-AuAGn1uxva5YBbBlXb+2JPxJRuemZsmlGcapPXWNSBNsQtAULfjioREGBWuI0EOvYUKjDnrCy8PW5Zlr1md5mw==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.1.tgz", + "integrity": "sha512-BJtA754Fba0YWRWHgjKUMTA3ltWarKgITXHQnbZ2mTxTXC4yMQlR0FI7HkB3fJYkhWBf4qjNiqvg3LDtXCcVRQ==", "dev": true, "requires": { - "@jest/expect-utils": "^29.1.2", - "jest-get-type": "^29.0.0", - "jest-matcher-utils": "^29.1.2", - "jest-message-util": "^29.1.2", - "jest-util": "^29.1.2" + "@jest/expect-utils": "^29.2.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.2.1", + "jest-message-util": "^29.2.1", + "jest-util": "^29.2.1" } }, "fast-deep-equal": { @@ -7170,9 +7154,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -7605,6 +7589,12 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -7721,59 +7711,59 @@ } }, "jest-diff": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.1.2.tgz", - "integrity": "sha512-4GQts0aUopVvecIT4IwD/7xsBaMhKTYoM4/njE/aVw9wpw+pIUVp8Vab/KnSzSilr84GnLBkaP3JLDnQYCKqVQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.1.tgz", + "integrity": "sha512-gfh/SMNlQmP3MOUgdzxPOd4XETDJifADpT937fN1iUGz+9DgOu2eUPHH25JDkLVcLwwqxv3GzVyK4VBUr9fjfA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.0.0", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "diff-sequences": "^29.2.0", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.2.1" } }, "jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true }, "jest-matcher-utils": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.1.2.tgz", - "integrity": "sha512-MV5XrD3qYSW2zZSHRRceFzqJ39B2z11Qv0KPyZYxnzDHFeYZGJlgGi0SW+IXSJfOewgJp/Km/7lpcFT+cgZypw==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.1.tgz", + "integrity": "sha512-hUTBh7H/Mnb6GTpihbLh8uF5rjAMdekfW/oZNXUMAXi7bbmym2HiRpzgqf/zzkjgejMrVAkPdVSQj+32enlUww==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.1.2", - "jest-get-type": "^29.0.0", - "pretty-format": "^29.1.2" + "jest-diff": "^29.2.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.2.1" } }, "jest-message-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.1.2.tgz", - "integrity": "sha512-9oJ2Os+Qh6IlxLpmvshVbGUiSkZVc2FK+uGOm6tghafnB2RyjKAxMZhtxThRMxfX1J1SOMhTn9oK3/MutRWQJQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz", + "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.1.2", + "@jest/types": "^29.2.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.1.2", + "pretty-format": "^29.2.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-util": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.1.2.tgz", - "integrity": "sha512-vPCk9F353i0Ymx3WQq3+a4lZ07NXu9Ca8wya6o4Fe4/aO1e1awMMprZ3woPFpKwghEOW+UXgd15vVotuNN9ONQ==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz", + "integrity": "sha512-P5VWDj25r7kj7kl4pN2rG/RN2c1TLfYYYZYULnS/35nFDjBai+hBeo3MDrYZS7p6IoY3YHZnt2vq4L6mKnLk0g==", "dev": true, "requires": { - "@jest/types": "^29.1.2", + "@jest/types": "^29.2.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -8008,12 +7998,11 @@ } }, "mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "requires": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -8488,9 +8477,9 @@ } }, "pretty-format": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.1.2.tgz", - "integrity": "sha512-CGJ6VVGXVRP2o2Dorl4mAwwvDWT25luIsYhkyVQW32E4nL+TgW939J7LlKT/npq5Cpq6j3s+sy+13yk7xYpBmg==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz", + "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==", "dev": true, "requires": { "@jest/schemas": "^29.0.0", @@ -9002,9 +8991,9 @@ } }, "typedoc": { - "version": "0.23.15", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.15.tgz", - "integrity": "sha512-x9Zu+tTnwxb9YdVr+zvX7LYzyBl1nieOr6lrSHbHsA22/RJK2m4Y525WIg5Mj4jWCmfL47v6f4hUzY7EIuwS5w==", + "version": "0.23.18", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.18.tgz", + "integrity": "sha512-0Tq/uFkUuWyRYyjOShTkhsOm6u5E8wf0i6L76/k5znEaxvWKHGeT2ywZThGrDrryV/skO/REM824D1gm8ccQuA==", "dev": true, "requires": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index 5be9c248..29ca7c42 100644 --- a/package.json +++ b/package.json @@ -12,15 +12,14 @@ "sol-ast-compile": "dist/bin/compile.js" }, "scripts": { - "clean": "rm -rf dist/ src/ast/typestrings/typeString_parser.ts src/compile/inference/file_level_definitions_parser.ts", + "clean": "rm -rf dist/ src/compile/inference/file_level_definitions_parser.ts test/utils/typeStrings/typeString_parser.ts", "transpile": "tsc", - "build-type-parser": "tspegjs -o src/types/typeStrings/typeString_parser.ts --custom-header-file src/types/typeStrings/typeString_parser_header.ts --cache src/types/typeStrings/typeString_grammar.pegjs", + "build-type-parser": "tspegjs -o test/utils/typeStrings/typeString_parser.ts --custom-header-file test/utils/typeStrings/typeString_parser_header.ts --cache test/utils/typeStrings/typeString_grammar.pegjs", "build-file-level-definitions-parser": "tspegjs -o src/compile/inference/file_level_definitions_parser.ts --custom-header-file src/compile/inference/file_level_definitions_parser_header.ts --cache src/compile/inference/file_level_definitions.pegjs", - "build-parsers": "npm run build-type-parser && npm run build-file-level-definitions-parser", - "build": "npm run clean && npm run build-parsers && npm run transpile && chmod u+x dist/bin/compile.js", + "build": "npm run clean && npm run build-file-level-definitions-parser && npm run transpile && chmod u+x dist/bin/compile.js", "lint": "eslint src/ test/ --ext=ts", "lint:fix": "eslint src/ test/ --ext=ts --fix", - "test": "NODE_OPTIONS='--max-old-space-size=2048' nyc mocha", + "test": "npm run build-type-parser && NODE_OPTIONS='--max-old-space-size=2048' nyc mocha", "coverage": "nyc report", "docs:render": "typedoc", "docs:clear": "rm -rf docs/", @@ -28,7 +27,7 @@ "prepare": "npm run build" }, "dependencies": { - "axios": "^1.1.0", + "axios": "^1.1.3", "commander": "^9.4.1", "findup-sync": "^5.0.0", "fs-extra": "^10.1.0", @@ -37,26 +36,26 @@ "solc": "^0.8.17", "src-location": "^1.1.0", "web3-eth-abi": "^1.8.0", - "decimal.js": "^10.4.1" + "decimal.js": "^10.4.2" }, "devDependencies": { "@types/fs-extra": "^9.0.13", "@types/mocha": "^10.0.0", - "@types/node": "^16.11.64", + "@types/node": "^16.18.0", "@types/semver": "^7.3.12", - "@typescript-eslint/eslint-plugin": "^5.39.0", - "@typescript-eslint/parser": "^5.39.0", - "eslint": "^8.24.0", + "@typescript-eslint/eslint-plugin": "^5.40.1", + "@typescript-eslint/parser": "^5.40.1", + "eslint": "^8.26.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", - "expect": "^29.1.2", - "mocha": "^10.0.0", + "expect": "^29.2.1", + "mocha": "^10.1.0", "nyc": "^15.1.0", "peggy": "^2.0.1", "prettier": "2.7.1", "ts-node": "^10.9.1", "ts-pegjs": "^2.1.0", - "typedoc": "^0.23.15", + "typedoc": "^0.23.18", "typescript": "^4.8.4" }, "homepage": "https://consensys.github.io/solc-typed-ast", diff --git a/src/ast/definitions.ts b/src/ast/definitions.ts index 6d57aa26..282c022d 100644 --- a/src/ast/definitions.ts +++ b/src/ast/definitions.ts @@ -1,7 +1,7 @@ import { gte, lt } from "semver"; import { FunctionVisibility } from "."; -import { forAll, pp } from "../misc"; -import { ABIEncoderVersion } from "../types/abi"; +import { assert, forAll, pp } from "../misc"; +import { ABIEncoderVersion, InferType } from "../types"; import { ASTNode } from "./ast_node"; import { StateVariableVisibility } from "./constants"; import { ContractDefinition } from "./implementation/declaration/contract_definition"; @@ -115,8 +115,10 @@ function getContainingScope(node: ASTNode, version: string): ScopeNode | undefin if (pt instanceof Block || pt instanceof UncheckedBlock) { if (gte(version, "0.5.0")) { const ptChildren = pt.children; + for (let i = ptChildren.indexOf(node) - 1; i >= 0; i--) { const sibling = ptChildren[i]; + if (sibling instanceof VariableDeclarationStatement) { return sibling; } @@ -135,6 +137,7 @@ function getContainingScope(node: ASTNode, version: string): ScopeNode | undefin */ function* lookupInSourceUnit( name: string, + inference: InferType, scope: SourceUnit, visitedUnits: Set ): Iterable { @@ -170,7 +173,7 @@ function* lookupInSourceUnit( } else if (child.vSymbolAliases.length === 0) { // import "..." // @todo maybe its better to go through child.vSourceUnit.vExportedSymbols here? - yield* lookupInScope(name, child.vSourceUnit, visitedUnits, false); + yield* lookupInScope(name, child.vSourceUnit, inference, visitedUnits, false); } else { // `import {} from "..."` or `import {a as } from "..."` for (const [foreignDef, alias] of child.vSymbolAliases) { @@ -182,13 +185,11 @@ function* lookupInSourceUnit( if (foreignDef instanceof ImportDirective) { symImportName = foreignDef.unitAlias; - if (symImportName === "") { - throw new Error( - `Unexpected ImportDirective foreign def with non-unit alias ${pp( - foreignDef - )}` - ); - } + assert( + symImportName !== "", + "Unexpected ImportDirective foreign def with non-unit alias {0}", + foreignDef + ); } else { symImportName = foreignDef.name; } @@ -208,6 +209,7 @@ function* lookupInSourceUnit( */ function* lookupInContractDefinition( name: string, + inference: InferType, scope: ContractDefinition, ignoreVisiblity: boolean ): Iterable { @@ -239,22 +241,16 @@ function* lookupInContractDefinition( continue; } - let sigHash: string | undefined; - - if (child instanceof FunctionDefinition) { - // Its a safe to assume V2 as its backward-compatible and - // we only use it internally here - sigHash = child.canonicalSignatureHash(ABIEncoderVersion.V2); - } else if ( - child instanceof VariableDeclaration && - child.visibility === StateVariableVisibility.Public - ) { - // Its a safe to assume V2 as its backward-compatible and - // we only use it internally here - sigHash = child.getterCanonicalSignatureHash(ABIEncoderVersion.V2); - } else if (child instanceof EventDefinition) { - sigHash = child.canonicalSignatureHash(ABIEncoderVersion.V2); - } + /** + * Its a safe to assume V2 as its backward-compatible and we only use it internally here + */ + const sigHash = + child instanceof FunctionDefinition || + child instanceof EventDefinition || + (child instanceof VariableDeclaration && + child.visibility === StateVariableVisibility.Public) + ? inference.signatureHash(child, ABIEncoderVersion.V2) + : undefined; if (sigHash !== undefined) { if (overridenSigHashes.has(sigHash)) { @@ -292,10 +288,11 @@ function* lookupInFunctionDefinition( function* lookupInBlock( name: string, scope: Block | UncheckedBlock, - version: string + inference: InferType ): Iterable { let declarations: VariableDeclaration[]; - if (version && lt(version, "0.5.0")) { + + if (lt(inference.version, "0.5.0")) { declarations = scope.getChildrenByType(VariableDeclaration); } else { declarations = scope.children @@ -324,16 +321,16 @@ function* lookupInBlock( function lookupInScope( name: string, scope: ScopeNode, + inference: InferType, visitedUnits = new Set(), - ignoreVisiblity: boolean, - version = "" + ignoreVisiblity: boolean ): Set { let results: Iterable; if (scope instanceof SourceUnit) { - results = lookupInSourceUnit(name, scope, visitedUnits); + results = lookupInSourceUnit(name, inference, scope, visitedUnits); } else if (scope instanceof ContractDefinition) { - results = lookupInContractDefinition(name, scope, ignoreVisiblity); + results = lookupInContractDefinition(name, inference, scope, ignoreVisiblity); } else if (scope instanceof FunctionDefinition) { results = lookupInFunctionDefinition(name, scope); } else if (scope instanceof ModifierDefinition) { @@ -341,7 +338,7 @@ function lookupInScope( } else if (scope instanceof VariableDeclarationStatement) { results = scope.vDeclarations.filter((decl) => decl.name === name); } else if (scope instanceof Block || scope instanceof UncheckedBlock) { - results = lookupInBlock(name, scope, version); + results = lookupInBlock(name, scope, inference); } else if (scope instanceof TryCatchClause) { results = scope.vParameters ? scope.vParameters.vParameters.filter((param) => param.name === name) @@ -371,12 +368,14 @@ function lookupInScope( export function resolveAny( name: string, ctx: ASTNode, - version: string, + inference: InferType, inclusive = false, ignoreVisiblity = false ): Set { let scope: ScopeNode | undefined = - inclusive && isScope(ctx, version) ? ctx : getContainingScope(ctx, version); + inclusive && isScope(ctx, inference.version) + ? ctx + : getContainingScope(ctx, inference.version); const elements = name.split("."); @@ -389,14 +388,14 @@ export function resolveAny( // If this is the first element (e.g. `A` in `A.B.C`), walk up the // stack of scopes starting from the current context, looking for `A` while (scope !== undefined) { - res = lookupInScope(element, scope, undefined, ignoreVisiblity, version); + res = lookupInScope(element, scope, inference, undefined, ignoreVisiblity); if (res.size > 0) { // Sanity check - when multiple results are found, they must either be overloaded events // or overloaded functions/public state vars. if (res.size > 1) { - if ( - !forAll( + assert( + forAll( res, (def) => def instanceof EventDefinition || @@ -404,14 +403,12 @@ export function resolveAny( (def instanceof VariableDeclaration && def.stateVariable && def.visibility === StateVariableVisibility.Public) - ) - ) { - throw new Error( - `Unexpected intermediate def for ${element} in ${name}: ${[ - ...res - ].map((n) => `${n.constructor.name}#${n.id}`)}` - ); - } + ), + "Unexpected intermediate def for {0} in {1}: {2}", + element, + name, + res + ); } const first = [...res][0]; @@ -428,12 +425,12 @@ export function resolveAny( } } - scope = getContainingScope(scope, version); + scope = getContainingScope(scope, inference.version); } } else { // If this is a later segment (e.g. `B` or `C` in `A.B.C`), // then resolve it recursively in the current scope. - res = resolveAny(element, scope as ASTNode, version, true, ignoreVisiblity); + res = resolveAny(element, scope as ASTNode, inference, true, ignoreVisiblity); } // We didn't find anything - return empty set @@ -449,29 +446,27 @@ export function resolveAny( // We found multiple definitions for an intermediate segment of // identifier path (e.g. multiple resolutions for `A` in `A.B`). This // shouldn't happen. - if (res.size > 1) { - throw new Error( - `Ambigious path resolution for ${element} in ${name} in ctx ${pp(ctx)}: got ${[ - ...res - ] - .map(pp) - .join(",")}` - ); - } + assert( + res.size === 1, + "Ambigious path resolution for {0} in {1} in ctx {2}: got {3}", + element, + name, + ctx, + res + ); const resolvedNode = [...res][0]; // An intermediate segment in an identifier path (e.g. `A` in `A.B`) should always resolve to a // single imported source unit or contract. - if ( - !(resolvedNode instanceof ImportDirective || resolvedNode instanceof ContractDefinition) - ) { - throw new Error( - `Unexpected non-scope node for ${element} in ${name} in ctx ${pp(ctx)}: got ${pp( - resolvedNode - )}` - ); - } + assert( + resolvedNode instanceof ImportDirective || resolvedNode instanceof ContractDefinition, + "Unexpected non-scope node for {0} in {1} in ctx {2}: got {3}", + element, + name, + ctx, + resolvedNode + ); scope = resolvedNode instanceof ImportDirective ? resolvedNode.vSourceUnit : resolvedNode; } diff --git a/src/ast/dispatch.ts b/src/ast/dispatch.ts index 9b91d474..a429f328 100644 --- a/src/ast/dispatch.ts +++ b/src/ast/dispatch.ts @@ -1,4 +1,4 @@ -import { ABIEncoderVersion } from "../types/abi"; +import { ABIEncoderVersion, InferType } from "../types"; import { ASTNodeConstructor } from "./ast_node"; import { StateVariableVisibility } from "./constants"; import { ContractDefinition } from "./implementation/declaration/contract_definition"; @@ -14,32 +14,33 @@ import { EmitStatement } from "./implementation/statement/emit_statement"; type FunctionLikeResolvable = FunctionDefinition | ModifierDefinition | EventDefinition; type Resolvable = FunctionLikeResolvable | VariableDeclaration; -function getResolvableCollection( +function getResolvableCollection( contract: ContractDefinition, - target: ASTNodeConstructor + target: ASTNodeConstructor ): readonly Resolvable[] { - let collection: readonly Resolvable[]; - if (target === FunctionDefinition) { - collection = contract.vFunctions; - } else if (target === ModifierDefinition) { - collection = contract.vModifiers; - } else if (target === EventDefinition) { - collection = contract.vEvents; - } else if (target === VariableDeclaration) { - collection = contract.vStateVariables; - } else { - throw new Error( - "Unable to select resolvable collection for target " + target.constructor.name - ); + return contract.vFunctions; + } + + if (target === ModifierDefinition) { + return contract.vModifiers; } - return collection; + if (target === EventDefinition) { + return contract.vEvents; + } + + if (target === VariableDeclaration) { + return contract.vStateVariables; + } + + throw new Error("Unable to select resolvable collection for target " + target.name); } export function resolve( scope: ContractDefinition, target: T, + inference: InferType, onlyParents = false ): T | undefined { let finder: (candidate: Resolvable) => boolean; @@ -47,13 +48,10 @@ export function resolve( if (target instanceof VariableDeclaration) { finder = (candidate) => candidate.name === target.name; } else { - const signatureHash = (target as FunctionLikeResolvable).canonicalSignatureHash( - ABIEncoderVersion.V2 - ); + const signatureHash = inference.signatureHash(target, ABIEncoderVersion.V2); finder = (candidate) => - signatureHash === - (candidate as FunctionLikeResolvable).canonicalSignatureHash(ABIEncoderVersion.V2); + signatureHash === inference.signatureHash(candidate, ABIEncoderVersion.V2); } for (const base of scope.vLinearizedBaseContracts) { @@ -91,6 +89,7 @@ export function resolveByName( scope: ContractDefinition, constructor: ASTNodeConstructor, name: string, + inference: InferType, onlyParents = false ): T[] { const result = []; @@ -113,7 +112,7 @@ export function resolveByName( const resolvableIdentifier = resolvable instanceof VariableDeclaration ? resolvable.name - : resolvable.canonicalSignatureHash(ABIEncoderVersion.V2); + : inference.signatureHash(resolvable, ABIEncoderVersion.V2); if (resolvable.name === name && !found.has(resolvableIdentifier)) { result.push(resolvable as T); @@ -144,13 +143,16 @@ function isExplicitlyBound(call: FunctionCall): boolean { export function resolveEvent( scope: ContractDefinition, statement: EmitStatement, + inference: InferType, onlyParents = false ): EventDefinition | undefined { const call = statement.vEventCall; const definition = call.vReferencedDeclaration; if (definition instanceof EventDefinition) { - return isExplicitlyBound(call) ? definition : resolve(scope, definition, onlyParents); + return isExplicitlyBound(call) + ? definition + : resolve(scope, definition, inference, onlyParents); } return undefined; @@ -159,12 +161,10 @@ export function resolveEvent( export function resolveCallable( scope: ContractDefinition, definition: FunctionDefinition | VariableDeclaration, + inference: InferType, onlyParents = false ): FunctionDefinition | VariableDeclaration | undefined { - const selector = - definition instanceof FunctionDefinition - ? definition.canonicalSignatureHash(ABIEncoderVersion.V2) - : definition.getterCanonicalSignatureHash(ABIEncoderVersion.V2); + const selector = inference.signatureHash(definition, ABIEncoderVersion.V2); for (const base of scope.vLinearizedBaseContracts) { if (onlyParents && base === scope) { @@ -172,14 +172,14 @@ export function resolveCallable( } for (const fn of base.vFunctions) { - if (fn.canonicalSignatureHash(ABIEncoderVersion.V2) === selector) { + if (inference.signatureHash(fn, ABIEncoderVersion.V2) === selector) { return fn; } } for (const v of base.vStateVariables) { if (v.visibility === StateVariableVisibility.Public) { - if (v.getterCanonicalSignatureHash(ABIEncoderVersion.V2) === selector) { + if (inference.signatureHash(v, ABIEncoderVersion.V2) === selector) { return v; } } diff --git a/src/ast/implementation/declaration/contract_definition.ts b/src/ast/implementation/declaration/contract_definition.ts index 5fa034ea..876bdfc5 100644 --- a/src/ast/implementation/declaration/contract_definition.ts +++ b/src/ast/implementation/declaration/contract_definition.ts @@ -1,6 +1,5 @@ -import { ABIEncoderVersion } from "../../../types/abi"; import { ASTNode, ASTNodeWithChildren } from "../../ast_node"; -import { ContractKind, StateVariableVisibility } from "../../constants"; +import { ContractKind } from "../../constants"; import { getDanglingDocumentation, getDocumentation, @@ -271,37 +270,6 @@ export class ContractDefinition return this.vFunctions.find((fn) => fn.isConstructor); } - interfaceId(encoderVersion: ABIEncoderVersion): string | undefined { - if ( - this.kind === ContractKind.Interface || - (this.kind === ContractKind.Contract && this.abstract) - ) { - const selectors: string[] = []; - - for (const fn of this.vFunctions) { - const hash = fn.canonicalSignatureHash(encoderVersion); - - if (hash) { - selectors.push(hash); - } - } - - for (const v of this.vStateVariables) { - if (v.visibility === StateVariableVisibility.Public) { - selectors.push(v.getterCanonicalSignatureHash(encoderVersion)); - } - } - - return selectors - .map((selector) => BigInt("0x" + selector)) - .reduce((a, b) => a ^ b, 0n) - .toString(16) - .padStart(8, "0"); - } - - return undefined; - } - /** * Returns `true` if `other` contract is present in the inheritance chain * of the current contract. Returns `false` otherwise. diff --git a/src/ast/implementation/declaration/error_definition.ts b/src/ast/implementation/declaration/error_definition.ts index 0095add2..085384d6 100644 --- a/src/ast/implementation/declaration/error_definition.ts +++ b/src/ast/implementation/declaration/error_definition.ts @@ -1,6 +1,4 @@ -import { ABIEncoderVersion } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; -import { encodeFuncSignature } from "../../utils"; import { SourceUnit } from "../meta"; import { ParameterList } from "../meta/parameter_list"; import { StructuredDocumentation } from "../meta/structured_documentation"; @@ -61,27 +59,4 @@ export class ErrorDefinition extends ASTNode { get vScope(): ContractDefinition | SourceUnit { return this.parent as ContractDefinition | SourceUnit; } - - /** - * Returns canonical representation of the error signature as string - * - * @deprecated - */ - canonicalSignature(encoderVersion: ABIEncoderVersion): string { - const args = this.vParameters.vParameters.map((arg) => - arg.canonicalSignatureType(encoderVersion) - ); - - return this.name + "(" + args.join(",") + ")"; - } - - /** - * Returns HEX string containing first 4 bytes of Keccak256 hash function - * applied to the canonical representation of the error signature. - * - * @deprecated - */ - canonicalSignatureHash(encoderVersion: ABIEncoderVersion): string { - return encodeFuncSignature(this.canonicalSignature(encoderVersion)); - } } diff --git a/src/ast/implementation/declaration/event_definition.ts b/src/ast/implementation/declaration/event_definition.ts index 40a7017c..fab5d11a 100644 --- a/src/ast/implementation/declaration/event_definition.ts +++ b/src/ast/implementation/declaration/event_definition.ts @@ -1,6 +1,4 @@ -import { ABIEncoderVersion } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; -import { encodeEventSignature } from "../../utils"; import { ParameterList } from "../meta/parameter_list"; import { StructuredDocumentation } from "../meta/structured_documentation"; import { ContractDefinition } from "./contract_definition"; @@ -67,34 +65,4 @@ export class EventDefinition extends ASTNode { get vScope(): ContractDefinition { return this.parent as ContractDefinition; } - - /** - * Returns canonical representation of the event signature as string - * - * @deprecated - */ - canonicalSignature(encoderVersion: ABIEncoderVersion): string { - const args = this.vParameters.vParameters.map((arg) => - arg.canonicalSignatureType(encoderVersion) - ); - - return this.name + "(" + args.join(",") + ")"; - } - - /** - * Returns HEX string containing first 32 bytes of Keccak256 hash function - * applied to the canonical representation of the event signature. - * - * @deprecated - */ - canonicalSignatureHash(encoderVersion: ABIEncoderVersion): string { - return encodeEventSignature(this.canonicalSignature(encoderVersion)); - } - - /** - * Returns 32 bytes of event topic hash or `undefined` if event is declared as anonymous. - */ - eventTopic(encoderVersion: ABIEncoderVersion): string | undefined { - return this.anonymous ? undefined : this.canonicalSignatureHash(encoderVersion); - } } diff --git a/src/ast/implementation/declaration/function_definition.ts b/src/ast/implementation/declaration/function_definition.ts index 4e441c47..66fadb69 100644 --- a/src/ast/implementation/declaration/function_definition.ts +++ b/src/ast/implementation/declaration/function_definition.ts @@ -1,13 +1,5 @@ -import { variableDeclarationToTypeNode } from "../../../types/utils"; -import { ABIEncoderVersion, abiTypeToLibraryCanonicalName } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; -import { - ContractKind, - FunctionKind, - FunctionStateMutability, - FunctionVisibility -} from "../../constants"; -import { encodeFuncSignature } from "../../utils"; +import { FunctionKind, FunctionStateMutability, FunctionVisibility } from "../../constants"; import { ModifierInvocation } from "../meta/modifier_invocation"; import { OverrideSpecifier } from "../meta/override_specifier"; import { ParameterList } from "../meta/parameter_list"; @@ -169,50 +161,4 @@ export class FunctionDefinition extends ASTNode { this.scope = value.id; } - - /** - * Returns canonical representation of the function signature as string. - * - * NOTE: This property will contain empty strings for fallback functions and constructors. - * - * @deprecated - */ - canonicalSignature(encoderVersion: ABIEncoderVersion): string { - if (this.name === "" || this.isConstructor) { - return ""; - } - - let args: string[]; - - // Signatures are computed differently depending on whether this is a library function - // or a contract method - if ( - this.vScope instanceof ContractDefinition && - this.vScope.kind === ContractKind.Library - ) { - args = this.vParameters.vParameters.map((arg) => - abiTypeToLibraryCanonicalName(variableDeclarationToTypeNode(arg)) - ); - } else { - args = this.vParameters.vParameters.map((arg) => - arg.canonicalSignatureType(encoderVersion) - ); - } - - return this.name + "(" + args.join(",") + ")"; - } - - /** - * Returns HEX string containing first 4 bytes of Keccak256 hash function - * applied to the canonical representation of the function signature. - * - * NOTE: This property will contain empty strings for fallback functions and constructors. - * - * @deprecated - */ - canonicalSignatureHash(encoderVersion: ABIEncoderVersion): string { - const signature = this.canonicalSignature(encoderVersion); - - return signature ? encodeFuncSignature(signature) : ""; - } } diff --git a/src/ast/implementation/declaration/modifier_definition.ts b/src/ast/implementation/declaration/modifier_definition.ts index ef232a34..a4333868 100644 --- a/src/ast/implementation/declaration/modifier_definition.ts +++ b/src/ast/implementation/declaration/modifier_definition.ts @@ -1,6 +1,4 @@ -import { ABIEncoderVersion } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; -import { encodeFuncSignature } from "../../utils"; import { OverrideSpecifier } from "../meta/override_specifier"; import { ParameterList } from "../meta/parameter_list"; import { StructuredDocumentation } from "../meta/structured_documentation"; @@ -97,27 +95,4 @@ export class ModifierDefinition extends ASTNode { get vScope(): ContractDefinition { return this.parent as ContractDefinition; } - - /** - * Returns canonical representation of the modifier signature as string. - * - * @deprecated - */ - canonicalSignature(encoderVersion: ABIEncoderVersion): string { - const args = this.vParameters.vParameters.map((arg) => - arg.canonicalSignatureType(encoderVersion) - ); - - return this.name + "(" + args.join(",") + ")"; - } - - /** - * Returns HEX string containing first 4 bytes of Keccak256 hash function - * applied to the canonical representation of the modifier signature. - * - * @deprecated - */ - canonicalSignatureHash(encoderVersion: ABIEncoderVersion): string { - return encodeFuncSignature(this.canonicalSignature(encoderVersion)); - } } diff --git a/src/ast/implementation/declaration/variable_declaration.ts b/src/ast/implementation/declaration/variable_declaration.ts index d6a22ec0..37543724 100644 --- a/src/ast/implementation/declaration/variable_declaration.ts +++ b/src/ast/implementation/declaration/variable_declaration.ts @@ -1,34 +1,9 @@ -import { assert } from "../../../misc/utils"; -import { - FunctionType, - IntType, - PointerType, - TupleType, - TypeNode, - UserDefinedType -} from "../../../types/ast"; -import { - generalizeType, - typeNameToSpecializedTypeNode, - variableDeclarationToTypeNode -} from "../../../types/utils"; -import { ABIEncoderVersion, abiTypeToCanonicalName, toABIEncodedType } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; -import { - DataLocation, - FunctionStateMutability, - FunctionVisibility, - Mutability, - StateVariableVisibility -} from "../../constants"; -import { encodeFuncSignature } from "../../utils"; +import { DataLocation, Mutability, StateVariableVisibility } from "../../constants"; import { Expression } from "../expression/expression"; import { OverrideSpecifier } from "../meta/override_specifier"; import { StructuredDocumentation } from "../meta/structured_documentation"; -import { ArrayTypeName } from "../type/array_type_name"; -import { Mapping } from "../type/mapping"; import { TypeName } from "../type/type_name"; -import { StructDefinition } from "./struct_definition"; export class VariableDeclaration extends ASTNode { /** @@ -170,117 +145,4 @@ export class VariableDeclaration extends ASTNode { this.scope = value.id; } - - /** - * @deprecated - */ - canonicalSignatureType(encoderVersion: ABIEncoderVersion): string { - const type = variableDeclarationToTypeNode(this); - const abiType = toABIEncodedType(type, encoderVersion); - - return abiTypeToCanonicalName(generalizeType(abiType)[0]); - } - - /** - * Computes the argument types and return type for the public accessor - * corresponding to this state variable. - * - * @deprecated - */ - getterArgsAndReturn(): [TypeNode[], TypeNode] { - const argTypes: TypeNode[] = []; - - let type = this.vType; - - assert( - type !== undefined, - "Called getterArgsAndReturn() on variable declaration without type", - this - ); - - while (true) { - if (type instanceof ArrayTypeName) { - argTypes.push(new IntType(256, false)); - - type = type.vBaseType; - } else if (type instanceof Mapping) { - argTypes.push(typeNameToSpecializedTypeNode(type.vKeyType, DataLocation.Memory)); - - type = type.vValueType; - } else { - break; - } - } - - let retType = typeNameToSpecializedTypeNode(type, DataLocation.Memory); - - if ( - retType instanceof PointerType && - retType.to instanceof UserDefinedType && - retType.to.definition instanceof StructDefinition - ) { - const elements: TypeNode[] = []; - - for (const member of retType.to.definition.vMembers) { - const memberT = member.vType; - - assert( - memberT !== undefined, - "Unexpected untyped struct member", - retType.to.definition - ); - - if (memberT instanceof Mapping || memberT instanceof ArrayTypeName) { - continue; - } - - elements.push(typeNameToSpecializedTypeNode(memberT, DataLocation.Memory)); - } - - retType = new TupleType(elements); - } - - return [argTypes, retType]; - } - - /** - * Computes the function type for the public accessor corresponding to this - * state variable. - * - * @deprecated - */ - getterFunType(): FunctionType { - const [args, ret] = this.getterArgsAndReturn(); - - return new FunctionType( - this.name, - args, - ret instanceof TupleType ? ret.elements : [ret], - FunctionVisibility.External, - FunctionStateMutability.View - ); - } - - /** - * Computes the canonical signature for the public accessor corresponding to - * this state variable. - * - * @deprecated - */ - getterCanonicalSignature(encoderVersion: ABIEncoderVersion): string { - const [internalArgTypes] = this.getterArgsAndReturn(); - const argTypes = internalArgTypes.map((typ) => toABIEncodedType(typ, encoderVersion, true)); - - return this.name + "(" + argTypes.map(abiTypeToCanonicalName).join(",") + ")"; - } - - /** - * Computes the canonical signature hash for the public accessor - * corresponding to this state variable. - * - * @deprecated - */ - getterCanonicalSignatureHash(encoderVersion: ABIEncoderVersion): string { - return encodeFuncSignature(this.getterCanonicalSignature(encoderVersion)); - } } diff --git a/src/ast/implementation/expression/function_call.ts b/src/ast/implementation/expression/function_call.ts index fac49b44..3637dc35 100644 --- a/src/ast/implementation/expression/function_call.ts +++ b/src/ast/implementation/expression/function_call.ts @@ -1,4 +1,3 @@ -import { ABIEncoderVersion } from "../../../types/abi"; import { ASTNode } from "../../ast_node"; import { ExternalReferenceType, FunctionCallKind } from "../../constants"; import { ErrorDefinition } from "../declaration/error_definition"; @@ -144,48 +143,6 @@ export class FunctionCall extends Expression { return undefined; } - /** - * Returns canonical signature of referenced definition, - * or `undefined` in case if there is callable is not - * a user-defined entity. - * - * @deprecated - */ - referencedCanonicalSignature(encoderVersion: ABIEncoderVersion): string | undefined { - const declaration = this.vReferencedDeclaration; - - if (declaration === undefined) { - return undefined; - } - - if (declaration instanceof VariableDeclaration) { - return declaration.getterCanonicalSignature(encoderVersion); - } - - return declaration.canonicalSignature(encoderVersion); - } - - /** - * Returns canonical signature hash of referenced definition, - * or `undefined` in case if there is callable is not - * a user-defined entity. - * - * @deprecated - */ - referencedCanonicalSignatureHash(encoderVersion: ABIEncoderVersion): string | undefined { - const declaration = this.vReferencedDeclaration; - - if (declaration === undefined) { - return undefined; - } - - if (declaration instanceof VariableDeclaration) { - return declaration.getterCanonicalSignatureHash(encoderVersion); - } - - return declaration.canonicalSignatureHash(encoderVersion); - } - /** * `identifier.memberName` or if `memberName` is empty it is `identifier` */ diff --git a/src/bin/compile.ts b/src/bin/compile.ts index f4bdc408..77ced907 100644 --- a/src/bin/compile.ts +++ b/src/bin/compile.ts @@ -24,6 +24,7 @@ import { FunctionDefinition, FunctionVisibility, getABIEncoderVersion, + InferType, isExact, LatestCompilerVersion, PossibleCompilerKinds, @@ -318,6 +319,8 @@ function error(message: string): never { ? getABIEncoderVersion(units, result.compilerVersion as string) : undefined; + const inference = new InferType(result.compilerVersion || LatestCompilerVersion); + const walker: ASTNodeCallback = (node) => { const level = node.getParents().length; const indent = INDENT.repeat(level); @@ -329,7 +332,9 @@ function error(message: string): never { } else if (node instanceof ContractDefinition) { message += " -> " + node.kind + " " + node.name; - const interfaceId = encoderVersion ? node.interfaceId(encoderVersion) : undefined; + const interfaceId = encoderVersion + ? inference.interfaceId(node, encoderVersion) + : undefined; if (interfaceId) { message += ` [id: ${interfaceId}]`; @@ -340,11 +345,11 @@ function error(message: string): never { (node.visibility === FunctionVisibility.Public || node.visibility === FunctionVisibility.External) && encoderVersion - ? node.canonicalSignature(encoderVersion) + ? inference.signature(node, encoderVersion) : undefined; if (signature && encoderVersion) { - const selector = node.canonicalSignatureHash(encoderVersion); + const selector = inference.signatureHash(node, encoderVersion); message += ` -> ${signature} [selector: ${selector}]`; } else { @@ -352,8 +357,8 @@ function error(message: string): never { } } else if (node instanceof ErrorDefinition || node instanceof EventDefinition) { if (encoderVersion) { - const signature = node.canonicalSignature(encoderVersion); - const selector = node.canonicalSignatureHash(encoderVersion); + const signature = inference.signature(node, encoderVersion); + const selector = inference.signatureHash(node, encoderVersion); message += ` -> ${signature} [selector: ${selector}]`; } @@ -365,8 +370,8 @@ function error(message: string): never { node.visibility === StateVariableVisibility.Public && encoderVersion !== undefined ) { - const signature = node.getterCanonicalSignature(encoderVersion); - const selector = node.getterCanonicalSignatureHash(encoderVersion); + const signature = inference.signature(node, encoderVersion); + const selector = inference.signatureHash(node, encoderVersion); message += ` [getter: ${signature}, selector: ${selector}]`; } diff --git a/src/types/abi.ts b/src/types/abi.ts index 61dface8..5bcaea0c 100644 --- a/src/types/abi.ts +++ b/src/types/abi.ts @@ -1,12 +1,7 @@ -import { - ContractDefinition, - DataLocation, - EnumDefinition, - StructDefinition, - UserDefinedValueTypeDefinition -} from ".."; +import { DataLocation } from ".."; import { assert } from "../misc"; import { + AddressType, ArrayType, BoolType, BytesType, @@ -14,19 +9,13 @@ import { FunctionType, IntType, MappingType, + PointerType, StringType, TupleType, - PointerType, TypeNode, - UserDefinedType, - AddressType + UserDefinedType } from "./ast"; -import { - getFQDefName, - typeNameToTypeNode, - variableDeclarationToTypeNode, - enumToIntType -} from "./utils"; +import { getFQDefName } from "./utils"; export enum ABIEncoderVersion { V1 = "ABIEncoderV1", @@ -35,71 +24,6 @@ export enum ABIEncoderVersion { export const ABIEncoderVersions = new Set([ABIEncoderVersion.V1, ABIEncoderVersion.V2]); -/** - * Convert an internal TypeNode to the external TypeNode that would correspond to it - * after ABI-encoding with encoder version `encoderVersion`. Follows the following rules: - * - * 1. Contract definitions turned to address. - * 2. Enum definitions turned to uint of minimal fitting size. - * 3. Any storage pointer types are converted to memory pointer types. - * 4. Throw an error on any nested mapping types. - * - * @see https://docs.soliditylang.org/en/latest/abi-spec.html - */ -export function toABIEncodedType( - type: TypeNode, - encoderVersion: ABIEncoderVersion, - normalizePointers = false -): TypeNode { - if (type instanceof MappingType) { - throw new Error("Cannot abi-encode mapping types"); - } - - if (type instanceof ArrayType) { - return new ArrayType( - toABIEncodedType(type.elementT, encoderVersion, normalizePointers), - type.size - ); - } - - if (type instanceof PointerType) { - const toT = toABIEncodedType(type.to, encoderVersion, normalizePointers); - - return new PointerType(toT, normalizePointers ? DataLocation.Memory : type.location); - } - - if (type instanceof UserDefinedType) { - if (type.definition instanceof UserDefinedValueTypeDefinition) { - return typeNameToTypeNode(type.definition.underlyingType); - } - - if (type.definition instanceof ContractDefinition) { - return new AddressType(false); - } - - if (type.definition instanceof EnumDefinition) { - return enumToIntType(type.definition); - } - - if (type.definition instanceof StructDefinition) { - assert( - encoderVersion !== ABIEncoderVersion.V1, - "Getters of struct return type are not supported by ABI encoder v1" - ); - - const fieldTs = type.definition.vMembers.map((fieldT) => - variableDeclarationToTypeNode(fieldT) - ); - - return new TupleType( - fieldTs.map((fieldT) => toABIEncodedType(fieldT, encoderVersion, normalizePointers)) - ); - } - } - - return type; -} - /** * Get the canonical name for the `TypeNode` `t`, to be used in * function/accessor/error/event signatures diff --git a/src/types/ast/index.ts b/src/types/ast/index.ts index b6bab197..90ab8e2a 100644 --- a/src/types/ast/index.ts +++ b/src/types/ast/index.ts @@ -16,7 +16,6 @@ export * from "./int_literal"; export * from "./int_type"; export * from "./mapping_type"; export * from "./modifier_type"; -export * from "./module_type"; export * from "./numeric_literal"; export * from "./packed_array_type"; export * from "./pointer"; diff --git a/src/types/ast/internal/index.ts b/src/types/ast/internal/index.ts index c4520ba2..7ad1b6ad 100644 --- a/src/types/ast/internal/index.ts +++ b/src/types/ast/internal/index.ts @@ -1,3 +1,2 @@ export * from "./function_set"; -export * from "./inaccessible_dynamic_type"; export * from "./type_var"; diff --git a/src/types/builtins.ts b/src/types/builtins.ts index 3d491911..da281bbe 100644 --- a/src/types/builtins.ts +++ b/src/types/builtins.ts @@ -1,5 +1,4 @@ import { - AddressType, BuiltinFunctionType, BuiltinStructType, IntType, @@ -41,8 +40,7 @@ export const typeContract = new BuiltinFunctionType( new Map([ ["name", [[types.stringMemory, ">=0.5.5"]]], ["creationCode", [[types.bytesMemory, ">=0.5.3"]]], - ["runtimeCode", [[types.bytesMemory, ">=0.5.3"]]], - ["interfaceId", [[types.bytes4, ">=0.6.7"]]] + ["runtimeCode", [[types.bytesMemory, ">=0.5.3"]]] ]) ) ] @@ -336,7 +334,7 @@ export const globalBuiltins = new BuiltinStructType( new BuiltinFunctionType( "ecrecover", [types.bytes32, types.uint8, types.bytes32, types.bytes32], - [new AddressType(false)] + [types.address] ), ">=0.4.13" ] diff --git a/src/types/eval_const.ts b/src/types/eval_const.ts index 7044ba04..60105222 100644 --- a/src/types/eval_const.ts +++ b/src/types/eval_const.ts @@ -13,7 +13,7 @@ import { VariableDeclaration } from "../ast"; import { pp } from "../misc"; -import { binaryOperatorGroups, subdenominationMultipliers } from "./infer"; +import { SUBDENOMINATION_MULTIPLIERS, BINARY_OPERATOR_GROUPS } from "./utils"; /** * Tune up precision of decimal values to follow Solidity behavior. * Be careful with precision - setting it to large values causes NodeJS to crash. @@ -133,15 +133,17 @@ function evalLiteral(expr: Literal): Value { const val = dec.isInteger() ? BigInt(dec.toFixed()) : dec; if (expr.subdenomination !== undefined) { - if (subdenominationMultipliers[expr.subdenomination] === undefined) { + const multiplier = SUBDENOMINATION_MULTIPLIERS.get(expr.subdenomination); + + if (multiplier === undefined) { throw new EvalError(expr, `Unknown denomination ${expr.subdenomination}`); } if (val instanceof Decimal) { - return demoteFromDec(val.times(subdenominationMultipliers[expr.subdenomination])); + return demoteFromDec(val.times(multiplier)); } - return val * BigInt(subdenominationMultipliers[expr.subdenomination].toFixed()); + return val * BigInt(multiplier.toFixed()); } return val; @@ -332,23 +334,23 @@ function evalBinary(expr: BinaryOperation): Value { const lVal = evalConstantExpr(expr.vLeftExpression); const rVal = evalConstantExpr(expr.vRightExpression); - if (binaryOperatorGroups.Logical.includes(expr.operator)) { + if (BINARY_OPERATOR_GROUPS.Logical.includes(expr.operator)) { return evalBinaryLogic(expr, lVal, rVal); } - if (binaryOperatorGroups.Equality.includes(expr.operator)) { + if (BINARY_OPERATOR_GROUPS.Equality.includes(expr.operator)) { return evalBinaryEquality(expr, lVal, rVal); } - if (binaryOperatorGroups.Comparison.includes(expr.operator)) { + if (BINARY_OPERATOR_GROUPS.Comparison.includes(expr.operator)) { return evalBinaryComparison(expr, lVal, rVal); } - if (binaryOperatorGroups.Arithmetic.includes(expr.operator)) { + if (BINARY_OPERATOR_GROUPS.Arithmetic.includes(expr.operator)) { return evalBinaryArithmetic(expr, lVal, rVal); } - if (binaryOperatorGroups.Bitwise.includes(expr.operator)) { + if (BINARY_OPERATOR_GROUPS.Bitwise.includes(expr.operator)) { return evalBinaryBitwise(expr, lVal, rVal); } diff --git a/src/types/index.ts b/src/types/index.ts index e24e2946..2e74ba22 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,9 +1,9 @@ export * from "./ast"; +export * from "./abi"; export * from "./builtins"; export * from "./eval_const"; export * from "./infer"; export * from "./misc"; export * from "./polymorphic"; export * from "./reserved"; -export * from "./typeStrings"; export * from "./utils"; diff --git a/src/types/infer.ts b/src/types/infer.ts index bdfb275b..5ddfab68 100644 --- a/src/types/infer.ts +++ b/src/types/infer.ts @@ -2,13 +2,17 @@ import { Decimal } from "decimal.js"; import { gte, lt } from "semver"; import { AnyResolvable, + ArrayTypeName, Assignment, ASTNode, BinaryOperation, Conditional, ContractDefinition, ContractKind, + ElementaryTypeName, ElementaryTypeNameExpression, + encodeEventSignature, + encodeFuncSignature, EnumDefinition, ErrorDefinition, EventDefinition, @@ -20,6 +24,7 @@ import { FunctionCallOptions, FunctionDefinition, FunctionStateMutability, + FunctionTypeName, FunctionVisibility, Identifier, IdentifierPath, @@ -28,6 +33,7 @@ import { IndexRangeAccess, Literal, LiteralKind, + Mapping, MemberAccess, ModifierDefinition, NewExpression, @@ -39,15 +45,18 @@ import { TupleExpression, TypeName, UnaryOperation, + UserDefinedTypeName, UserDefinedValueTypeDefinition, VariableDeclaration, VariableDeclarationStatement } from "../ast"; import { DataLocation } from "../ast/constants"; import { assert, eq, forAny, pp } from "../misc"; +import { ABIEncoderVersion, abiTypeToCanonicalName, abiTypeToLibraryCanonicalName } from "./abi"; import { AddressType, ArrayType, + BoolType, BuiltinFunctionType, BuiltinStructType, BytesType, @@ -55,7 +64,6 @@ import { EventType, FixedBytesType, FunctionLikeSetType, - FunctionSetType, FunctionType, ImportRefType, IntLiteralType, @@ -93,43 +101,29 @@ import { TypeSubstituion } from "./polymorphic"; import { types } from "./reserved"; -import { parse } from "./typeStrings"; import { + BINARY_OPERATOR_GROUPS, castable, decimalToRational, + enumToIntType, generalizeType, getFallbackRecvFuns, getFQDefName, + inferCommonVisiblity, isReferenceType, isVisiblityExternallyCallable, + mergeFunTypes, smallestFittingType, specializeType, - typeNameToTypeNode + stripSingletonParens, + SUBDENOMINATION_MULTIPLIERS } from "./utils"; -export const unaryImpureOperators = ["++", "--"]; +const unaryImpureOperators = ["++", "--"]; -export const binaryOperatorGroups = { - Arithmetic: ["+", "-", "*", "/", "%", "**"], - Bitwise: ["<<", ">>", "&", "|", "^"], - Comparison: ["<", ">", "<=", ">="], - Equality: ["==", "!="], - Logical: ["&&", "||"] -}; - -export const subdenominationMultipliers: { [key: string]: Decimal } = { - seconds: new Decimal(1), - minutes: new Decimal(60), - hours: new Decimal(3600), - days: new Decimal(24 * 3600), - weeks: new Decimal(7 * 24 * 3600), - years: new Decimal(365 * 24 * 3600), - wei: new Decimal(1), - gwei: new Decimal(10 ** 9), - szabo: new Decimal(10 ** 12), - finney: new Decimal(10).toPower(15), - ether: new Decimal(10).toPower(18) -}; +const RX_ADDRESS = /^address *(payable)?$/; +const RX_INTEGER = /^(u?)int([0-9]*)$/; +const RX_FIXED_BYTES = /^bytes([0-9]+)$/; /** * Some builtins have types that are not easy to express with our current hacky polymorphic support. @@ -176,19 +170,6 @@ function typesAreUnordered( return [undefined, undefined]; } -/// Strip any singleton parens from expressions. I.e. given (((e))) returns e. -function stripSingletonParens(e: Expression): Expression { - while (e instanceof TupleExpression && e.vOriginalComponents.length === 1) { - const comp = e.vOriginalComponents[0]; - - assert(comp !== null, 'Unexpected "null" component in tuple with single element'); - - e = comp; - } - - return e; -} - /** * Given a `FunctionType` or `FunctionSetType` `arg` return a new `FunctionType`/`FunctionSetType` with * all first arguments marked as implicit. @@ -211,63 +192,6 @@ function markFirstArgImplicit = []; - - if (a instanceof FunctionType || a instanceof BuiltinFunctionType) { - funs.push(a); - } else { - funs.push(...a.defs); - } - - if (b instanceof FunctionType || b instanceof BuiltinFunctionType) { - funs.push(b); - } else { - funs.push(...b.defs); - } - - return new FunctionLikeSetType(funs); -} - -/** - * Given 2 function pointer's visibilities infer a common visibility thats compatible with both. - * This is used to infer the visibility of the expression `flag ? fun1 : fun2` where fun1 and fun2 are - * function pointers. - */ -function inferCommonVisiblity( - a: FunctionVisibility, - b: FunctionVisibility -): FunctionVisibility | undefined { - const visiblityOrder = [ - FunctionVisibility.External, - FunctionVisibility.Public, - FunctionVisibility.Internal, - FunctionVisibility.Default, - FunctionVisibility.Private - ]; - - if (a == b) { - return a; - } - - if (visiblityOrder.indexOf(a) > visiblityOrder.indexOf(b)) { - [b, a] = [a, b]; - } - - if (a === FunctionVisibility.External) { - return b == FunctionVisibility.Public ? FunctionVisibility.External : undefined; - } - - return FunctionVisibility.Internal; -} - export class InferType { constructor(public readonly version: string) {} @@ -438,14 +362,17 @@ export class InferType { let commonElT = this.inferCommonType(a.elements[i], b.elements[i]); if (commonElT instanceof IntLiteralType && commonElT.literal !== undefined) { - commonElT = smallestFittingType(commonElT.literal) as TypeNode; + const fittingT = smallestFittingType(commonElT.literal); + assert( - commonElT !== undefined, + fittingT !== undefined, "Can't infer common type for tuple elements {0} between {1} and {2}", i, a, b ); + + commonElT = fittingT; } commonElTs.push(commonElT); @@ -508,9 +435,9 @@ export class InferType { */ typeOfBinaryOperation(node: BinaryOperation): TypeNode { if ( - binaryOperatorGroups.Comparison.includes(node.operator) || - binaryOperatorGroups.Equality.includes(node.operator) || - binaryOperatorGroups.Logical.includes(node.operator) + BINARY_OPERATOR_GROUPS.Comparison.includes(node.operator) || + BINARY_OPERATOR_GROUPS.Equality.includes(node.operator) || + BINARY_OPERATOR_GROUPS.Logical.includes(node.operator) ) { return types.bool; } @@ -549,7 +476,7 @@ export class InferType { } } - if (binaryOperatorGroups.Arithmetic.includes(node.operator)) { + if (BINARY_OPERATOR_GROUPS.Arithmetic.includes(node.operator)) { assert( a instanceof IntType || a instanceof IntLiteralType, "Unexpected type of {0}", @@ -565,7 +492,7 @@ export class InferType { return this.inferCommonIntType(a, b); } - if (binaryOperatorGroups.Bitwise.includes(node.operator)) { + if (BINARY_OPERATOR_GROUPS.Bitwise.includes(node.operator)) { // For bitshifts just take the type of the lhs if ([">>", "<<"].includes(node.operator)) { if (a instanceof IntLiteralType) { @@ -646,13 +573,15 @@ export class InferType { } assert(node.vArguments.length === 1, `Unexpected number of args to type cast {0}`, node); + const arg = node.vArguments[0]; - const argT = this.typeOf(arg); if (arg instanceof Literal && arg.value.startsWith("0x") && arg.value.length === 42) { return lt(this.version, "0.6.0") ? types.addressPayable : types.address; } + const argT = this.typeOf(arg); + if ( argT instanceof IntType || argT instanceof IntLiteralType || @@ -666,10 +595,12 @@ export class InferType { } if (argT instanceof UserDefinedType && argT.definition instanceof ContractDefinition) { - const contract = argT.definition; - const funs = getFallbackRecvFuns(contract); - - if (forAny(funs, (fun) => fun.stateMutability === FunctionStateMutability.Payable)) { + if ( + forAny( + getFallbackRecvFuns(argT.definition), + (fn) => fn.stateMutability === FunctionStateMutability.Payable + ) + ) { return types.addressPayable; } } @@ -716,9 +647,9 @@ export class InferType { typeOfNewCall(node: FunctionCall): TypeNode { const newExpr = node.vCallee; - assert(newExpr instanceof NewExpression, "Unexpected vcall {0}", newExpr); + assert(newExpr instanceof NewExpression, 'Unexpected "new" call {0}', newExpr); - const typ = typeNameToTypeNode(newExpr.vTypeName); + const typ = this.typeNameToTypeNode(newExpr.vTypeName); const loc = typ instanceof UserDefinedType && typ.definition instanceof ContractDefinition ? DataLocation.Storage @@ -733,7 +664,7 @@ export class InferType { callExp: Expression ): FunctionType | BuiltinFunctionType | undefined { const argTs: TypeNode[] = args.map((arg) => this.typeOf(arg)); - // If we are matching with a + const argTsWithImplictArg = callExp instanceof MemberAccess ? [this.typeOf(callExp.vExpression), ...argTs] : argTs; @@ -763,30 +694,6 @@ export class InferType { return undefined; } - /** - * Return true IFF the passed in node is an external callee. There are 2 cases for external calls: - * - * 1. The builtin functions (address).call/callcode/staticcall/delegatecall/transfer/send - * 2. Calling a function on some variable of type ContractDefinition - */ - private isFunctionCallExternal(callee: ASTNode, calleeT: TypeNode): boolean { - if (!(callee instanceof MemberAccess)) { - return false; - } - - const name = callee.memberName; - - if ( - calleeT instanceof BuiltinFunctionType && - ["call", "callcode", "staticcall", "delegatecall", "transfer", "send"].includes(name) - ) { - return true; - } - - const baseT = this.typeOf(callee.vExpression); - return baseT instanceof UserDefinedType && baseT.definition instanceof ContractDefinition; - } - /** * Infer the type of the function call */ @@ -809,9 +716,7 @@ export class InferType { if (node.vFunctionCallType === ExternalReferenceType.Builtin) { if (calleeT instanceof FunctionLikeSetType) { - calleeT = calleeT.defs.filter( - (d) => d instanceof BuiltinFunctionType - )[0] as BuiltinFunctionType; + calleeT = calleeT.defs.filter((d) => d instanceof BuiltinFunctionType)[0]; } if (!(calleeT instanceof BuiltinFunctionType || calleeT instanceof FunctionType)) { @@ -968,14 +873,14 @@ export class InferType { innerT instanceof IntType || (innerT instanceof UserDefinedType && innerT.definition instanceof EnumDefinition) ) { - return applySubstitution(typeInt, new Map([["T", innerT]])) as BuiltinFunctionType; + return applySubstitution(typeInt, new Map([["T", innerT]])); } if (innerT instanceof UserDefinedType && innerT.definition instanceof ContractDefinition) { const resTemplateT = innerT.definition.kind === ContractKind.Interface ? typeInterface : typeContract; - return applySubstitution(resTemplateT, new Map([["T", innerT]])) as BuiltinFunctionType; + return applySubstitution(resTemplateT, new Map([["T", innerT]])); } throw new SolTypeError(`Unexpected type ${innerT.pp()} in type() node ${pp(node)}`); @@ -1173,25 +1078,27 @@ export class InferType { } typeOfLiteral(node: Literal): TypeNode { - if (node.kind === "number") { + if (node.kind === LiteralKind.Number) { if (node.typeString === "address") { - return new AddressType(false); + return types.address; } if (node.typeString === "address payable") { - return new AddressType(true); + return types.addressPayable; } let val = new Decimal(node.value.replaceAll("_", "")); if (node.subdenomination !== undefined) { + const multiplier = SUBDENOMINATION_MULTIPLIERS.get(node.subdenomination); + assert( - node.subdenomination in subdenominationMultipliers, + multiplier !== undefined, "Unknown subdenomination {0}", node.subdenomination ); - val = val.times(subdenominationMultipliers[node.subdenomination]); + val = val.times(multiplier); } if (val.isInteger()) { @@ -1201,7 +1108,11 @@ export class InferType { return new RationalLiteralType(decimalToRational(val)); } - if (node.kind === "string" || node.kind === "unicodeString" || node.kind === "hexString") { + if ( + node.kind === LiteralKind.String || + node.kind === LiteralKind.UnicodeString || + node.kind === LiteralKind.HexString + ) { return new StringLiteralType(node.kind); } @@ -1232,7 +1143,7 @@ export class InferType { /// using for *; match = true; } else { - const usingForTyp = typeNameToTypeNode(usingFor.vTypeName); + const usingForTyp = this.typeNameToTypeNode(usingFor.vTypeName); match = eq(usingForTyp, generalizeType(baseT)[0]); } @@ -1278,7 +1189,7 @@ export class InferType { if (res) { assert( res instanceof FunctionType || res instanceof FunctionLikeSetType, - `Unexpected type {0} for {1} in library {1}`, + "Unexpected type {0} for {1} in library {1}", res, node.memberName, usingFor.vLibraryName.name @@ -1377,9 +1288,8 @@ export class InferType { private typeOfMemberAccessImpl(node: MemberAccess, baseT: TypeNode): TypeNode | undefined { if (baseT instanceof UserDefinedType && baseT.definition instanceof ContractDefinition) { const contract = baseT.definition; - let fieldT = this.typeOfResolved(node.memberName, contract, true); - let builtinT: TypeNode | undefined; + let fieldT = this.typeOfResolved(node.memberName, contract, true); assert( fieldT === undefined || @@ -1390,15 +1300,15 @@ export class InferType { fieldT ); + let builtinT: TypeNode | undefined; + // For solidity <0.5.0 contract variables are implicitly castable to address if (lt(this.version, "0.5.0")) { builtinT = addressBuiltins.getFieldForVersion(node.memberName, this.version); } if (fieldT) { - if (this.isFunctionCallExternal(node, baseT)) { - fieldT = this.changeLocToMemory(fieldT); - } + fieldT = this.changeLocToMemory(fieldT); if (builtinT instanceof BuiltinFunctionType) { return mergeFunTypes( @@ -1431,7 +1341,7 @@ export class InferType { fields[0] ); - return specializeType(typeNameToTypeNode(fields[0].vType), baseT.location); + return specializeType(this.typeNameToTypeNode(fields[0].vType), baseT.location); } } @@ -1539,15 +1449,13 @@ export class InferType { componentT ); + /** + * Components of second arg of decode() are plain types, + * however they got specialized or slightly promoted on assigment. + */ if (componentT.type instanceof AddressType && !componentT.type.payable) { - /** - * Promote address to address payable - */ - retTs.push(new AddressType(true)); + retTs.push(types.addressPayable); } else { - /** - * Specialize types to memory - */ retTs.push(specializeType(componentT.type, DataLocation.Memory)); } } @@ -1628,7 +1536,7 @@ export class InferType { baseT.type instanceof UserDefinedType && baseT.type.definition instanceof UserDefinedValueTypeDefinition ) { - const innerT = typeNameToTypeNode(baseT.type.definition.underlyingType); + const innerT = this.typeNameToTypeNode(baseT.type.definition.underlyingType); if (node.memberName === "wrap") { return new BuiltinFunctionType("wrap", [innerT], [baseT.type]); @@ -1655,9 +1563,7 @@ export class InferType { } typeOfNewExpression(newExpr: NewExpression): TypeNode { - assert(newExpr instanceof NewExpression, "Unexpected vcall {0}", newExpr); - - const typ = typeNameToTypeNode(newExpr.vTypeName); + const typ = this.typeNameToTypeNode(newExpr.vTypeName); const loc = typ instanceof UserDefinedType && typ.definition instanceof ContractDefinition ? DataLocation.Storage @@ -1689,32 +1595,32 @@ export class InferType { typeOfTupleExpression(node: TupleExpression): TypeNode { const componentTs = node.vComponents.map((cmp) => this.typeOf(cmp)); - if (node.isInlineArray) { - assert(node.vComponents.length > 0, "Can't have an empty array initialize"); - - let elT = componentTs.reduce((prev, cur) => this.inferCommonType(prev, cur)); - - if (elT instanceof IntLiteralType) { - const concreteT = elT.smallestFittingType(); + if (!node.isInlineArray) { + return componentTs.length === 1 ? componentTs[0] : new TupleType(componentTs); + } - assert( - concreteT !== undefined, - "Unable to figure out concrete type for array of literals {0}", - node - ); + assert(node.vComponents.length > 0, "Can't have an empty array initializer"); - elT = concreteT; - } + let elT = componentTs.reduce((prev, cur) => this.inferCommonType(prev, cur)); - elT = specializeType(generalizeType(elT)[0], DataLocation.Memory); + if (elT instanceof IntLiteralType) { + const concreteT = elT.smallestFittingType(); - return new PointerType( - new ArrayType(elT, BigInt(node.components.length)), - DataLocation.Memory + assert( + concreteT !== undefined, + "Unable to figure out concrete type for array of literals {0}", + node ); + + elT = concreteT; } - return componentTs.length === 1 ? componentTs[0] : new TupleType(componentTs); + elT = specializeType(generalizeType(elT)[0], DataLocation.Memory); + + return new PointerType( + new ArrayType(elT, BigInt(node.components.length)), + DataLocation.Memory + ); } typeOfUnaryOperation(node: UnaryOperation): TypeNode { @@ -1752,6 +1658,26 @@ export class InferType { throw new Error(`NYI unary operator ${node.operator} in ${pp(node)}`); } + typeOfElementaryTypeNameExpression(node: ElementaryTypeNameExpression): TypeNode { + let innerT: TypeNode; + + if (node.typeName instanceof TypeName) { + innerT = this.typeNameToTypeNode(node.typeName); + } else { + const elementaryT = this.elementaryTypeNameStringToTypeNode(node.typeName); + + assert( + elementaryT !== undefined, + 'NYI converting elementary type name "{0}"', + node.typeName + ); + + innerT = elementaryT; + } + + return new TypeNameType(innerT); + } + /** * Given an expression infer its type. */ @@ -1769,17 +1695,7 @@ export class InferType { } if (node instanceof ElementaryTypeNameExpression) { - let innerT: TypeNode; - - if (node.typeName instanceof TypeName) { - innerT = typeNameToTypeNode(node.typeName); - } else { - /// Prior to Solc 0.6.0 the TypeName is a string, which means we - /// unfortunately still need the typeString parser for backwards compat :( - innerT = parse(node.typeName, { ctx: node, version: this.version }); - } - - return new TypeNameType(innerT); + return this.typeOfElementaryTypeNameExpression(node); } if (node instanceof FunctionCall) { @@ -1818,9 +1734,8 @@ export class InferType { return this.typeOfUnaryOperation(node); } - /// FunctionCallOptions don't really get a type if (node instanceof FunctionCallOptions) { - return types.noType; + return this.typeOf(node.vExpression); } throw new Error(`NYI type inference of node ${node.constructor.name}`); @@ -1849,7 +1764,7 @@ export class InferType { const defs: AnyResolvable[] = []; for (const ctx of ctxs) { - defs.push(...resolveAny(name, ctx, this.version, true)); + defs.push(...resolveAny(name, ctx, this, true)); } if (defs.length === 0) { @@ -1899,7 +1814,7 @@ export class InferType { return new FunctionLikeSetType([ ...funs.map((funDef) => this.funDefToType(funDef)), - ...getters.map((getter) => getter.getterFunType()) + ...getters.map((varDecl) => this.getterFunType(varDecl)) ]); } @@ -1941,7 +1856,7 @@ export class InferType { assert(getters.length === 1, "Unexpected overloading between getters for {0}", name); return externalOnly - ? getters[0].getterFunType() + ? this.getterFunType(getters[0]) : this.variableDeclarationToTypeNode(getters[0]); } @@ -2042,7 +1957,7 @@ export class InferType { variableDeclarationToTypeNode(decl: VariableDeclaration): TypeNode { assert(decl.vType !== undefined, "Expected {0} to have type", decl); - const generalType = typeNameToTypeNode(decl.vType); + const generalType = this.typeNameToTypeNode(decl.vType); if (isReferenceType(generalType)) { const loc = this.inferVariableDeclLocation(decl); @@ -2092,4 +2007,413 @@ export class InferType { return new ErrorType(def.name, argTs); } + + /** + * Computes the function type for the public accessor corresponding to a state variable + */ + getterFunType(v: VariableDeclaration): FunctionType { + const [args, ret] = this.getterArgsAndReturn(v); + + return new FunctionType( + v.name, + args, + ret instanceof TupleType ? ret.elements : [ret], + FunctionVisibility.External, + FunctionStateMutability.View + ); + } + + /** + * Computes the argument types and return type for the public accessor + * corresponding to a state variable. + */ + getterArgsAndReturn(v: VariableDeclaration): [TypeNode[], TypeNode] { + const argTypes: TypeNode[] = []; + + let type = v.vType; + + assert( + type !== undefined, + "Called getterArgsAndReturn() on variable declaration without type", + v + ); + + while (true) { + if (type instanceof ArrayTypeName) { + argTypes.push(new IntType(256, false)); + + type = type.vBaseType; + } else if (type instanceof Mapping) { + argTypes.push( + this.typeNameToSpecializedTypeNode(type.vKeyType, DataLocation.Memory) + ); + + type = type.vValueType; + } else { + break; + } + } + + let retType = this.typeNameToSpecializedTypeNode(type, DataLocation.Memory); + + if ( + retType instanceof PointerType && + retType.to instanceof UserDefinedType && + retType.to.definition instanceof StructDefinition + ) { + const elements: TypeNode[] = []; + + for (const member of retType.to.definition.vMembers) { + const memberT = member.vType; + + assert( + memberT !== undefined, + "Unexpected untyped struct member", + retType.to.definition + ); + + if (memberT instanceof Mapping || memberT instanceof ArrayTypeName) { + continue; + } + + elements.push(this.typeNameToSpecializedTypeNode(memberT, DataLocation.Memory)); + } + + retType = new TupleType(elements); + } + + return [argTypes, retType]; + } + + /** + * Given the `name` string of elementary type, + * returns corresponding type node. + * + * @todo Consider fixes due to https://github.com/ConsenSys/solc-typed-ast/issues/160 + */ + elementaryTypeNameStringToTypeNode(name: string): TypeNode | undefined { + name = name.trim(); + + if (name === "bool") { + return new BoolType(); + } + + let m = name.match(RX_INTEGER); + + if (m !== null) { + const isSigned = m[1] !== "u"; + const bitWidth = m[2] === "" ? 256 : parseInt(m[2]); + + return new IntType(bitWidth, isSigned); + } + + m = name.match(RX_ADDRESS); + + if (m !== null) { + const isPayable = m[1] === "payable"; + + return new AddressType(isPayable); + } + + m = name.match(RX_FIXED_BYTES); + + if (m !== null) { + const size = parseInt(m[1]); + + return new FixedBytesType(size); + } + + if (name === "byte") { + return new FixedBytesType(1); + } + + if (name === "bytes") { + return new BytesType(); + } + + if (name === "string") { + return new StringType(); + } + + return undefined; + } + + /** + * Convert a given ast `TypeName` into a `TypeNode`. + * This produces "general type patterns" without any specific storage information. + */ + typeNameToTypeNode(node: TypeName): TypeNode { + if (node instanceof ElementaryTypeName) { + const type = this.elementaryTypeNameStringToTypeNode(node.name); + + assert(type !== undefined, 'NYI converting elementary type name "{0}"', node.name); + + /** + * The payability marker of an "address" type is contained + * in `stateMutability` property instead of "name" string. + */ + if (type instanceof AddressType) { + type.payable = node.stateMutability === "payable"; + } + + return type; + } + + if (node instanceof ArrayTypeName) { + const elT = this.typeNameToTypeNode(node.vBaseType); + + let size: bigint | undefined; + + if (node.vLength) { + const result = evalConstantExpr(node.vLength); + + assert( + typeof result === "bigint", + "Expected bigint for size of an array type", + node + ); + + size = result; + } + + return new ArrayType(elT, size); + } + + if (node instanceof UserDefinedTypeName) { + const def = node.vReferencedDeclaration; + + if ( + def instanceof StructDefinition || + def instanceof EnumDefinition || + def instanceof ContractDefinition || + def instanceof UserDefinedValueTypeDefinition + ) { + return new UserDefinedType(getFQDefName(def), def); + } + + throw new Error(`NYI converting user-defined AST type ${def.print()} to TypeNode`); + } + + if (node instanceof FunctionTypeName) { + /** + * `vType` is always defined here for parameters if a function type. + * Even in 0.4.x can't have function declarations with `var` args. + */ + const args = node.vParameterTypes.vParameters.map((arg) => + this.variableDeclarationToTypeNode(arg) + ); + + const rets = node.vReturnParameterTypes.vParameters.map((arg) => + this.variableDeclarationToTypeNode(arg) + ); + + return new FunctionType(undefined, args, rets, node.visibility, node.stateMutability); + } + + if (node instanceof Mapping) { + const keyT = this.typeNameToTypeNode(node.vKeyType); + const valueT = this.typeNameToTypeNode(node.vValueType); + + return new MappingType(keyT, valueT); + } + + throw new Error(`NYI converting AST type ${node.print()} to TypeNode`); + } + + /** + * Computes a `TypeNode` equivalent of given `astT`, + * specialized for location `loc` (if applicable). + */ + typeNameToSpecializedTypeNode(astT: TypeName, loc: DataLocation): TypeNode { + return specializeType(this.typeNameToTypeNode(astT), loc); + } + + /** + * Convert an internal TypeNode to the external TypeNode that would correspond to it + * after ABI-encoding with encoder version `encoderVersion`. Follows the following rules: + * + * 1. Contract definitions turned to address. + * 2. Enum definitions turned to uint of minimal fitting size. + * 3. Any storage pointer types are converted to memory pointer types. + * 4. Throw an error on any nested mapping types. + * + * @see https://docs.soliditylang.org/en/latest/abi-spec.html + */ + toABIEncodedType( + type: TypeNode, + encoderVersion: ABIEncoderVersion, + normalizePointers = false + ): TypeNode { + if (type instanceof MappingType) { + throw new Error("Cannot abi-encode mapping types"); + } + + if (type instanceof ArrayType) { + return new ArrayType( + this.toABIEncodedType(type.elementT, encoderVersion, normalizePointers), + type.size + ); + } + + if (type instanceof PointerType) { + const toT = this.toABIEncodedType(type.to, encoderVersion, normalizePointers); + + return new PointerType(toT, normalizePointers ? DataLocation.Memory : type.location); + } + + if (type instanceof UserDefinedType) { + if (type.definition instanceof UserDefinedValueTypeDefinition) { + return this.typeNameToTypeNode(type.definition.underlyingType); + } + + if (type.definition instanceof ContractDefinition) { + return types.address; + } + + if (type.definition instanceof EnumDefinition) { + return enumToIntType(type.definition); + } + + if (type.definition instanceof StructDefinition) { + assert( + encoderVersion !== ABIEncoderVersion.V1, + "Getters of struct return type are not supported by ABI encoder v1" + ); + + const fieldTs = type.definition.vMembers.map((fieldT) => + this.variableDeclarationToTypeNode(fieldT) + ); + + return new TupleType( + fieldTs.map((fieldT) => + this.toABIEncodedType(fieldT, encoderVersion, normalizePointers) + ) + ); + } + } + + return type; + } + + /** + * Returns canonical representation of the signature as string. + * + * NOTE: Empty string will be returned for fallback functions and constructors. + */ + signature( + node: + | FunctionDefinition + | EventDefinition + | ErrorDefinition + | ModifierDefinition + | VariableDeclaration, + encoderVersion: ABIEncoderVersion + ): string { + let args: string[]; + + if (node instanceof VariableDeclaration) { + const [getterArgs] = this.getterArgsAndReturn(node); + + args = getterArgs.map((type) => + abiTypeToCanonicalName(this.toABIEncodedType(type, encoderVersion, true)) + ); + } else { + if (node instanceof FunctionDefinition && (node.name === "" || node.isConstructor)) { + return ""; + } + + // Signatures are computed differently depending on whether this is a library function + // or a contract method + if ( + node.vScope instanceof ContractDefinition && + node.vScope.kind === ContractKind.Library + ) { + args = node.vParameters.vParameters.map((arg) => { + const type = this.variableDeclarationToTypeNode(arg); + + return abiTypeToLibraryCanonicalName(type); + }); + } else { + args = node.vParameters.vParameters.map((arg) => { + const type = this.variableDeclarationToTypeNode(arg); + const abiType = this.toABIEncodedType(type, encoderVersion); + + return abiTypeToCanonicalName(generalizeType(abiType)[0]); + }); + } + } + + return node.name + "(" + args.join(",") + ")"; + } + + /** + * Returns HEX string containing first 4 bytes of keccak256 hash function + * applied to the canonical representation of the passed + * function / event / error / modifier or public state variable getter signature. + * + * NOTE: Empty string will be returned for fallback functions and constructors. + */ + signatureHash( + node: + | FunctionDefinition + | EventDefinition + | ErrorDefinition + | ModifierDefinition + | VariableDeclaration, + encoderVersion: ABIEncoderVersion + ): string { + if (node instanceof FunctionDefinition) { + const signature = this.signature(node, encoderVersion); + + return signature ? encodeFuncSignature(signature) : ""; + } + + if ( + node instanceof VariableDeclaration || + node instanceof ErrorDefinition || + node instanceof ModifierDefinition + ) { + return encodeFuncSignature(this.signature(node, encoderVersion)); + } + + if (node instanceof EventDefinition) { + return encodeEventSignature(this.signature(node, encoderVersion)); + } + + throw new Error(`Unable to compute signature hash for node ${pp(node)}`); + } + + interfaceId( + contract: ContractDefinition, + encoderVersion: ABIEncoderVersion + ): string | undefined { + if ( + contract.kind === ContractKind.Interface || + (contract.kind === ContractKind.Contract && contract.abstract) + ) { + const selectors: string[] = []; + + for (const fn of contract.vFunctions) { + const hash = this.signatureHash(fn, encoderVersion); + + if (hash) { + selectors.push(hash); + } + } + + for (const v of contract.vStateVariables) { + if (v.visibility === StateVariableVisibility.Public) { + selectors.push(this.signatureHash(v, encoderVersion)); + } + } + + return selectors + .map((selector) => BigInt("0x" + selector)) + .reduce((a, b) => a ^ b, 0n) + .toString(16) + .padStart(8, "0"); + } + + return undefined; + } } diff --git a/src/types/typeStrings/index.ts b/src/types/typeStrings/index.ts deleted file mode 100644 index cc1ce513..00000000 --- a/src/types/typeStrings/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./typeString_parser"; diff --git a/src/types/utils.ts b/src/types/utils.ts index 43f3096a..dd012135 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -1,39 +1,37 @@ import Decimal from "decimal.js"; import { gte, lt, satisfies } from "semver"; import { - ArrayTypeName, ContractDefinition, DataLocation, - ElementaryTypeName, EnumDefinition, ErrorDefinition, EventDefinition, + Expression, + ExternalReferenceType, + FunctionCall, + FunctionCallKind, FunctionDefinition, FunctionKind, FunctionStateMutability, - FunctionTypeName, FunctionVisibility, - Mapping, ModifierDefinition, - ParameterList, PragmaDirective, SourceUnit, StructDefinition, - TypeName, - UserDefinedTypeName, - UserDefinedValueTypeDefinition, - VariableDeclaration, - VariableDeclarationStatement + TupleExpression, + VariableDeclaration } from "../ast"; -import { assert, eq, forAll, pp } from "../misc"; -import { types } from "../types/reserved"; +import { assert, eq, forAll, forAny } from "../misc"; +import { types } from "../types"; import { ABIEncoderVersion, ABIEncoderVersions } from "./abi"; import { AddressType, ArrayType, - BoolType, + BuiltinFunctionType, BytesType, FixedBytesType, + FunctionLikeSetType, + FunctionSetType, FunctionType, IntLiteralType, IntType, @@ -50,7 +48,30 @@ import { UserDefinition } from "./ast"; import { VersionDependentType } from "./builtins"; -import { evalConstantExpr } from "./eval_const"; + +export const SUBDENOMINATION_MULTIPLIERS = new Map([ + ["seconds", new Decimal(1)], + ["minutes", new Decimal(60)], + ["hours", new Decimal(3600)], + ["days", new Decimal(24 * 3600)], + ["weeks", new Decimal(7 * 24 * 3600)], + ["years", new Decimal(365 * 24 * 3600)], + ["wei", new Decimal(1)], + ["gwei", new Decimal(10 ** 9)], + ["szabo", new Decimal(10 ** 12)], + ["finney", new Decimal(10).toPower(15)], + ["ether", new Decimal(10).toPower(18)] +]); + +export const CALL_BUILTINS = ["call", "callcode", "staticcall", "delegatecall", "transfer", "send"]; + +export const BINARY_OPERATOR_GROUPS = { + Arithmetic: ["+", "-", "*", "/", "%", "**"], + Bitwise: ["<<", ">>", "&", "|", "^"], + Comparison: ["<", ">", "<=", ">="], + Equality: ["==", "!="], + Logical: ["&&", "||"] +}; export function getTypeForCompilerVersion( typing: VersionDependentType, @@ -61,6 +82,78 @@ export function getTypeForCompilerVersion( return satisfies(compilerVersion, version) ? type : undefined; } +/** + * Given 2 function pointer's visibilities infer a common visibility thats compatible with both. + * This is used to infer the visibility of the expression `flag ? fun1 : fun2` where fun1 and fun2 are + * function pointers. + */ +export function inferCommonVisiblity( + a: FunctionVisibility, + b: FunctionVisibility +): FunctionVisibility | undefined { + const visiblityOrder = [ + FunctionVisibility.External, + FunctionVisibility.Public, + FunctionVisibility.Internal, + FunctionVisibility.Default, + FunctionVisibility.Private + ]; + + if (a == b) { + return a; + } + + if (visiblityOrder.indexOf(a) > visiblityOrder.indexOf(b)) { + [b, a] = [a, b]; + } + + if (a === FunctionVisibility.External) { + return b == FunctionVisibility.Public ? FunctionVisibility.External : undefined; + } + + return FunctionVisibility.Internal; +} + +/** + * Given two `FunctionType`s/`BuiltinFunctionType`s/`FunctionSetType`s `a` and `b` + * return a `FunctionSetType` that includes everything in `a` and `b`. + */ +export function mergeFunTypes( + a: FunctionType | BuiltinFunctionType | FunctionSetType, + b: FunctionType | BuiltinFunctionType | FunctionSetType +): FunctionSetType { + const funs: Array = []; + + if (a instanceof FunctionType || a instanceof BuiltinFunctionType) { + funs.push(a); + } else { + funs.push(...a.defs); + } + + if (b instanceof FunctionType || b instanceof BuiltinFunctionType) { + funs.push(b); + } else { + funs.push(...b.defs); + } + + return new FunctionLikeSetType(funs); +} + +/** + * Strip any singleton parens from expressions. I.e. given (((e))) returns e. + */ +export function stripSingletonParens(e: Expression): Expression { + while (e instanceof TupleExpression && e.vOriginalComponents.length === 1) { + const comp = e.vOriginalComponents[0]; + + assert(comp !== null, 'Unexpected "null" component in tuple with single element'); + + e = comp; + } + + return e; +} + /** * Given a general type 'pattern' that doesn't contain any data locations, and a data location, * produce a concrete instance of the general type for the target location. @@ -174,117 +267,6 @@ export function getFQDefName(def: NamedDefinition): string { return def.vScope instanceof ContractDefinition ? `${def.vScope.name}.${def.name}` : def.name; } -/** - * Convert a given ast `TypeName` into a `TypeNode`. This produces "general - * type patterns" without any specific storage information. - * - * @param astT - original AST `TypeName` - * @returns equivalent `TypeNode`. - * - * @deprecated Use `InferType.typeOf()` instead. - */ -export function typeNameToTypeNode(astT: TypeName): TypeNode { - if (astT instanceof ElementaryTypeName) { - const name = astT.name.trim(); - - if (name === "bool") { - return new BoolType(); - } - - const rxAddress = /^address *(payable)?$/; - - if (rxAddress.test(name)) { - return new AddressType(astT.stateMutability === "payable"); - } - - const rxInt = /^(u?)int([0-9]*)$/; - - let m = name.match(rxInt); - - if (m !== null) { - const signed = m[1] !== "u"; - const nBits = m[2] === "" ? 256 : parseInt(m[2]); - - return new IntType(nBits, signed); - } - - const rxFixedBytes = /^bytes([0-9]+)$/; - - m = name.match(rxFixedBytes); - - if (m !== null) { - const size = parseInt(m[1]); - - return new FixedBytesType(size); - } - - if (name === "byte") { - return new FixedBytesType(1); - } - - if (name === "bytes") { - return new BytesType(); - } - - if (name === "string") { - return new StringType(); - } - - throw new Error(`NYI converting elementary AST Type ${name}`); - } - - if (astT instanceof ArrayTypeName) { - const elT = typeNameToTypeNode(astT.vBaseType); - - let size: bigint | undefined; - - if (astT.vLength) { - const result = evalConstantExpr(astT.vLength); - - assert(typeof result === "bigint", "Expected bigint for size of an array type", astT); - - size = result; - } - - return new ArrayType(elT, size); - } - - if (astT instanceof UserDefinedTypeName) { - const def = astT.vReferencedDeclaration; - - if ( - def instanceof StructDefinition || - def instanceof EnumDefinition || - def instanceof ContractDefinition || - def instanceof UserDefinedValueTypeDefinition - ) { - return new UserDefinedType(getFQDefName(def), def); - } - - throw new Error(`NYI typechecking of user-defined type ${def.print()}`); - } - - if (astT instanceof FunctionTypeName) { - /** - * `vType` is always defined here for parameters if a function type. - * Even in 0.4.x can't have function declarations with `var` args. - */ - const args = astT.vParameterTypes.vParameters.map(variableDeclarationToTypeNode); - const rets = astT.vReturnParameterTypes.vParameters.map(variableDeclarationToTypeNode); - - return new FunctionType(undefined, args, rets, astT.visibility, astT.stateMutability); - } - - if (astT instanceof Mapping) { - const keyT = typeNameToTypeNode(astT.vKeyType); - const valueT = typeNameToTypeNode(astT.vValueType); - - return new MappingType(keyT, valueT); - } - - throw new Error(`NYI converting AST Type ${astT.print()} to SType`); -} - export function isReferenceType(generalT: TypeNode): boolean { return ( (generalT instanceof UserDefinedType && generalT.definition instanceof StructDefinition) || @@ -294,69 +276,6 @@ export function isReferenceType(generalT: TypeNode): boolean { ); } -/** - * Computes a `TypeNode` equivalent of given `astT`, - * specialized for location `loc` (if applicable). - * - * @deprecated Use `InferType.typeOf()` instead. - */ -export function typeNameToSpecializedTypeNode(astT: TypeName, loc: DataLocation): TypeNode { - return specializeType(typeNameToTypeNode(astT), loc); -} - -/** - * @deprecated Use `InferType.inferVariableDeclLocation()` instead. - */ -export function inferVariableDeclLocation(decl: VariableDeclaration): DataLocation { - if (decl.stateVariable) { - return decl.constant ? DataLocation.Memory : DataLocation.Storage; - } - - if (decl.storageLocation !== DataLocation.Default) { - return decl.storageLocation; - } - - if (decl.parent instanceof ParameterList) { - // In 0.4.x param/return locations may be omitted. We assume calldata - // for external and memory for the rest - const fun = decl.parent.parent as FunctionDefinition; - - return fun.visibility === FunctionVisibility.External - ? DataLocation.CallData - : DataLocation.Memory; - } - - if (decl.parent instanceof VariableDeclarationStatement) { - // In 0.4.x local var locations may be omitted. We assume memory. - return DataLocation.Memory; - } - - if (decl.parent instanceof StructDefinition) { - return DataLocation.Default; - } - - if (decl.parent instanceof SourceUnit) { - // Global vars don't have a location (no ref types yet) - return DataLocation.Default; - } - - throw new Error(`NYI variable declaration ${pp(decl)}`); -} - -/** - * Given a `VariableDeclaration` node `decl` compute the `TypeNode` that corresponds to the variable. - * This takes into account the storage location of the `decl`. - * - * @deprecated Use `InferType.variableDeclarationToTypeNode()` instead. - */ -export function variableDeclarationToTypeNode(decl: VariableDeclaration): TypeNode { - assert(decl.vType !== undefined, "Expected {0} to have type", decl); - - const loc = inferVariableDeclLocation(decl); - - return typeNameToSpecializedTypeNode(decl.vType, loc); -} - export function enumToIntType(decl: EnumDefinition): IntType { const length = decl.children.length; @@ -429,6 +348,25 @@ export function getABIEncoderVersion( return lt(compilerVersion, "0.8.0") ? ABIEncoderVersion.V1 : ABIEncoderVersion.V2; } +export function isFunctionCallExternal(call: FunctionCall): boolean { + if (call.kind !== FunctionCallKind.FunctionCall) { + return false; + } + + if ( + call.vFunctionCallType === ExternalReferenceType.Builtin && + CALL_BUILTINS.includes(call.vFunctionName) + ) { + return true; + } + + if (call.vExpression.typeString.includes(FunctionVisibility.External)) { + return true; + } + + return false; +} + export function getFallbackRecvFuns(contract: ContractDefinition): FunctionDefinition[] { const res: FunctionDefinition[] = []; @@ -487,8 +425,8 @@ export function castable(fromT: TypeNode, toT: TypeNode, compilerVersion: string if (fromT instanceof StringLiteralType) { /** * @todo Should we make an explicit check that string literal fits to bytes size? - * Note that string length is not the same as count ob bytes in string due to multibyte chars. - * Also for hex string literals we should check evenness of length + * Note that string length is not the same as count of bytes in string due to multibyte chars. + * Also for hex string literals we should check evenness of length. */ if (toT instanceof FixedBytesType) { return true; @@ -570,13 +508,11 @@ export function castable(fromT: TypeNode, toT: TypeNode, compilerVersion: string if (fromT instanceof UserDefinedType && fromT.definition instanceof ContractDefinition) { if (toT instanceof AddressType) { - // We can implicitly cast from contract to payable address if it has a payable recieve/fallback function + // We can implicitly cast from contract to payable address if it has a payable receive/fallback function if (toT.payable) { - const fns = getFallbackRecvFuns(fromT.definition); - - return ( - fns.length > 0 && - forAll(fns, (fn) => fn.stateMutability === FunctionStateMutability.Payable) + return forAny( + getFallbackRecvFuns(fromT.definition), + (fn) => fn.stateMutability === FunctionStateMutability.Payable ); } diff --git a/test/integration/types/external_calls.spec.ts b/test/integration/types/external_calls.spec.ts new file mode 100644 index 00000000..5a6ab4b4 --- /dev/null +++ b/test/integration/types/external_calls.spec.ts @@ -0,0 +1,112 @@ +import expect from "expect"; +import { + assert, + ASTKind, + ASTReader, + ASTWriter, + compileSourceString, + DefaultASTWriterMapping, + detectCompileErrors, + FunctionCall, + isFunctionCallExternal, + PrettyFormatter +} from "../../../src"; + +const samples: Array<[string, string, string[]]> = [ + [ + "case_a.sol", + `pragma solidity 0.6.0; + +contract Foo { + function a() public {} + function b() public {} +} + +contract Main { + function c() public {} + function d() public {} + + function main() public payable { + Foo f = new Foo(); + + c(); + this.c(); + + function () internal fIntPtr = c; + + fIntPtr(); + + fIntPtr = d; + + fIntPtr(); + + (true ? c : d)(); + + f.a(); + f.b(); + + function () external fExtPtr = f.a; + + fExtPtr(); + + fExtPtr = f.b; + fExtPtr(); + + fExtPtr = this.c; + fExtPtr(); + + (true ? this.c : this.d)(); + (false ? f.a : f.b)(); + } +} +`, + [ + "this.c", + "f.a", + "f.b", + "fExtPtr", + "fExtPtr", + "fExtPtr", + "(true ? this.c : this.d)", + "(false ? f.a : f.b)" + ] + ] +]; + +describe("isFunctionCallExternal()", () => { + for (const [sample, content, expected] of samples) { + it(`${sample} produces ${JSON.stringify(expected)}`, async () => { + const { data, compilerVersion } = await compileSourceString( + "sample.sol", + content, + "auto" + ); + + const errors = detectCompileErrors(data); + + expect(errors).toHaveLength(0); + + const reader = new ASTReader(); + const units = reader.read(data, ASTKind.Any); + + expect(units).toHaveLength(1); + + assert(compilerVersion !== undefined, "Expected compiler version to be defined"); + + const writer = new ASTWriter( + DefaultASTWriterMapping, + new PrettyFormatter(4, 0), + compilerVersion + ); + + const actual = units[0] + .getChildrenBySelector( + (node): node is FunctionCall => + node instanceof FunctionCall && isFunctionCallExternal(node) + ) + .map((node) => writer.write(node.vExpression)); + + expect(actual).toEqual(expected); + }); + } +}); diff --git a/test/integration/types/infer.spec.ts b/test/integration/types/infer.spec.ts index 769c5b35..73faf7e2 100644 --- a/test/integration/types/infer.spec.ts +++ b/test/integration/types/infer.spec.ts @@ -51,19 +51,18 @@ import { IntLiteralType, IntType, isVisiblityExternallyCallable, - ModuleType, PackedArrayType, - parse, PointerType, RationalLiteralType, StringLiteralType, - SyntaxError, + SuperType, TupleType, TypeNameType, TypeNode, UserDefinedType } from "../../../src/types"; -import { SuperType } from "../../../src/types/ast/super"; +import { ModuleType } from "../../utils/typeStrings/ast/module_type"; +import { parse, SyntaxError } from "../../utils/typeStrings/typeString_parser"; export const samples: string[] = [ "./test/samples/solidity/compile_04.sol", @@ -406,8 +405,7 @@ function compareTypeNodes( } /// For imports we use the slightly richer ImportRefType while - /// the string parser returns the simpler ModuleType. ModuleType should - /// be considered deprecated + /// the string parser returns the simpler ModuleType. if ( inferredT instanceof ImportRefType && parsedT instanceof ModuleType && @@ -636,7 +634,7 @@ function compareTypeNodes( return eq(inferredT, parsedT); } -export const ENV_CUSTOM_PATH = "SOLC_TEST_SAMPLES_PATH"; +const ENV_CUSTOM_PATH = "SOLC_TEST_SAMPLES_PATH"; describe("Type inference for expressions", () => { const path = process.env[ENV_CUSTOM_PATH]; @@ -649,7 +647,7 @@ describe("Type inference for expressions", () => { : samples; for (const sample of sampleList) { - it(`${sample}`, async () => { + it(sample, async () => { let result: CompileResult; let compilerVersion: string | undefined; let data: any; @@ -691,22 +689,20 @@ describe("Type inference for expressions", () => { expect(errors).toHaveLength(0); - assert(compilerVersion !== undefined, "Expected compiler version to be set to precise"); + assert(compilerVersion !== undefined, "Expected compiler version to be defined"); - const astKind = lt(compilerVersion as string, "0.5.0") - ? ASTKind.Legacy - : ASTKind.Modern; + const astKind = lt(compilerVersion, "0.5.0") ? ASTKind.Legacy : ASTKind.Modern; const reader = new ASTReader(); const sourceUnits = reader.read(data, astKind); - const infer = new InferType(compilerVersion); + const inference = new InferType(compilerVersion); for (const unit of sourceUnits) { for (const expr of unit.getChildrenBySelector( (child) => child instanceof Expression )) { - const inferredType = infer.typeOf(expr); + const inferredType = inference.typeOf(expr); // typeStrings for Identifiers in ImportDirectives may be undefined. if (expr.typeString === undefined) { @@ -733,7 +729,7 @@ describe("Type inference for expressions", () => { try { parsedType = parse(expr.typeString, { ctx: expr, - version: compilerVersion + inference }); } catch (e) { if (e instanceof SyntaxError) { diff --git a/test/integration/types/typestrings.spec.ts b/test/integration/types/typestrings.spec.ts index e162ebcf..04732dca 100644 --- a/test/integration/types/typestrings.spec.ts +++ b/test/integration/types/typestrings.spec.ts @@ -18,16 +18,14 @@ import { Identifier, ModifierInvocation, PossibleCompilerKinds, - VariableDeclaration -} from "../../../src"; -import { - generalizeType, - getNodeType, + VariableDeclaration, + InferType, MappingType, PointerType, specializeType, - variableDeclarationToTypeNode -} from "../../../src/types"; + generalizeType +} from "../../../src"; +import { getNodeType } from "../../utils/typeStrings/typeString_parser"; const samples: Array<[string, string, ASTKind]> = [ [ @@ -129,6 +127,7 @@ describe("Round-trip tests for typestring parser/printer", () => { ); expect(result.compilerVersion).toEqual(compilerVersion); + const errors = detectCompileErrors(result.data); expect(errors).toHaveLength(0); @@ -138,6 +137,8 @@ describe("Round-trip tests for typestring parser/printer", () => { const reader = new ASTReader(); const sourceUnits = reader.read(data, astKind); + const inference = new InferType(compilerVersion); + for (const unit of sourceUnits) { for (const node of unit.getChildrenBySelector( (child) => @@ -155,7 +156,7 @@ describe("Round-trip tests for typestring parser/printer", () => { continue; } - const typeNode = getNodeType(typedASTNode, compilerVersion); + const typeNode = getNodeType(typedASTNode, inference); // Edge case: We don't fully model type strings for external function type names. // External function type strings contain the funtion name as well, which we ignore @@ -198,7 +199,7 @@ describe("Round-trip tests for typestring parser/printer", () => { typedASTNode.vReferencedDeclaration instanceof VariableDeclaration && typedASTNode.vReferencedDeclaration.vType !== undefined ) { - const compType2 = variableDeclarationToTypeNode( + const compType2 = inference.variableDeclarationToTypeNode( typedASTNode.vReferencedDeclaration ); diff --git a/test/unit/ast/dispatch.spec.ts b/test/unit/ast/dispatch.spec.ts index e9627a52..311b55f6 100644 --- a/test/unit/ast/dispatch.spec.ts +++ b/test/unit/ast/dispatch.spec.ts @@ -3,10 +3,12 @@ import { ASTNodeConstructor, ASTReader, compileJson, + CompilerVersions05, ContractDefinition, EmitStatement, EventDefinition, FunctionDefinition, + InferType, ModifierDefinition, resolve, resolveByName, @@ -24,6 +26,8 @@ describe("Dynamic dispatch AST utils", async () => { const [mainUnit] = reader.read(data); const [a, b, c, d, i] = mainUnit.vContracts; + const inference = new InferType(CompilerVersions05[CompilerVersions05.length - 1]); + describe("resolve()", () => { const cases: Array< [ @@ -82,7 +86,7 @@ describe("Dynamic dispatch AST utils", async () => { const definer = resolvable.vScope as ContractDefinition; it(`${resolvable.name} of ${definer.name} for ${scope.name}`, () => { - const node = resolve(scope, resolvable, onlyParents); + const node = resolve(scope, resolvable, inference, onlyParents); if (expectation === undefined) { expect(node === undefined).toEqual(true); @@ -137,7 +141,7 @@ describe("Dynamic dispatch AST utils", async () => { for (const [scope, kind, name, onlyParents, expectations] of cases) { it(`${kind.name} ${name} for ${scope.name} (only parents: ${onlyParents})`, () => { - const result = resolveByName(scope, kind, name, onlyParents); + const result = resolveByName(scope, kind, name, inference, onlyParents); expect(result.length).toEqual(expectations.length); @@ -168,7 +172,7 @@ describe("Dynamic dispatch AST utils", async () => { for (const [scope, stmt, id] of cases) { it(`${stmt.type}#${stmt.id} for ${scope.name}`, () => { - const node = resolveEvent(scope, stmt); + const node = resolveEvent(scope, stmt, inference); expect(node).toBeInstanceOf(EventDefinition); expect((node as EventDefinition).id).toEqual(id); @@ -217,7 +221,7 @@ describe("Dynamic dispatch AST utils", async () => { const definer = resolvable.vScope as ContractDefinition; it(`${resolvable.name} of ${definer.name} for ${scope.name}`, () => { - const node = resolveCallable(scope, resolvable, onlyParents); + const node = resolveCallable(scope, resolvable, inference, onlyParents); if (expectation === undefined) { expect(node === undefined).toEqual(true); diff --git a/test/unit/ast/reading/declaration/contract_0413.spec.ts b/test/unit/ast/reading/declaration/contract_0413.spec.ts index 6f2cf3b7..1811e03f 100644 --- a/test/unit/ast/reading/declaration/contract_0413.spec.ts +++ b/test/unit/ast/reading/declaration/contract_0413.spec.ts @@ -1,6 +1,5 @@ import expect from "expect"; import { ASTReader, compileJson, ContractDefinition, SourceUnit } from "../../../../../src"; -import { ABIEncoderVersion } from "../../../../../src/types/abi"; describe("ContractDefinition (Solc 0.4.13)", () => { const sample = "test/samples/solidity/declarations/contract_0413.json"; @@ -45,12 +44,6 @@ describe("ContractDefinition (Solc 0.4.13)", () => { expect(contract.vFunctions[0].name).toEqual("add"); expect(contract.vFunctions[0].implemented).toEqual(true); expect(contract.vFunctions[0].isConstructor).toEqual(false); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "add(uint256,uint256)" - ); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "771602f7" - ); expect(contract.getChildren().length).toEqual(16); }); @@ -79,12 +72,6 @@ describe("ContractDefinition (Solc 0.4.13)", () => { expect(contract.vFunctions[0].name).toEqual("some"); expect(contract.vFunctions[0].implemented).toEqual(false); expect(contract.vFunctions[0].isConstructor).toEqual(false); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "some(uint256,uint256)" - ); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "cdb3deb6" - ); expect(contract.getChildren().length).toEqual(9); }); @@ -129,19 +116,11 @@ describe("ContractDefinition (Solc 0.4.13)", () => { expect(contract.vFunctions[0].implemented).toEqual(true); expect(contract.vFunctions[0].isConstructor).toEqual(true); expect(contract.vFunctions[0] === contract.vConstructor).toEqual(true); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual(""); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual(""); expect(contract.vFunctions[1].id).toEqual(71); expect(contract.vFunctions[1].name).toEqual("some"); expect(contract.vFunctions[1].implemented).toEqual(true); expect(contract.vFunctions[1].isConstructor).toEqual(false); - expect(contract.vFunctions[1].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "some(uint256,uint256)" - ); - expect(contract.vFunctions[1].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "cdb3deb6" - ); expect(contract.vModifiers.length).toEqual(0); diff --git a/test/unit/ast/reading/declaration/contract_050.spec.ts b/test/unit/ast/reading/declaration/contract_050.spec.ts index b8e0cc8c..643bcf57 100644 --- a/test/unit/ast/reading/declaration/contract_050.spec.ts +++ b/test/unit/ast/reading/declaration/contract_050.spec.ts @@ -1,6 +1,5 @@ import expect from "expect"; import { ASTReader, compileJson, ContractDefinition, SourceUnit } from "../../../../../src"; -import { ABIEncoderVersion } from "../../../../../src/types/abi"; describe("ContractDefinition (Solc 0.5.0)", () => { const sample = "test/samples/solidity/declarations/contract_050.json"; @@ -45,12 +44,6 @@ describe("ContractDefinition (Solc 0.5.0)", () => { expect(contract.vFunctions[0].name).toEqual("add"); expect(contract.vFunctions[0].implemented).toEqual(true); expect(contract.vFunctions[0].isConstructor).toEqual(false); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "add(uint256,uint256)" - ); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "771602f7" - ); expect(contract.getChildren().length).toEqual(16); }); @@ -79,12 +72,6 @@ describe("ContractDefinition (Solc 0.5.0)", () => { expect(contract.vFunctions[0].name).toEqual("some"); expect(contract.vFunctions[0].implemented).toEqual(false); expect(contract.vFunctions[0].isConstructor).toEqual(false); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "some(uint256,uint256)" - ); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "cdb3deb6" - ); expect(contract.getChildren().length).toEqual(9); }); @@ -128,19 +115,11 @@ describe("ContractDefinition (Solc 0.5.0)", () => { expect(contract.vFunctions[0].implemented).toEqual(true); expect(contract.vFunctions[0].isConstructor).toEqual(true); expect(contract.vFunctions[0] === contract.vConstructor).toEqual(true); - expect(contract.vFunctions[0].canonicalSignature(ABIEncoderVersion.V1)).toEqual(""); - expect(contract.vFunctions[0].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual(""); expect(contract.vFunctions[1].id).toEqual(71); expect(contract.vFunctions[1].name).toEqual("some"); expect(contract.vFunctions[1].implemented).toEqual(true); expect(contract.vFunctions[1].isConstructor).toEqual(false); - expect(contract.vFunctions[1].canonicalSignature(ABIEncoderVersion.V1)).toEqual( - "some(uint256,uint256)" - ); - expect(contract.vFunctions[1].canonicalSignatureHash(ABIEncoderVersion.V1)).toEqual( - "cdb3deb6" - ); expect(contract.vModifiers.length).toEqual(0); diff --git a/test/unit/misc/definitions.spec.ts b/test/unit/misc/definitions.spec.ts index 3054cbe5..66ba2164 100644 --- a/test/unit/misc/definitions.spec.ts +++ b/test/unit/misc/definitions.spec.ts @@ -20,6 +20,7 @@ import { FunctionDefinition, Identifier, IdentifierPath, + InferType, resolveAny, SourceUnit, StateVariableVisibility, @@ -105,6 +106,8 @@ describe("resolveAny() correctly resolves all Identifiers/UserDefinedTypeNames/F const reader = new ASTReader(); const sourceUnits = reader.read(result.data, astKind); + const inference = new InferType(compilerVersion); + for (const unit of sourceUnits) { for (const node of unit.getChildrenBySelector( (child) => @@ -174,7 +177,7 @@ describe("resolveAny() correctly resolves all Identifiers/UserDefinedTypeNames/F } const expectedID = def.id; - const resolved = [...resolveAny(name, ctx, compilerVersion)]; + const resolved = [...resolveAny(name, ctx, inference)]; expect(resolved.length).toBeGreaterThanOrEqual(1); @@ -421,6 +424,7 @@ describe("resolveAny() unit tests", () => { for (const [sample, compilerVersion, astKind, sampleTests] of unitSamples) { describe(sample, async () => { const reader = new ASTReader(); + const inference = new InferType(compilerVersion); before(async () => { const result = await compileSol(sample, "auto"); @@ -438,7 +442,7 @@ describe("resolveAny() unit tests", () => { for (const [name, expectedIds, testName] of unitTests) { it(testName, () => { const ctxNode = reader.context.locate(ctxId); - const resolvedNodes = resolveAny(name, ctxNode, compilerVersion); + const resolvedNodes = resolveAny(name, ctxNode, inference); expect(new Set(expectedIds)).toEqual( new Set([...resolvedNodes].map((node) => node.id)) @@ -451,7 +455,10 @@ describe("resolveAny() unit tests", () => { }); describe("resolveAny() correctly handles visibility", async () => { + const compilerVersion = "0.8.13"; const reader = new ASTReader(); + const inference = new InferType(compilerVersion); + const sample = `contract Base { uint private privX; uint internal intX; @@ -481,7 +488,7 @@ contract Child is Base { let foo: ASTNode; before(async () => { - const compResult = await compileSourceString("sample.sol", sample, "0.8.13"); + const compResult = await compileSourceString("sample.sol", sample, compilerVersion); [unit] = reader.read(compResult.data); foo = unit.getChildrenBySelector( (nd) => nd instanceof FunctionDefinition && nd.name === "foo" @@ -500,7 +507,7 @@ contract Child is Base { ]; for (const [name, expCount] of tests) { - const res = resolveAny(name, foo, "0.8.13"); + const res = resolveAny(name, foo, inference); expect(res.size).toEqual(expCount); } }); @@ -517,7 +524,7 @@ contract Child is Base { ]; for (const [name, expCount] of tests) { - const res = resolveAny(name, foo, "0.8.13", false, true); + const res = resolveAny(name, foo, inference, false, true); expect(res.size).toEqual(expCount); } }); diff --git a/test/unit/misc/pretty_printing.spec.ts b/test/unit/misc/pretty_printing.spec.ts index 1fa7fa00..07cc84f0 100644 --- a/test/unit/misc/pretty_printing.spec.ts +++ b/test/unit/misc/pretty_printing.spec.ts @@ -10,7 +10,6 @@ import { FunctionLikeSetType, FunctionStateMutability, FunctionVisibility, - InaccessibleDynamicType, InferType, IntType, isPPAble, @@ -146,7 +145,6 @@ describe("Utility formatting routines", () => { new FunctionLikeSetType([infer.eventDefToType(evA), infer.eventDefToType(evB)]), "event_set { event evA(), event evB() }" ], - [new InaccessibleDynamicType(), "inaccessible_dynamic_type"], [new TVar("T"), ""] ]; diff --git a/test/unit/types/builtins.spec.ts b/test/unit/types/builtins.spec.ts index b00e951c..4b7e90c2 100644 --- a/test/unit/types/builtins.spec.ts +++ b/test/unit/types/builtins.spec.ts @@ -3,7 +3,6 @@ import { abi, address06Builtins, addressBuiltins, - AddressType, BoolType, BuiltinFunctionType, BuiltinStructType, @@ -11,9 +10,7 @@ import { CompilerVersions, DataLocation, eq, - FixedBytesType, globalBuiltins, - IntType, LatestCompilerVersion, PointerType, TRest, @@ -24,58 +21,53 @@ import { const cases: Array<[BuiltinStructType, string, string[], TypeNode | undefined]> = [ [globalBuiltins, "abi", ["0.4.13", "0.4.21"], undefined], [globalBuiltins, "abi", ["0.4.22", LatestCompilerVersion], abi], - [globalBuiltins, "block.coinbase", ["0.4.13", "0.4.26"], new AddressType(false)], - [globalBuiltins, "block.coinbase", ["0.5.0", LatestCompilerVersion], new AddressType(true)], - [ - globalBuiltins, - "block.difficulty", - ["0.4.13", LatestCompilerVersion], - new IntType(256, false) - ], - [globalBuiltins, "block.gaslimit", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], - [globalBuiltins, "block.number", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], - [globalBuiltins, "block.timestamp", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], + [globalBuiltins, "block.coinbase", ["0.4.13", "0.4.26"], types.address], + [globalBuiltins, "block.coinbase", ["0.5.0", LatestCompilerVersion], types.addressPayable], + [globalBuiltins, "block.difficulty", ["0.4.13", LatestCompilerVersion], types.uint256], + [globalBuiltins, "block.gaslimit", ["0.4.13", LatestCompilerVersion], types.uint256], + [globalBuiltins, "block.number", ["0.4.13", LatestCompilerVersion], types.uint256], + [globalBuiltins, "block.timestamp", ["0.4.13", LatestCompilerVersion], types.uint256], [globalBuiltins, "block.blockhash", ["0.5.0", LatestCompilerVersion], undefined], [ globalBuiltins, "block.blockhash", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("blockhash", [new IntType(256, false)], [new FixedBytesType(32)]) + new BuiltinFunctionType("blockhash", [types.uint256], [types.bytes32]) ], [globalBuiltins, "block.chainid", ["0.4.13", "0.7.6"], undefined], - [globalBuiltins, "block.chainid", ["0.8.0", LatestCompilerVersion], new IntType(256, false)], + [globalBuiltins, "block.chainid", ["0.8.0", LatestCompilerVersion], types.uint256], [globalBuiltins, "block.basefee", ["0.4.13", "0.8.6"], undefined], - [globalBuiltins, "block.basefee", ["0.8.7", LatestCompilerVersion], new IntType(256, false)], + [globalBuiltins, "block.basefee", ["0.8.7", LatestCompilerVersion], types.uint256], [ globalBuiltins, "msg.data", ["0.4.13", LatestCompilerVersion], new PointerType(new BytesType(), DataLocation.CallData) ], - [globalBuiltins, "msg.sender", ["0.4.13", "0.4.26"], new AddressType(false)], - [globalBuiltins, "msg.sender", ["0.5.0", "0.7.6"], new AddressType(true)], - [globalBuiltins, "msg.sender", ["0.8.0", LatestCompilerVersion], new AddressType(false)], - [globalBuiltins, "msg.sig", ["0.4.13", LatestCompilerVersion], new FixedBytesType(4)], - [globalBuiltins, "msg.value", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], + [globalBuiltins, "msg.sender", ["0.4.13", "0.4.26"], types.address], + [globalBuiltins, "msg.sender", ["0.5.0", "0.7.6"], types.addressPayable], + [globalBuiltins, "msg.sender", ["0.8.0", LatestCompilerVersion], types.address], + [globalBuiltins, "msg.sig", ["0.4.13", LatestCompilerVersion], types.bytes4], + [globalBuiltins, "msg.value", ["0.4.13", LatestCompilerVersion], types.uint256], [globalBuiltins, "msg.gas", ["0.5.0", LatestCompilerVersion], undefined], - [globalBuiltins, "msg.gas", ["0.4.13", "0.4.26"], new IntType(256, false)], - [globalBuiltins, "tx.gasprice", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], - [globalBuiltins, "tx.origin", ["0.4.13", "0.4.26"], new AddressType(false)], - [globalBuiltins, "tx.origin", ["0.5.0", "0.7.6"], new AddressType(true)], - [globalBuiltins, "tx.origin", ["0.8.0", LatestCompilerVersion], new AddressType(false)], + [globalBuiltins, "msg.gas", ["0.4.13", "0.4.26"], types.uint256], + [globalBuiltins, "tx.gasprice", ["0.4.13", LatestCompilerVersion], types.uint256], + [globalBuiltins, "tx.origin", ["0.4.13", "0.4.26"], types.address], + [globalBuiltins, "tx.origin", ["0.5.0", "0.7.6"], types.addressPayable], + [globalBuiltins, "tx.origin", ["0.8.0", LatestCompilerVersion], types.address], [globalBuiltins, "blockhash", ["0.4.13", "0.4.21"], undefined], [ globalBuiltins, "blockhash", ["0.4.22", LatestCompilerVersion], - new BuiltinFunctionType("blockhash", [new IntType(256, false)], [new FixedBytesType(32)]) + new BuiltinFunctionType("blockhash", [types.uint256], [types.bytes32]) ], [globalBuiltins, "gasleft", ["0.4.13", "0.4.20"], undefined], [ globalBuiltins, "gasleft", ["0.4.21", LatestCompilerVersion], - new BuiltinFunctionType("gasleft", [], [new IntType(256, false)]) + new BuiltinFunctionType("gasleft", [], [types.uint256]) ], [ globalBuiltins, @@ -91,8 +83,8 @@ const cases: Array<[BuiltinStructType, string, string[], TypeNode | undefined]> ["0.4.13", LatestCompilerVersion], new BuiltinFunctionType( "addmod", - [new IntType(256, false), new IntType(256, false), new IntType(256, false)], - [new IntType(256, false)] + [types.uint256, types.uint256, types.uint256], + [types.uint256] ) ], [ @@ -101,76 +93,64 @@ const cases: Array<[BuiltinStructType, string, string[], TypeNode | undefined]> ["0.4.13", LatestCompilerVersion], new BuiltinFunctionType( "mulmod", - [new IntType(256, false), new IntType(256, false), new IntType(256, false)], - [new IntType(256, false)] + [types.uint256, types.uint256, types.uint256], + [types.uint256] ) ], [ globalBuiltins, "suicide", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("suicide", [new AddressType(false)], []) + new BuiltinFunctionType("suicide", [types.address], []) ], [globalBuiltins, "suicide", ["0.5.0", LatestCompilerVersion], undefined], [ globalBuiltins, "selfdestruct", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("selfdestruct", [new AddressType(false)], []) + new BuiltinFunctionType("selfdestruct", [types.address], []) ], [ globalBuiltins, "selfdestruct", ["0.5.0", LatestCompilerVersion], - new BuiltinFunctionType("selfdestruct", [new AddressType(true)], []) + new BuiltinFunctionType("selfdestruct", [types.addressPayable], []) ], [ globalBuiltins, "keccak256", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("keccak256", [new TRest("T")], [new FixedBytesType(32)]) + new BuiltinFunctionType("keccak256", [new TRest("T")], [types.bytes32]) ], [ globalBuiltins, "keccak256", ["0.5.0", LatestCompilerVersion], - new BuiltinFunctionType( - "keccak256", - [new PointerType(new BytesType(), DataLocation.Memory)], - [new FixedBytesType(32)] - ) + new BuiltinFunctionType("keccak256", [types.bytesMemory], [types.bytes32]) ], [ globalBuiltins, "sha256", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("sha256", [new TRest("T")], [new FixedBytesType(32)]) + new BuiltinFunctionType("sha256", [new TRest("T")], [types.bytes32]) ], [ globalBuiltins, "sha256", ["0.5.0", LatestCompilerVersion], - new BuiltinFunctionType( - "sha256", - [new PointerType(new BytesType(), DataLocation.Memory)], - [new FixedBytesType(32)] - ) + new BuiltinFunctionType("sha256", [types.bytesMemory], [types.bytes32]) ], [ globalBuiltins, "ripemd160", ["0.4.13", "0.4.26"], - new BuiltinFunctionType("ripemd160", [new TRest("T")], [new FixedBytesType(20)]) + new BuiltinFunctionType("ripemd160", [new TRest("T")], [types.bytes20]) ], [ globalBuiltins, "ripemd160", ["0.5.0", LatestCompilerVersion], - new BuiltinFunctionType( - "ripemd160", - [new PointerType(new BytesType(), DataLocation.Memory)], - [new FixedBytesType(20)] - ) + new BuiltinFunctionType("ripemd160", [types.bytesMemory], [types.bytes20]) ], [ globalBuiltins, @@ -178,33 +158,23 @@ const cases: Array<[BuiltinStructType, string, string[], TypeNode | undefined]> ["0.4.13", LatestCompilerVersion], new BuiltinFunctionType( "ecrecover", - [ - new FixedBytesType(32), - new IntType(8, false), - new FixedBytesType(32), - new FixedBytesType(32) - ], - [new AddressType(false)] + [types.bytes32, types.uint8, types.bytes32, types.bytes32], + [types.address] ) ], - [addressBuiltins, "balance", ["0.4.13", LatestCompilerVersion], new IntType(256, false)], + [addressBuiltins, "balance", ["0.4.13", LatestCompilerVersion], types.uint256], [ addressBuiltins, "staticcall", ["0.5.0", LatestCompilerVersion], new BuiltinFunctionType( "staticcall", - [new PointerType(new BytesType(), DataLocation.Memory)], - [new BoolType(), new PointerType(new BytesType(), DataLocation.Memory)] + [types.bytesMemory], + [new BoolType(), types.bytesMemory] ) ], [addressBuiltins, "code", ["0.4.13", "0.7.6"], undefined], - [ - address06Builtins, - "code", - ["0.8.0", LatestCompilerVersion], - new PointerType(new BytesType(), DataLocation.Memory) - ] + [address06Builtins, "code", ["0.8.0", LatestCompilerVersion], types.bytesMemory] ]; describe("getTypeForCompilerVersion() and builtin types", () => { diff --git a/test/unit/types/castable.spec.ts b/test/unit/types/castable.spec.ts index 59e35f4d..ca407f8e 100644 --- a/test/unit/types/castable.spec.ts +++ b/test/unit/types/castable.spec.ts @@ -1,9 +1,7 @@ import { expect } from "expect"; import { - AddressType, ArrayType, ASTNodeFactory, - BytesType, castable, CompilerVersions04, CompilerVersions05, @@ -20,6 +18,7 @@ import { PointerType, StringLiteralType, TypeNode, + types, UserDefinedType } from "../../../src"; @@ -32,53 +31,43 @@ const cases: Array< ] > = [ [ - new PointerType(new ArrayType(new IntType(8, false)), DataLocation.Memory), - new PointerType(new ArrayType(new IntType(8, false)), DataLocation.CallData), + new PointerType(new ArrayType(types.uint8), DataLocation.Memory), + new PointerType(new ArrayType(types.uint8), DataLocation.CallData), LatestCompilerVersion, true ], [ - new PointerType(new ArrayType(new IntType(8, false)), DataLocation.Memory), + new PointerType(new ArrayType(types.uint8), DataLocation.Memory), new PointerType(new ArrayType(new IntType(8, true)), DataLocation.CallData), LatestCompilerVersion, false ], - [new StringLiteralType("string"), new FixedBytesType(32), LatestCompilerVersion, true], - [new StringLiteralType("hexString"), new FixedBytesType(32), LatestCompilerVersion, true], - [ - new StringLiteralType("string"), - new PointerType(new BytesType(), DataLocation.Memory), - LatestCompilerVersion, - true - ], - [ - new StringLiteralType("hexString"), - new PointerType(new BytesType(), DataLocation.CallData), - LatestCompilerVersion, - true - ], + [new StringLiteralType("string"), types.bytes32, LatestCompilerVersion, true], + [new StringLiteralType("hexString"), types.bytes32, LatestCompilerVersion, true], + [new StringLiteralType("string"), types.bytesMemory, LatestCompilerVersion, true], + [new StringLiteralType("hexString"), types.bytesCalldata, LatestCompilerVersion, true], [new IntLiteralType(0xffn), new FixedBytesType(1), LatestCompilerVersion, true], [new IntLiteralType(-1n), new FixedBytesType(1), LatestCompilerVersion, false], [new IntLiteralType(0xffffn), new IntType(16, false), LatestCompilerVersion, true], - [new IntLiteralType(0n), new AddressType(false), CompilerVersions05[0], false], + [new IntLiteralType(0n), types.address, CompilerVersions05[0], false], [ new IntLiteralType(0n), - new AddressType(false), + types.address, CompilerVersions04[CompilerVersions04.length - 1], true ], - [new AddressType(true), new AddressType(false), LatestCompilerVersion, true], - [new AddressType(false), new AddressType(true), LatestCompilerVersion, false], + [types.addressPayable, types.address, LatestCompilerVersion, true], + [types.address, types.addressPayable, LatestCompilerVersion, false], [new FixedBytesType(12), new FixedBytesType(24), LatestCompilerVersion, true], [new FixedBytesType(24), new FixedBytesType(12), LatestCompilerVersion, false], [new IntType(8, true), new IntType(16, true), LatestCompilerVersion, true], - [new IntType(8, false), new IntType(16, false), LatestCompilerVersion, true], + [types.uint8, new IntType(16, false), LatestCompilerVersion, true], [new IntType(16, true), new IntType(8, true), LatestCompilerVersion, false], - [new IntType(16, false), new IntType(8, false), LatestCompilerVersion, false], - [new IntType(8, false), new AddressType(false), LatestCompilerVersion, true], - [new IntType(160, false), new AddressType(false), LatestCompilerVersion, true], - [new IntType(256, false), new AddressType(false), LatestCompilerVersion, false], - [new IntType(8, true), new AddressType(false), LatestCompilerVersion, false], + [new IntType(16, false), types.uint8, LatestCompilerVersion, false], + [types.uint8, types.address, LatestCompilerVersion, true], + [types.uint160, types.address, LatestCompilerVersion, true], + [types.uint256, types.address, LatestCompilerVersion, false], + [new IntType(8, true), types.address, LatestCompilerVersion, false], [ (factory) => { const c = factory.makeContractDefinition( @@ -95,7 +84,7 @@ const cases: Array< return new UserDefinedType(c.name, c); }, - new AddressType(false), + types.address, LatestCompilerVersion, true ], @@ -115,7 +104,7 @@ const cases: Array< return new UserDefinedType(c.name, c); }, - new AddressType(true), + types.addressPayable, LatestCompilerVersion, false ], @@ -150,7 +139,7 @@ const cases: Array< return new UserDefinedType(c.name, c); }, - new AddressType(true), + types.addressPayable, LatestCompilerVersion, true ], @@ -185,7 +174,7 @@ const cases: Array< return new UserDefinedType(c.name, c); }, - new AddressType(true), + types.addressPayable, LatestCompilerVersion, true ], diff --git a/test/unit/types/getters.spec.ts b/test/unit/types/getters.spec.ts index 5c70250b..3bcdeb6b 100644 --- a/test/unit/types/getters.spec.ts +++ b/test/unit/types/getters.spec.ts @@ -1,6 +1,5 @@ import expect from "expect"; import { - AddressType, assert, ASTNodeConstructor, ASTReader, @@ -16,13 +15,16 @@ import { FunctionType, FunctionVisibility, getFQDefName, + InferType, IntType, + LatestCompilerVersion, PointerType, PossibleCompilerKinds, SourceUnit, StringType, StructDefinition, TypeNode, + types, UserDefinedType, UserDefinedValueTypeDefinition, UserDefinition, @@ -67,8 +69,8 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ "a", new FunctionType( "a", - [new IntType(256, false)], - [new IntType(256, false)], + [types.uint256], + [types.uint256], FunctionVisibility.External, FunctionStateMutability.View ) @@ -77,8 +79,8 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ "b", new FunctionType( "b", - [new AddressType(false)], - [new IntType(256, false)], + [types.address], + [types.uint256], FunctionVisibility.External, FunctionStateMutability.View ) @@ -116,7 +118,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ new FunctionType( "e", [], - [new AddressType(false)], + [types.address], FunctionVisibility.External, FunctionStateMutability.View ) @@ -128,7 +130,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ return new FunctionType( "f", - [new IntType(256, false)], + [types.uint256], [ new IntType(8, true), new PointerType(new StringType(), DataLocation.Memory), @@ -149,7 +151,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ return new FunctionType( "g", - [new IntType(256, false)], + [types.uint256], [new UserDefinedType(def.name, def)], FunctionVisibility.External, FunctionStateMutability.View @@ -262,7 +264,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ return new FunctionType( "udtvMapping", - [new UserDefinedType(getFQDefName(defA), defA), new IntType(256, false)], + [new UserDefinedType(getFQDefName(defA), defA), types.uint256], [new UserDefinedType(getFQDefName(defU), defU)], FunctionVisibility.External, FunctionStateMutability.View @@ -287,7 +289,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ new UserDefinedType(getFQDefName(def), def), DataLocation.Memory ), - new IntType(256, false) + types.uint256 ], FunctionVisibility.External, FunctionStateMutability.View @@ -303,8 +305,8 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ "a", new FunctionType( "a", - [new IntType(256, false)], - [new IntType(256, false)], + [types.uint256], + [types.uint256], FunctionVisibility.External, FunctionStateMutability.View ) @@ -313,8 +315,8 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ "b", new FunctionType( "b", - [new AddressType(false)], - [new IntType(256, false)], + [types.address], + [types.uint256], FunctionVisibility.External, FunctionStateMutability.View ) @@ -352,7 +354,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ new FunctionType( "e", [], - [new AddressType(false)], + [types.address], FunctionVisibility.External, FunctionStateMutability.View ) @@ -364,7 +366,7 @@ const cases: Array<[string, Array<[string, TypeNode | DeferredTypeNode]>]> = [ return new FunctionType( "f", - [new IntType(256, false)], + [types.uint256], [new UserDefinedType(def.name, def)], FunctionVisibility.External, FunctionStateMutability.View @@ -380,9 +382,10 @@ describe("getterFunType()", () => { for (const kind of PossibleCompilerKinds) { describe(`[${kind}] sample`, () => { let unit: SourceUnit; + let inference: InferType; before(async () => { - const { data } = await compileSol( + const { data, compilerVersion } = await compileSol( sample, "auto", undefined, @@ -401,6 +404,8 @@ describe("getterFunType()", () => { expect(units.length).toEqual(1); unit = units[0]; + + inference = new InferType(compilerVersion || LatestCompilerVersion); }); for (const [stateVarName, typing] of mapping) { @@ -409,7 +414,7 @@ describe("getterFunType()", () => { }`, () => { const expectedType = typing instanceof TypeNode ? typing : typing(unit); const stateVar = getStateVar(unit, stateVarName); - const resultType = stateVar.getterFunType(); + const resultType = inference.getterFunType(stateVar); assert( eq(resultType, expectedType), diff --git a/test/unit/types/signatures.spec.ts b/test/unit/types/signatures.spec.ts index a7656a47..1196bbe4 100644 --- a/test/unit/types/signatures.spec.ts +++ b/test/unit/types/signatures.spec.ts @@ -1,6 +1,7 @@ import expect from "expect"; import { lt } from "semver"; import { + ABIEncoderVersion, AnyResolvable, assert, ASTKind, @@ -13,17 +14,15 @@ import { ErrorDefinition, EventDefinition, FunctionDefinition, - FunctionStateMutability, + FunctionLikeType, FunctionType, - FunctionVisibility, generalizeType, + InferType, PossibleCompilerKinds, resolveAny, SourceUnit, - VariableDeclaration, - variableDeclarationToTypeNode + VariableDeclaration } from "../../../src"; -import { ABIEncoderVersion } from "../../../src/types/abi"; const samples: Array<[string, string, ABIEncoderVersion]> = [ [ @@ -50,14 +49,14 @@ function resolveOne( name: string, contractName: string, unit: SourceUnit, - compilerVersion: string + inference: InferType ): AnyResolvable | undefined { - const contracts = [...resolveAny(contractName, unit, compilerVersion, true)]; + const contracts = [...resolveAny(contractName, unit, inference, true)]; assert(contracts.length === 1, `Contract ${contractName} not found in ${unit.sourceEntryKey}`); const contract = contracts[0] as ContractDefinition; - const defs = [...resolveAny(name, contract, compilerVersion, true)]; + const defs = [...resolveAny(name, contract, inference, true)]; if (defs.length === 0) { return undefined; @@ -100,6 +99,8 @@ describe("Check canonical signatures are generated correctly", () => { const sourceUnits = reader.read(data, ASTKind.Any); const unit = sourceUnits[0]; + const inference = new InferType(compilerVersion); + const runTestsHelper = ( contractName: string, functionHashes: any, @@ -107,7 +108,7 @@ describe("Check canonical signatures are generated correctly", () => { ) => { for (const expectedSignature in functionHashes) { const defName = expectedSignature.slice(0, expectedSignature.indexOf("(")); - const def = resolveOne(defName, contractName, unit, compilerVersion); + const def = resolveOne(defName, contractName, unit, inference); if (def === undefined) { continue; @@ -115,10 +116,11 @@ describe("Check canonical signatures are generated correctly", () => { let signature: string; - if (def instanceof VariableDeclaration) { - signature = def.getterCanonicalSignature(encoderVer); - } else if (def instanceof FunctionDefinition) { - signature = def.canonicalSignature(encoderVer); + if ( + def instanceof VariableDeclaration || + def instanceof FunctionDefinition + ) { + signature = inference.signature(def, encoderVer); } else { throw new Error(`NYI: ${def.print()}`); } @@ -141,42 +143,22 @@ describe("Check canonical signatures are generated correctly", () => { continue; } - const def = resolveOne(abiEntry.name, contractName, unit, compilerVersion); + const def = resolveOne(abiEntry.name, contractName, unit, inference); if (def === undefined) { continue; } - let funT: FunctionType; + let funT: FunctionType | FunctionLikeType; if (def instanceof VariableDeclaration) { - funT = def.getterFunType(); + funT = inference.getterFunType(def); } else if (def instanceof FunctionDefinition) { - funT = new FunctionType( - def.name, - def.vParameters.vParameters.map(variableDeclarationToTypeNode), - def.vReturnParameters.vParameters.map( - variableDeclarationToTypeNode - ), - def.visibility, - def.stateMutability - ); + funT = inference.funDefToType(def); } else if (def instanceof EventDefinition) { - funT = new FunctionType( - def.name, - def.vParameters.vParameters.map(variableDeclarationToTypeNode), - [], - FunctionVisibility.Default, - FunctionStateMutability.View - ); + funT = inference.eventDefToType(def); } else if (def instanceof ErrorDefinition) { - funT = new FunctionType( - def.name, - def.vParameters.vParameters.map(variableDeclarationToTypeNode), - [], - FunctionVisibility.Default, - FunctionStateMutability.View - ); + funT = inference.errDefToType(def); } else { throw new Error(`NYI: ${def.print()}`); } @@ -190,6 +172,13 @@ describe("Check canonical signatures are generated correctly", () => { } if (abiEntry.type === "function") { + assert( + funT instanceof FunctionType, + "Expected function type, got {0} for {1}", + funT, + def + ); + expect(funT.returns.length).toEqual(abiEntry.outputs.length); for (let i = 0; i < funT.returns.length; i++) { diff --git a/src/types/ast/internal/inaccessible_dynamic_type.ts b/test/utils/typeStrings/ast/inaccessible_dynamic_type.ts similarity index 74% rename from src/types/ast/internal/inaccessible_dynamic_type.ts rename to test/utils/typeStrings/ast/inaccessible_dynamic_type.ts index 37c5cece..13eebd83 100644 --- a/src/types/ast/internal/inaccessible_dynamic_type.ts +++ b/test/utils/typeStrings/ast/inaccessible_dynamic_type.ts @@ -1,9 +1,8 @@ -import { TypeNode } from "../type"; +import { TypeNode } from "../../../../src"; /** * Place-holder type used only by the typestring parser for * cases when the typestring contains "inaccessible dynamic type". - * @todo move under test/ along with typestring parser */ export class InaccessibleDynamicType extends TypeNode { pp(): string { diff --git a/src/types/ast/module_type.ts b/test/utils/typeStrings/ast/module_type.ts similarity index 56% rename from src/types/ast/module_type.ts rename to test/utils/typeStrings/ast/module_type.ts index 1538a06c..1921a94d 100644 --- a/src/types/ast/module_type.ts +++ b/test/utils/typeStrings/ast/module_type.ts @@ -1,9 +1,5 @@ -import { Range } from "../../misc"; -import { TypeNode } from "./type"; +import { Range, TypeNode } from "../../../../src"; -// NOTE: This class is only used by the TypeString parser and should be -// considered deprecated. -// @deprecated export class ModuleType extends TypeNode { readonly path: string; diff --git a/src/types/typeStrings/typeString_grammar.pegjs b/test/utils/typeStrings/typeString_grammar.pegjs similarity index 98% rename from src/types/typeStrings/typeString_grammar.pegjs rename to test/utils/typeStrings/typeString_grammar.pegjs index 26222d9b..7dd87df4 100644 --- a/src/types/typeStrings/typeString_grammar.pegjs +++ b/test/utils/typeStrings/typeString_grammar.pegjs @@ -290,7 +290,7 @@ UserDefinedType = return makeUserDefinedType( name, StructDefinition, - options.version, + options.inference, options.ctx ); } @@ -298,7 +298,7 @@ UserDefinedType = return makeUserDefinedType( name, EnumDefinition, - options.version, + options.inference, options.ctx ); } @@ -306,7 +306,7 @@ UserDefinedType = return makeUserDefinedType( name, ContractDefinition, - options.version, + options.inference, options.ctx ); } @@ -314,14 +314,14 @@ UserDefinedType = return makeUserDefinedType( name, ContractDefinition, - options.version, + options.inference, options.ctx ); } / name: FQName { return makeUserDefinedType( name, UserDefinedValueTypeDefinition, - options.version, + options.inference, options.ctx ); } diff --git a/src/types/typeStrings/typeString_parser_header.ts b/test/utils/typeStrings/typeString_parser_header.ts similarity index 80% rename from src/types/typeStrings/typeString_parser_header.ts rename to test/utils/typeStrings/typeString_parser_header.ts index ec4d2908..e373e039 100644 --- a/src/types/typeStrings/typeString_parser_header.ts +++ b/test/utils/typeStrings/typeString_parser_header.ts @@ -15,8 +15,6 @@ import { StructDefinition, UserDefinedValueTypeDefinition, VariableDeclaration, -} from "../../ast"; -import { AddressType, ArrayType, BoolType, @@ -24,11 +22,9 @@ import { BytesType, FixedBytesType, FunctionType, - InaccessibleDynamicType, IntLiteralType, IntType, MappingType, - ModuleType, PointerType, RationalLiteralType, StringLiteralType, @@ -36,9 +32,13 @@ import { TupleType, TypeNameType, TypeNode, - UserDefinedType -} from "../ast"; -import { assert, pp } from "../../misc"; + UserDefinedType, + assert, + pp, + InferType +} from "../../../src"; +import { InaccessibleDynamicType } from "./ast/inaccessible_dynamic_type"; +import { ModuleType } from "./ast/module_type"; function getFunctionAttributes( decorators: string[] @@ -99,14 +99,15 @@ function getFunctionAttributes( * * The function uses a parser to process the type string, * while resolving and user-defined type references in the context of `node`. - * + * * @param arg - an AST node with a type string (`Expression` or `VariableDeclaration`) * @param version - compiler version to be used. Useful as resolution rules changed between 0.4.x and 0.5.x. - * - * @deprecated Use `InferType.typeOf()` instead. */ -export function getNodeType(node: Expression | VariableDeclaration, version: string): TypeNode { - return parse(node.typeString, { ctx: node, version }) as TypeNode; +export function getNodeType( + node: Expression | VariableDeclaration, + inference: InferType +): TypeNode { + return parse(node.typeString, { ctx: node, inference }) as TypeNode; } /** @@ -115,36 +116,42 @@ export function getNodeType(node: Expression | VariableDeclaration, version: str * * The function uses a parser to process the type string, * while resolving and user-defined type references in the context of `ctx`. - * + * * @param arg - either a type string, or a node with a type string (`Expression` or `VariableDeclaration`) * @param version - compiler version to be used. Useful as resolution rules changed between 0.4.x and 0.5.x. * @param ctx - `ASTNode` representing the context in which a type string is to be parsed - * - * @deprecated Use `InferType.typeOf()` instead. */ -export function getNodeTypeInCtx(arg: Expression | VariableDeclaration | string, version: string, ctx: ASTNode): TypeNode { +export function getNodeTypeInCtx( + arg: Expression | VariableDeclaration | string, + inference: InferType, + ctx: ASTNode +): TypeNode { const typeString = typeof arg === "string" ? arg : arg.typeString; - return parse(typeString, { ctx, version }) as TypeNode; + return parse(typeString, { ctx, inference }) as TypeNode; } function makeUserDefinedType( name: string, constructor: ASTNodeConstructor, - version: string, + inference: InferType, ctx: ASTNode ): UserDefinedType { - let defs = [...resolveAny(name, ctx, version)]; + let defs = [...resolveAny(name, ctx, inference)]; /** * Note that constructors below 0.5.0 may have same name as contract definition. */ if (constructor === ContractDefinition) { - defs = defs.filter((def) => - def instanceof ContractDefinition || - (def instanceof FunctionDefinition && - def.isConstructor && - def.name === def.vScope.name)).map((def) => def instanceof FunctionDefinition ? def.vScope : def); + defs = defs + .filter( + (def) => + def instanceof ContractDefinition || + (def instanceof FunctionDefinition && + def.isConstructor && + def.name === def.vScope.name) + ) + .map((def) => (def instanceof FunctionDefinition ? def.vScope : def)); } else { defs = defs.filter((def) => def instanceof constructor); } @@ -157,7 +164,7 @@ function makeUserDefinedType( throw new Error(`Multiple matches for ${constructor.name} ${name}`); } - let def = defs[0]; + const def = defs[0]; assert( def instanceof constructor,