From 39f5cdeb96c9325a7b23db06b16e819688ac6681 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 10 Sep 2019 13:19:14 +0200 Subject: [PATCH 1/8] feat(sampiler): initial version of sample transpiler This is the initial version of a tool that will parse the TypeScript samples and emit equivalent sample code in Python. For now, its use is limited: - only supports Python - doesn't support properly integrating/compiling with a multi-package build yet. However, it will be an initial version we can demo and iterate on. --- packages/jsii-diff/package-lock.json | 144 - .../jsii-dotnet-jsonmodel/package-lock.json | 4 - .../package-lock.json | 378 -- .../jsii-dotnet-runtime/package-lock.json | 125 - packages/jsii-java-runtime/package-lock.json | 122 - packages/jsii-kernel/package-lock.json | 29 - packages/jsii-pacmak/lib/targets/python.ts | 52 +- packages/jsii-pacmak/package-lock.json | 69 - packages/jsii-pacmak/package.json | 1 + packages/jsii-pacmak/tsconfig.json | 11 +- packages/jsii-reflect/package-lock.json | 186 - packages/jsii-ruby-runtime/package-lock.json | 483 -- packages/jsii-runtime/package-lock.json | 93 +- packages/jsii-sampiler/.gitignore | 5 + packages/jsii-sampiler/README.md | 147 + packages/jsii-sampiler/bin/jsii-snippet | 2 + packages/jsii-sampiler/bin/jsii-snippet.ts | 52 + .../jsii-sampiler/examples/controlflow.ts | 15 + packages/jsii-sampiler/examples/incomplete.ts | 11 + packages/jsii-sampiler/lib/converter.ts | 375 ++ packages/jsii-sampiler/lib/index.ts | 3 + packages/jsii-sampiler/lib/jsii/jsii-utils.ts | 63 + .../jsii-sampiler/lib/languages/default.ts | 217 + .../jsii-sampiler/lib/languages/python.ts | 540 ++ .../jsii-sampiler/lib/languages/visualize.ts | 186 + .../lib/markdown/markdown-renderer.ts | 132 + .../jsii-sampiler/lib/markdown/markdown.ts | 101 + .../lib/markdown/replace-code-renderer.ts | 43 + .../lib/markdown/structure-renderer.ts | 55 + packages/jsii-sampiler/lib/o-tree.ts | 201 + packages/jsii-sampiler/lib/translate.ts | 118 + .../jsii-sampiler/lib/typescript/ast-utils.ts | 334 ++ .../jsii-sampiler/lib/typescript/imports.ts | 76 + .../lib/typescript/ts-compiler.ts | 85 + packages/jsii-sampiler/lib/util.ts | 26 + packages/jsii-sampiler/package-lock.json | 4917 +++++++++++++++++ packages/jsii-sampiler/package.json | 47 + .../test/markdown/roundtrip.test.ts | 164 + packages/jsii-sampiler/test/otree.test.ts | 50 + .../jsii-sampiler/test/python/calls.test.ts | 197 + .../jsii-sampiler/test/python/classes.test.ts | 166 + .../test/python/comments.test.ts | 84 + .../test/python/expressions.test.ts | 61 + .../jsii-sampiler/test/python/hiding.test.ts | 60 + .../jsii-sampiler/test/python/imports.test.ts | 26 + .../jsii-sampiler/test/python/misc.test.ts | 9 + packages/jsii-sampiler/test/python/python.ts | 42 + .../test/python/statements.test.ts | 100 + packages/jsii-sampiler/tsconfig.json | 28 + packages/jsii-spec/package-lock.json | 4 - packages/jsii/lib/helpers.ts | 2 +- packages/jsii/package-lock.json | 17 - packages/oo-ascii-tree/package-lock.json | 4 - 53 files changed, 8798 insertions(+), 1664 deletions(-) create mode 100644 packages/jsii-sampiler/.gitignore create mode 100644 packages/jsii-sampiler/README.md create mode 100755 packages/jsii-sampiler/bin/jsii-snippet create mode 100644 packages/jsii-sampiler/bin/jsii-snippet.ts create mode 100644 packages/jsii-sampiler/examples/controlflow.ts create mode 100644 packages/jsii-sampiler/examples/incomplete.ts create mode 100644 packages/jsii-sampiler/lib/converter.ts create mode 100644 packages/jsii-sampiler/lib/index.ts create mode 100644 packages/jsii-sampiler/lib/jsii/jsii-utils.ts create mode 100644 packages/jsii-sampiler/lib/languages/default.ts create mode 100644 packages/jsii-sampiler/lib/languages/python.ts create mode 100644 packages/jsii-sampiler/lib/languages/visualize.ts create mode 100644 packages/jsii-sampiler/lib/markdown/markdown-renderer.ts create mode 100644 packages/jsii-sampiler/lib/markdown/markdown.ts create mode 100644 packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts create mode 100644 packages/jsii-sampiler/lib/markdown/structure-renderer.ts create mode 100644 packages/jsii-sampiler/lib/o-tree.ts create mode 100644 packages/jsii-sampiler/lib/translate.ts create mode 100644 packages/jsii-sampiler/lib/typescript/ast-utils.ts create mode 100644 packages/jsii-sampiler/lib/typescript/imports.ts create mode 100644 packages/jsii-sampiler/lib/typescript/ts-compiler.ts create mode 100644 packages/jsii-sampiler/lib/util.ts create mode 100644 packages/jsii-sampiler/package-lock.json create mode 100644 packages/jsii-sampiler/package.json create mode 100644 packages/jsii-sampiler/test/markdown/roundtrip.test.ts create mode 100644 packages/jsii-sampiler/test/otree.test.ts create mode 100644 packages/jsii-sampiler/test/python/calls.test.ts create mode 100644 packages/jsii-sampiler/test/python/classes.test.ts create mode 100644 packages/jsii-sampiler/test/python/comments.test.ts create mode 100644 packages/jsii-sampiler/test/python/expressions.test.ts create mode 100644 packages/jsii-sampiler/test/python/hiding.test.ts create mode 100644 packages/jsii-sampiler/test/python/imports.test.ts create mode 100644 packages/jsii-sampiler/test/python/misc.test.ts create mode 100644 packages/jsii-sampiler/test/python/python.ts create mode 100644 packages/jsii-sampiler/test/python/statements.test.ts create mode 100644 packages/jsii-sampiler/tsconfig.json diff --git a/packages/jsii-diff/package-lock.json b/packages/jsii-diff/package-lock.json index bbd83fdb30..57662100ae 100644 --- a/packages/jsii-diff/package-lock.json +++ b/packages/jsii-diff/package-lock.json @@ -319,12 +319,6 @@ "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", "dev": true }, - "case": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz", - "integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -377,11 +371,6 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -497,12 +486,6 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, "default-require-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", @@ -518,18 +501,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, "diff": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", @@ -1006,94 +977,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.15.1.tgz", - "integrity": "sha512-2jyOH4+SohH4QhH44r5yMLHfwLyBU1Enji3PIID3745oTm51CooBGIggK7k9Fn1DMEhXgc7sT8E39kWM2AsoeQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.0.1", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.15.1", - "log4js": "^5.0.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "^3.5.3", - "yargs": "^13.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-reflect": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.15.1.tgz", - "integrity": "sha512-4EpWXN8kDhsRoD7lRoRhOW5YNN8niyUHbwdlv3s082O2HvIwgJiFfZs9WGK0dIH7Vvl0HhxkNQtcWb+KdqUGvA==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.15.1", - "oo-ascii-tree": "^0.15.1", - "yargs": "^13.3.0" - }, - "dependencies": { - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - } - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -1126,11 +1009,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1423,11 +1301,6 @@ "wrappy": "1" } }, - "oo-ascii-tree": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.15.1.tgz", - "integrity": "sha512-utKfbpEBMeqahYy2FCLybwZQ7+b5W7OlJdQ4zTUjNys6weuwtS6pHIC85J54/e09PsK/ABmWhr58S4kA9yxBpw==" - }, "opener": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", @@ -1753,17 +1626,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "sort-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", - "integrity": "sha512-OgXPErPJM/rBK5OhzIJ+etib/BmLQ1JY55Nb/ElhoWUec62pXNF/X6DrecHq3NW5OAGX0KxYD7m0HtgB9dvGeA==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1834,12 +1696,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/packages/jsii-dotnet-jsonmodel/package-lock.json b/packages/jsii-dotnet-jsonmodel/package-lock.json index aeb69a3d23..fc48387ac4 100644 --- a/packages/jsii-dotnet-jsonmodel/package-lock.json +++ b/packages/jsii-dotnet-jsonmodel/package-lock.json @@ -9,10 +9,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true } } } diff --git a/packages/jsii-dotnet-runtime-test/package-lock.json b/packages/jsii-dotnet-runtime-test/package-lock.json index 7ca1b65bd8..20846d9c3d 100644 --- a/packages/jsii-dotnet-runtime-test/package-lock.json +++ b/packages/jsii-dotnet-runtime-test/package-lock.json @@ -4,389 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "codemaker": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/codemaker/-/codemaker-0.15.1.tgz", - "integrity": "sha512-VLQzcK7aAJljiAC3d951f4fYn2Gblcs2yRMEvYq38b4UsCRHKSaCnuANPdNRTZ0qM+BIXDbwx3G4D1xB1Kj8tQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "fs-extra": "^8.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - }, - "commonmark": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.0.tgz", - "integrity": "sha512-Wc3kvAIm0EK85pHsM95Fev31wEN6/zQpwd2qcLDL8psjHRoUFvUeGHevIJAdToWUuFoX8WI/gmeDauqy32xgJQ==", - "dev": true, - "requires": { - "entities": "~ 1.1.1", - "mdurl": "~ 1.0.1", - "minimist": "~ 1.2.0", - "string.prototype.repeat": "^0.2.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-dotnet-runtime": { - "version": "file:../jsii-dotnet-runtime", - "dev": true - }, - "jsii-pacmak": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-0.15.1.tgz", - "integrity": "sha512-th9FKrF0pZdzfxNryHNHtIiiT2hA3VKpLqzZ5UPu5p49AhOgSTfHhCLqAVRUyo7i+pqE8BeCOoGer5XzlRdy5w==", - "dev": true, - "requires": { - "clone": "^2.1.2", - "codemaker": "^0.15.1", - "commonmark": "^0.29.0", - "escape-string-regexp": "^2.0.0", - "fs-extra": "^8.1.0", - "jsii-reflect": "^0.15.1", - "jsii-spec": "^0.15.1", - "spdx-license-list": "^6.1.0", - "xmlbuilder": "^13.0.2", - "yargs": "^13.3.0" - } - }, - "jsii-reflect": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.15.1.tgz", - "integrity": "sha512-4EpWXN8kDhsRoD7lRoRhOW5YNN8niyUHbwdlv3s082O2HvIwgJiFfZs9WGK0dIH7Vvl0HhxkNQtcWb+KdqUGvA==", - "dev": true, - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.15.1", - "oo-ascii-tree": "^0.15.1", - "yargs": "^13.3.0" - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "dev": true, - "requires": { - "jsonschema": "^1.2.4" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "oo-ascii-tree": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.15.1.tgz", - "integrity": "sha512-utKfbpEBMeqahYy2FCLybwZQ7+b5W7OlJdQ4zTUjNys6weuwtS6pHIC85J54/e09PsK/ABmWhr58S4kA9yxBpw==", - "dev": true - }, - "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string.prototype.repeat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", - "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, "typescript": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } } diff --git a/packages/jsii-dotnet-runtime/package-lock.json b/packages/jsii-dotnet-runtime/package-lock.json index 7cf1bd37ed..35de3d5c38 100644 --- a/packages/jsii-dotnet-runtime/package-lock.json +++ b/packages/jsii-dotnet-runtime/package-lock.json @@ -4,136 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-dotnet-jsonmodel": { - "version": "file:../jsii-dotnet-jsonmodel" - }, - "jsii-kernel": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.15.1.tgz", - "integrity": "sha512-YFEPtPgZ/Z3P5WLP2Gt4z44nGjdbdxZiWoSlHL+4YhTvEOG0v4jyANwXfhblN26WpK0DpztPZcGpxEsPRC5a+Q==", - "dev": true, - "requires": { - "jsii-spec": "^0.15.1", - "source-map": "^0.7.3", - "tar": "^4.4.10" - } - }, - "jsii-runtime": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-runtime/-/jsii-runtime-0.15.1.tgz", - "integrity": "sha512-s5p/zVhyv3NetT3X1kUu74mGQzKouBEWvyK4ue8saPagDLMvoL3ObjvEmKKFdYeYeLpMu0OVnvM3EJDCNo6ZKA==", - "dev": true, - "requires": { - "jsii-kernel": "^0.15.1", - "jsii-spec": "^0.15.1" - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "dev": true, - "requires": { - "jsonschema": "^1.2.4" - } - }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", - "dev": true - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "minipass": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.4.0.tgz", - "integrity": "sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, "typescript": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true } } } diff --git a/packages/jsii-java-runtime/package-lock.json b/packages/jsii-java-runtime/package-lock.json index ba01ab9681..7185a24fd0 100644 --- a/packages/jsii-java-runtime/package-lock.json +++ b/packages/jsii-java-runtime/package-lock.json @@ -4,133 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-kernel": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.15.1.tgz", - "integrity": "sha512-YFEPtPgZ/Z3P5WLP2Gt4z44nGjdbdxZiWoSlHL+4YhTvEOG0v4jyANwXfhblN26WpK0DpztPZcGpxEsPRC5a+Q==", - "dev": true, - "requires": { - "jsii-spec": "^0.15.1", - "source-map": "^0.7.3", - "tar": "^4.4.10" - } - }, - "jsii-runtime": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-runtime/-/jsii-runtime-0.15.1.tgz", - "integrity": "sha512-s5p/zVhyv3NetT3X1kUu74mGQzKouBEWvyK4ue8saPagDLMvoL3ObjvEmKKFdYeYeLpMu0OVnvM3EJDCNo6ZKA==", - "dev": true, - "requires": { - "jsii-kernel": "^0.15.1", - "jsii-spec": "^0.15.1" - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "dev": true, - "requires": { - "jsonschema": "^1.2.4" - } - }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", - "dev": true - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "minipass": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.4.0.tgz", - "integrity": "sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, "typescript": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true } } } diff --git a/packages/jsii-kernel/package-lock.json b/packages/jsii-kernel/package-lock.json index aee615144d..4d5f3448ac 100644 --- a/packages/jsii-kernel/package-lock.json +++ b/packages/jsii-kernel/package-lock.json @@ -119,14 +119,6 @@ "to-fast-properties": "^2.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/fs-extra": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", @@ -1063,22 +1055,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.16.0.tgz", - "integrity": "sha512-HIrWBEyHV1ZGccEsl1I7C8xk7uOJ/IJ+15QJM0JiIRMjMZ4f+V7L5gIfSoBmE5KljOWm3KuHfAitsCpRZZp6ew==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -1112,11 +1088,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index a163135202..7351a9c6f3 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -5,6 +5,7 @@ import * as escapeStringRegexp from 'escape-string-regexp'; import * as reflect from 'jsii-reflect'; import * as spec from 'jsii-spec'; import { Stability } from 'jsii-spec'; +import * as sampiler from 'jsii-sampiler'; import { Generator, GeneratorOptions } from '../generator'; import { warn } from '../logging'; import { md2rst } from '../markdown'; @@ -254,7 +255,7 @@ abstract class BasePythonClassType implements PythonType, ISortableType { const bases = classParams.length > 0 ? `(${classParams.join(", ")})` : ""; code.openBlock(`class ${this.pythonName}${bases}`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); this.emitPreamble(code, resolver); @@ -411,7 +412,7 @@ abstract class BaseMethod implements PythonBase { } code.openBlock(`def ${this.pythonName}(${pythonParams.join(", ")}) -> ${returnType}`); - emitDocString(code, this.docs, { arguments: documentableArgs }); + emitDocString(code, this.docs, { arguments: documentableArgs, documentableItem: `method-${this.pythonName}`}); this.emitBody(code, resolver, renderAbstract, forceEmitBody); code.closeBlock(); } @@ -539,7 +540,7 @@ abstract class BaseProperty implements PythonBase { code.line("@abc.abstractmethod"); } code.openBlock(`def ${this.pythonName}(${this.implicitParameter}) -> ${pythonType}`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { code.line(`return jsii.${this.jsiiGetMethod}(${this.implicitParameter}, "${this.jsName}")`); } else { @@ -575,7 +576,7 @@ class Interface extends BasePythonClassType { resolver = this.fqn ? resolver.bind(this.fqn) : resolver; const proxyBases: string[] = this.bases.map(b => `jsii.proxy_for(${resolver.resolve({ type: b })})`); code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(", ")})`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); code.line(`__jsii_type__ = "${this.fqn}"`); if (this.members.length > 0) { @@ -698,7 +699,7 @@ class Struct extends BasePythonClassType { name: m.pythonName, docs: m.docs, })); - emitDocString(code, this.docs, { arguments: args }); + emitDocString(code, this.docs, { arguments: args, documentableItem: `class-${this.pythonName}` }); } private emitGetter(member: StructField, code: CodeMaker, resolver: TypeResolver) { @@ -769,13 +770,13 @@ class StructField implements PythonBase { } public emitDocString(code: CodeMaker) { - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); } public emit(code: CodeMaker, resolver: TypeResolver) { const resolvedType = this.typeAnnotation(resolver); code.line(`${this.pythonName}: ${resolvedType}`); - emitDocString(code, this.docs); + this.emitDocString(code); } } @@ -954,7 +955,7 @@ class EnumMember implements PythonBase { public emit(code: CodeMaker, _resolver: TypeResolver) { code.line(`${this.pythonName} = "${this.value}"`); - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `enum-${this.pythonName}` }); } } @@ -1146,7 +1147,9 @@ class Package { } code.openFile("README.md"); - code.line(this.metadata.readme && this.metadata.readme.markdown); + if (this.metadata.readme) { + code.line(convertSnippetsInMarkdown(this.metadata.readme.markdown, 'README.md')); + } code.closeFile("README.md"); // Strip " (build abcdef)" from the jsii version @@ -1783,7 +1786,8 @@ interface DocumentableArgument { } function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { - arguments?: DocumentableArgument[] + arguments?: DocumentableArgument[], + documentableItem?: string } = {}) { if ((!docs || Object.keys(docs).length === 0) && !options.arguments) { return; } if (!docs) { docs = {}; } @@ -1819,7 +1823,7 @@ function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { if (docs.remarks) { brk(); - lines.push(...md2rst(docs.remarks || '').split('\n')); + lines.push(...md2rst(convertSnippetsInMarkdown(docs.remarks || '', options.documentableItem || 'docstring')).split('\n')); brk(); } @@ -1847,7 +1851,10 @@ function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { if (docs.example) { brk(); lines.push('Example::'); - for (const line of docs.example.split('\n')) { + + const exampleText = convertExample(docs.example, options.documentableItem || 'example'); + + for (const line of exampleText.split('\n')) { lines.push(` ${line}`); } brk(); @@ -1895,3 +1902,24 @@ function isStruct(typeSystem: reflect.TypeSystem, ref: spec.TypeReference): bool const type = typeSystem.tryFindFqn(ref.fqn); return type !== undefined && type.isInterfaceType() && type.isDataType(); } + +const pythonTranslator = new sampiler.PythonVisitor({ + disclaimer: 'Example may have issues. See https://github.com/aws/jsii/issues/826' +}); + +function convertExample(example: string, filename: string): string { + const source = new sampiler.LiteralSource(example, filename); + const result = sampiler.translateTypeScript(source, pythonTranslator); + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); +} + +function convertSnippetsInMarkdown(markdown: string, filename: string): string { + const source = new sampiler.LiteralSource(markdown, filename); + const result = sampiler.translateMarkdown(source, pythonTranslator, { + languageIdentifier: 'python' + }); + // FIXME: This should translate into an exit code somehow + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); +} diff --git a/packages/jsii-pacmak/package-lock.json b/packages/jsii-pacmak/package-lock.json index bce922c6f2..86bd27f129 100644 --- a/packages/jsii-pacmak/package-lock.json +++ b/packages/jsii-pacmak/package-lock.json @@ -111,10 +111,6 @@ "to-fast-properties": "^2.0.0" } }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/clone": { "version": "0.1.30", "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz", @@ -387,16 +383,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, - "codemaker": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/codemaker/-/codemaker-0.16.0.tgz", - "integrity": "sha512-e4l4oXa5A11GX+FrU3/WRr680IPb/5sycC1aZ+qYWySDSqKtRbKajFNfq9BYcy8CvFvU1VMTDK1DbEQiQIV4Zw==", - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "fs-extra": "^8.1.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -416,11 +402,6 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1032,46 +1013,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-dotnet-jsonmodel": { - "version": "file:../jsii-dotnet-jsonmodel", - "dev": true - }, - "jsii-dotnet-runtime": { - "version": "file:../jsii-dotnet-runtime", - "dev": true - }, - "jsii-java-runtime": { - "version": "file:../jsii-java-runtime", - "dev": true - }, - "jsii-reflect": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.16.0.tgz", - "integrity": "sha512-5k1a2VRaDlLMMkqVeQO3s/j9wqyHv+w9tj8IDyrS3VBt634hEX4PtZT7UpQvn8upBDTwdL3oVYv9/LECCxae+w==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.16.0", - "oo-ascii-tree": "^0.16.0", - "yargs": "^14.0.0" - } - }, - "jsii-spec": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.16.0.tgz", - "integrity": "sha512-HIrWBEyHV1ZGccEsl1I7C8xk7uOJ/IJ+15QJM0JiIRMjMZ4f+V7L5gIfSoBmE5KljOWm3KuHfAitsCpRZZp6ew==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -1104,11 +1045,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1394,11 +1330,6 @@ "wrappy": "1" } }, - "oo-ascii-tree": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.16.0.tgz", - "integrity": "sha512-BXR5SASSGN/I1uXWNvrq8oFihZGdPVJtoyElXdqdN38N38KRVC95GQ1hgW+DuV7YNoCBDSXKN7dBVPG6JJBbTQ==" - }, "opener": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", diff --git a/packages/jsii-pacmak/package.json b/packages/jsii-pacmak/package.json index a04d2d2fb3..e7406a9584 100644 --- a/packages/jsii-pacmak/package.json +++ b/packages/jsii-pacmak/package.json @@ -27,6 +27,7 @@ "fs-extra": "^8.1.0", "jsii-reflect": "^0.16.0", "jsii-spec": "^0.16.0", + "jsii-sampiler": "^0.16.0", "spdx-license-list": "^6.1.0", "xmlbuilder": "^13.0.2", "yargs": "^14.0.0" diff --git a/packages/jsii-pacmak/tsconfig.json b/packages/jsii-pacmak/tsconfig.json index d0a9a2d8cc..5ae4563404 100644 --- a/packages/jsii-pacmak/tsconfig.json +++ b/packages/jsii-pacmak/tsconfig.json @@ -55,9 +55,10 @@ "include": [ "**/*.ts" ], - "references": [{ - "path": "../jsii-spec" - }, { - "path": "../codemaker" - }] + "references": [ + { "path": "../jsii-spec" }, + { "path": "../codemaker" }, + { "path": "../jsii-sampiler" }, + { "path": "../jsii-reflect" } + ] } diff --git a/packages/jsii-reflect/package-lock.json b/packages/jsii-reflect/package-lock.json index 24cf6fb6b7..7c7daa84d9 100644 --- a/packages/jsii-reflect/package-lock.json +++ b/packages/jsii-reflect/package-lock.json @@ -385,10 +385,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz", @@ -909,12 +905,6 @@ "rsvp": "^4.8.4" } }, - "case": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz", - "integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==", - "dev": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1115,12 +1105,6 @@ } } }, - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1141,12 +1125,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1209,12 +1187,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -1563,12 +1535,6 @@ "locate-path": "^3.0.0" } }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true - }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3200,67 +3166,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.15.1.tgz", - "integrity": "sha512-2jyOH4+SohH4QhH44r5yMLHfwLyBU1Enji3PIID3745oTm51CooBGIggK7k9Fn1DMEhXgc7sT8E39kWM2AsoeQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.0.1", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.15.1", - "log4js": "^5.0.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "^3.5.3", - "yargs": "^13.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3302,11 +3207,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3386,36 +3286,6 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, - "log4js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-5.0.0.tgz", - "integrity": "sha512-yySdC7uCTYo1cCW3Of79PFQVrR1NVK3XxdFozEkLOYhpFsyhVE68yizMdJV7pcrwhvop5J+GGamwb2ejrDt6ww==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3767,11 +3637,6 @@ "wrappy": "1" } }, - "oo-ascii-tree": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.15.1.tgz", - "integrity": "sha512-utKfbpEBMeqahYy2FCLybwZQ7+b5W7OlJdQ4zTUjNys6weuwtS6pHIC85J54/e09PsK/ABmWhr58S4kA9yxBpw==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4182,12 +4047,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", - "dev": true - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -4433,17 +4292,6 @@ } } }, - "sort-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", - "integrity": "sha512-OgXPErPJM/rBK5OhzIJ+etib/BmLQ1JY55Nb/ElhoWUec62pXNF/X6DrecHq3NW5OAGX0KxYD7m0HtgB9dvGeA==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4511,12 +4359,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -4576,34 +4418,6 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, - "streamroller": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.1.0.tgz", - "integrity": "sha512-Ps7CuQL0RRG0YAigxNehrGfHrLu+jKSSnhiZBwF8uWi62WmtHDQV1OG5gVgV5SAzitcz1GrM3QVgnRO0mXV2hg==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", diff --git a/packages/jsii-ruby-runtime/package-lock.json b/packages/jsii-ruby-runtime/package-lock.json index d8286d1422..15d04910a3 100644 --- a/packages/jsii-ruby-runtime/package-lock.json +++ b/packages/jsii-ruby-runtime/package-lock.json @@ -4,494 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "codemaker": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/codemaker/-/codemaker-0.15.1.tgz", - "integrity": "sha512-VLQzcK7aAJljiAC3d951f4fYn2Gblcs2yRMEvYq38b4UsCRHKSaCnuANPdNRTZ0qM+BIXDbwx3G4D1xB1Kj8tQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "fs-extra": "^8.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - }, - "commonmark": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.0.tgz", - "integrity": "sha512-Wc3kvAIm0EK85pHsM95Fev31wEN6/zQpwd2qcLDL8psjHRoUFvUeGHevIJAdToWUuFoX8WI/gmeDauqy32xgJQ==", - "dev": true, - "requires": { - "entities": "~ 1.1.1", - "mdurl": "~ 1.0.1", - "minimist": "~ 1.2.0", - "string.prototype.repeat": "^0.2.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-kernel": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.15.1.tgz", - "integrity": "sha512-YFEPtPgZ/Z3P5WLP2Gt4z44nGjdbdxZiWoSlHL+4YhTvEOG0v4jyANwXfhblN26WpK0DpztPZcGpxEsPRC5a+Q==", - "dev": true, - "requires": { - "jsii-spec": "^0.15.1", - "source-map": "^0.7.3", - "tar": "^4.4.10" - } - }, - "jsii-pacmak": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-0.15.1.tgz", - "integrity": "sha512-th9FKrF0pZdzfxNryHNHtIiiT2hA3VKpLqzZ5UPu5p49AhOgSTfHhCLqAVRUyo7i+pqE8BeCOoGer5XzlRdy5w==", - "dev": true, - "requires": { - "clone": "^2.1.2", - "codemaker": "^0.15.1", - "commonmark": "^0.29.0", - "escape-string-regexp": "^2.0.0", - "fs-extra": "^8.1.0", - "jsii-reflect": "^0.15.1", - "jsii-spec": "^0.15.1", - "spdx-license-list": "^6.1.0", - "xmlbuilder": "^13.0.2", - "yargs": "^13.3.0" - } - }, - "jsii-reflect": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.15.1.tgz", - "integrity": "sha512-4EpWXN8kDhsRoD7lRoRhOW5YNN8niyUHbwdlv3s082O2HvIwgJiFfZs9WGK0dIH7Vvl0HhxkNQtcWb+KdqUGvA==", - "dev": true, - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.15.1", - "oo-ascii-tree": "^0.15.1", - "yargs": "^13.3.0" - } - }, - "jsii-runtime": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-runtime/-/jsii-runtime-0.15.1.tgz", - "integrity": "sha512-s5p/zVhyv3NetT3X1kUu74mGQzKouBEWvyK4ue8saPagDLMvoL3ObjvEmKKFdYeYeLpMu0OVnvM3EJDCNo6ZKA==", - "dev": true, - "requires": { - "jsii-kernel": "^0.15.1", - "jsii-spec": "^0.15.1" - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "dev": true, - "requires": { - "jsonschema": "^1.2.4" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "minipass": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.4.0.tgz", - "integrity": "sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "oo-ascii-tree": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.15.1.tgz", - "integrity": "sha512-utKfbpEBMeqahYy2FCLybwZQ7+b5W7OlJdQ4zTUjNys6weuwtS6pHIC85J54/e09PsK/ABmWhr58S4kA9yxBpw==", - "dev": true - }, - "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string.prototype.repeat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", - "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, "typescript": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } } diff --git a/packages/jsii-runtime/package-lock.json b/packages/jsii-runtime/package-lock.json index 943a6dada0..341b4d0f9c 100644 --- a/packages/jsii-runtime/package-lock.json +++ b/packages/jsii-runtime/package-lock.json @@ -169,14 +169,6 @@ "to-fast-properties": "^2.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -973,7 +965,8 @@ "chownr": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", + "dev": true }, "chrome-trace-event": { "version": "1.0.2", @@ -1896,14 +1889,6 @@ "integrity": "sha1-zyVVTKBQ3EmuZla0HeQiWJidy84=", "dev": true }, - "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", - "requires": { - "minipass": "^2.2.1" - } - }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -3110,32 +3095,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-kernel": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.15.1.tgz", - "integrity": "sha512-YFEPtPgZ/Z3P5WLP2Gt4z44nGjdbdxZiWoSlHL+4YhTvEOG0v4jyANwXfhblN26WpK0DpztPZcGpxEsPRC5a+Q==", - "requires": { - "jsii-spec": "^0.15.1", - "source-map": "^0.7.3", - "tar": "^4.4.10" - } - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3169,11 +3128,6 @@ "minimist": "^1.2.0" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3466,6 +3420,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "dev": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3474,18 +3429,11 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, - "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "requires": { - "minipass": "^2.2.1" - } - }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -3529,6 +3477,7 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "minimist": "0.0.8" }, @@ -3536,7 +3485,8 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true } } }, @@ -4401,7 +4351,8 @@ "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true }, "safe-regex": { "version": "1.1.0", @@ -4644,7 +4595,8 @@ "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true }, "source-map-loader": { "version": "0.2.4", @@ -5008,27 +4960,6 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "dependencies": { - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" - } - } - }, "terser": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/terser/-/terser-4.2.1.tgz", diff --git a/packages/jsii-sampiler/.gitignore b/packages/jsii-sampiler/.gitignore new file mode 100644 index 0000000000..176084432b --- /dev/null +++ b/packages/jsii-sampiler/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +*.js +*.tsbuildinfo +node_modules +*.d.ts diff --git a/packages/jsii-sampiler/README.md b/packages/jsii-sampiler/README.md new file mode 100644 index 0000000000..c0ddf4580a --- /dev/null +++ b/packages/jsii-sampiler/README.md @@ -0,0 +1,147 @@ +# jsii-sampiler: a transpiler for code samples + +Utility to transcribe example code snippets from TypeScript to other +jsii languages. + +Has knowledge about jsii language translation conventions to do the +translations. Only supports a limited set of TypeScript language features. + +## Compilability + +The sampiler can translate both code that completely compiles and typechecks, +as well as code that doesn't. + +In case of non-compiling samples the translations will be based off of +grammatical parsing only. This has the downside that we do not have the type +information available to the exact right thing in all instances. + +If the samples don't compile or don't have full type information: + +- No way to declare typed variables for Java and C#. +- Can only "see" the fields of structs as far as they are declared in the same + snippet. Inherited fields or structs declared not in the same snippet are + invisible. +- When we explode a struct parameter into keyword parameters and we pass it on + to another callable, we can't know which keyword arguments the called function + actually takes so we just pass all of them (might be too many). +- When structs contain nested structs, Python and other languages need to know + the types of these fields to generate the right calls. +- Object literals are used both to represent structs as well as to represent + dictionaries, and without type information it's impossible to determine + which is which. + +## Void masking + +In order to make examples compile, boilerplate code may need to be added +that detracts from the example at hand (such as variable declarations +and imports). + +This package supports hiding parts of the original source after +translation. + +To mark special locations in the source tree, we use the `void` +expression keyword and or the `comma` operator feature to attach this +expression to another expression. Both are little-used JavaScript +features that are reliably parsed by TypeScript and do not affect the +semantics of the application in which they appear (so the program +executes the same with or without them). + +A handy mnemonic for this feature is that you can use it to "send your +code into the void". + +### Hiding statements + +Statement hiding looks like this: + +```ts +before(); // will be shown + +void 0; // start hiding (the argument to 'void' doesn't matter) +middle(); // will not be shown +void 'show'; // stop hiding + +after(); // will be shown again +``` + +Void masking only works to the end of the enclosing scope, so in some +cases you can omit the `void 'show'` directive to turn hiding back off. + +To explicit show that code was hidden, pass `'block'` to the void +statement: + + +```ts +before(); +void 'block'; // start hiding, will render a '# ...' +middle(); +``` + +### Hiding expressions + +For hiding expressions, we use `comma` expressions to attach a `void` +statement to an expression value without changing the meaning of the +code. + +Example: + +```ts +foo(1, 2, (void 1, 3)); +``` + +Will render as + +``` +foo(1, 2) +``` + +Also supports a visible ellipsis: + +```ts +const x = (void '...', 3); +``` + +Renders to: + +``` +x = ... +``` + +## Build integration + +This tool has the ability to hide irrelevant parts of the generated code +snippet (see the section called "void masking" below). Because the samples +should be compilable to extract all necessary type information, and because +they could depend on any package, the following steps need to happen: + +* All packages need to be built (by `jsii`). Ideally, the reduced example ends + up in the assembly. +* After all packages have been built, sample snippets should be checked + for compilability and supported language constructs (not all language + features can be translated to other languages). This requires the full + snippets (before reducing). +* After the full samples have been type-checked, their reduced version + can be translated and inserted into the various generated packages by + `jsii-pacmak`. + +To avoid an additional dependency of `jsii` on the `jsii-samples` mechanism, +what we'll do instead is mutating the assembly in-place. So simplified, +the workflow looks like this: + +* All packages get compiled by `jsii`. +* We postprocess all assemblies using `jsii-samples`, extracting code to + a side-archive (`.jsii.samples`) and replacing the original version in the + assembly, and generating all other language versions. This becomes a + translation table, with the key being a hash of the reduced snippet. +* `jsii-pacmak` replaces snippets from the translation table. + +In this process, `jsii-samples` is as much self-contained as possible. It +works on an assembly to produce a lookup file, which `jsii-pacmak` reads. +`jsii-pacmak` has a simple fallback, which is use the unsubtituted example in +case the right example is not available. + +Alternatively, since `jsii` doesn't really provide any facilities to mutate +an assembly in-place, we leave the unreduced examples in the source assembly, +and force all downstream renderers (such as the doc renderer and API tooling) +to use `jsii-samples` to reduce the snippets before presenting them. This is +not ideal but probably the way we're going to go because `jsii` doesn't provide +any tooling to mutate an assembly in-place. diff --git a/packages/jsii-sampiler/bin/jsii-snippet b/packages/jsii-sampiler/bin/jsii-snippet new file mode 100755 index 0000000000..407f7e294a --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-snippet @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./jsii-snippet.js'); diff --git a/packages/jsii-sampiler/bin/jsii-snippet.ts b/packages/jsii-sampiler/bin/jsii-snippet.ts new file mode 100644 index 0000000000..ea521016b1 --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-snippet.ts @@ -0,0 +1,52 @@ +import fs = require("fs"); +import yargs = require('yargs'); +import { FileSource, isErrorDiagnostic, LiteralSource, printDiagnostics, + renderTree, translateMarkdown, TranslateOptions, translateTypeScript } from '../lib'; +import { PythonVisitor } from '../lib/languages/python'; +import { VisualizeAstVisitor } from '../lib/languages/visualize'; + +async function main() { + const argv = yargs + .usage('$0 [file]') + .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) + .option('markdown', { alias: 'm', boolean: true, description: 'Parse input as MarkDown and translate snippets inside it' }) + .help() + .version(require('../package.json').version) + .argv; + + const options: TranslateOptions = {}; + + let visitor; + if (argv.python) { visitor = new PythonVisitor(); } + if (!visitor) { + // Default to visualizing AST, including nodes we don't recognize yet + visitor = new VisualizeAstVisitor(); + options.bestEffort = false; + } + + const fakeInputFileName = argv.markdown ? 'stdin.md' : 'stdin.ts'; + + const source = argv._.length > 0 + ? new FileSource(argv._[0]) + : new LiteralSource(fs.readFileSync(0, "utf-8"), fakeInputFileName); + + const result = argv.markdown + ? translateMarkdown(source, visitor, options) + : translateTypeScript(source, visitor, options); + + process.stdout.write(renderTree(result.tree) + '\n'); + + if (result.diagnostics.length > 0) { + printDiagnostics(result.diagnostics, process.stderr); + + if (result.diagnostics.some(isErrorDiagnostic)) { + process.exit(1); + } + } +} + +main().catch(e => { + // tslint:disable-next-line:no-console + console.error(e); + process.exit(1); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/examples/controlflow.ts b/packages/jsii-sampiler/examples/controlflow.ts new file mode 100644 index 0000000000..4846ae5d1f --- /dev/null +++ b/packages/jsii-sampiler/examples/controlflow.ts @@ -0,0 +1,15 @@ +import lib = require('@aws-cdk/lib'); + +/** + * This squares a value + */ +function squareNumber(x: number, y?: number) { + return x * x; +} + +// This is where the magic happens +if (Math.random() % 2 == 0) { + console.log(squareNumber(3)); +} else { + console.log(squareNumber(6)); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/examples/incomplete.ts b/packages/jsii-sampiler/examples/incomplete.ts new file mode 100644 index 0000000000..12e1a87681 --- /dev/null +++ b/packages/jsii-sampiler/examples/incomplete.ts @@ -0,0 +1,11 @@ +someObject.callSomeFunction(x, { + y: 3 +}); + +/* This is a thing */ +SomeClass.callSomeFunction(x, { + y: 3 +}); + +// Some comment +const obj = new SecondFunction(this, { hello: 1 }); diff --git a/packages/jsii-sampiler/lib/converter.ts b/packages/jsii-sampiler/lib/converter.ts new file mode 100644 index 0000000000..42c540b6b8 --- /dev/null +++ b/packages/jsii-sampiler/lib/converter.ts @@ -0,0 +1,375 @@ +import ts = require('typescript'); +import { NO_SYNTAX, OTree, UnknownSyntax } from './o-tree'; +import { commentRangeFromTextRange, extractMaskingVoidExpression, extractShowingVoidExpression, nodeChildren, + repeatNewlines, scanText } from './typescript/ast-utils'; +import { analyzeImportDeclaration, analyzeImportEquals, ImportStatement } from './typescript/imports'; + +/** + * AST conversion operation + * + * Dispatch the actual conversion to a specific handler which will get the + * appropriate method called for particular AST nodes. The handler may use + * context to modify its own operations when traversing the tree hierarchy, + * the type of which should be expressed via the C parameter. + */ +export class AstConverter { + public readonly diagnostics = new Array(); + public readonly currentContext: C; + + constructor( + private readonly sourceFile: ts.SourceFile, + private readonly typeChecker: ts.TypeChecker, + private readonly handler: AstHandler, + private readonly options: ConvertOptions = {}) { + + this.currentContext = handler.defaultContext; + } + + /** + * Merge the new context with the current context and create a new Converter from it + */ + public updateContext(contextUpdate: C): AstConverter { + const newContext = this.handler.mergeContext(this.currentContext, contextUpdate); + + // Use prototypal inheritance to create a version of 'this' in which only + // 'currentContext' is updated. + return Object.assign(Object.create(this), { + currentContext: newContext + }); + } + + /** + * Convert a single node to an OTree + */ + public convert(node: ts.Node | undefined): OTree { + if (node === undefined) { return NO_SYNTAX; } + + // Basic transform of node + const transformed = this.dispatch(node); + if (!transformed.attachComment) { return transformed; } + + return this.attachLeadingTrivia(node, transformed); + } + + /** + * Convert a set of nodes, filtering out hidden nodes + */ + public convertAll(nodes: ReadonlyArray): OTree[] { + return filterVisible(nodes).map(this.convert.bind(this)); + } + + /** + * Convert a set of nodes, but update the context for the last one. + * + * Takes visibility into account. + */ + public convertLastDifferently(nodes: ReadonlyArray, lastContext: C): OTree[] { + const lastConverter = this.updateContext(lastContext); + + const convert = this.convert.bind(this); + const lastConvert = lastConverter.convert.bind(lastConverter); + + const ret: OTree[] = []; + + const vis = assignVisibility(nodes); + for (let i = 0; i < vis.length; i++) { + const whichConvert = i === vis.length - 1 ? lastConvert : convert; + + const node = vis[i].visible ? vis[i].node : vis[i].maskingVoid; + if (node) { + ret.push(whichConvert(node)); + } + } + + return ret; + } + + public textOf(node: ts.Node): string { + return node.getText(this.sourceFile); + } + + public textAt(pos: number, end: number): string { + return this.sourceFile.text.substring(pos, end); + } + + public typeOfExpression(node: ts.Expression) { + return this.typeChecker.getContextualType(node); + } + + public typeOfType(node: ts.TypeNode): ts.Type { + return this.typeChecker.getTypeFromTypeNode(node); + } + + public report(node: ts.Node, messageText: string, category: ts.DiagnosticCategory = ts.DiagnosticCategory.Error) { + this.diagnostics.push({ + category, code: 0, + messageText, + file: this.sourceFile, + start: node.getStart(this.sourceFile), + length: node.getWidth(this.sourceFile) + }); + } + + public reportUnsupported(node: ts.Node): void { + const nodeKind = ts.SyntaxKind[node.kind]; + // tslint:disable-next-line:max-line-length + this.report(node, `This TypeScript language feature (${nodeKind}) is not supported in examples because we cannot translate it. Please rewrite this example.`); + } + + /** + * Return a newline if the given node is preceded by at least one newline + * + * Used to mirror newline use between matchin brackets (such as { ... } and [ ... ]). + */ + public mirrorNewlineBefore(viz?: ts.Node, suffix: string = ''): string { + if (viz === undefined) { return suffix; } + + // Return a newline if the given node is preceded by newlines + const leadingRanges = scanText(this.sourceFile.text, viz.getFullStart(), viz.getStart(this.sourceFile)); + const newlines = []; + + for (const range of leadingRanges) { + if (range.type === 'other') { + newlines.push(repeatNewlines(this.sourceFile.text.substring(range.pos, range.end))); + } + } + + return (newlines.join('').length > 0 ? '\n' : '') + suffix; + } + + /** + * Dispatch node to handler + */ + private dispatch(tree: ts.Node): OTree { + // Special nodes + if (ts.isEmptyStatement(tree)) { + // Additional semicolon where it doesn't belong. + return NO_SYNTAX; + } + + const visitor = this.handler; + const context = this; + + // Nodes with meaning + if (ts.isSourceFile(tree)) { return visitor.sourceFile(tree, this); } + if (ts.isImportEqualsDeclaration(tree)) { return visitor.importStatement(analyzeImportEquals(tree, context), context); } + if (ts.isImportDeclaration(tree)) { return visitor.importStatement(analyzeImportDeclaration(tree, context), context); } + if (ts.isStringLiteral(tree)) { return visitor.stringLiteral(tree, context); } + if (ts.isFunctionDeclaration(tree)) { return visitor.functionDeclaration(tree, context); } + if (ts.isIdentifier(tree)) { return visitor.identifier(tree, context); } + if (ts.isBlock(tree)) { return visitor.block(tree, context); } + if (ts.isParameter(tree)) { return visitor.parameterDeclaration(tree, context); } + if (ts.isReturnStatement(tree)) { return visitor.returnStatement(tree, context); } + if (ts.isBinaryExpression(tree)) { return visitor.binaryExpression(tree, context); } + if (ts.isIfStatement(tree)) { return visitor.ifStatement(tree, context); } + if (ts.isPropertyAccessExpression(tree)) { return visitor.propertyAccessExpression(tree, context); } + if (ts.isCallExpression(tree)) { return visitor.callExpression(tree, context); } + if (ts.isExpressionStatement(tree)) { return visitor.expressionStatement(tree, context); } + if (ts.isNoSubstitutionTemplateLiteral(tree)) { return visitor.noSubstitutionTemplateLiteral(tree, context); } + if (ts.isToken(tree)) { return visitor.token(tree, context); } + if (ts.isObjectLiteralExpression(tree)) { return visitor.objectLiteralExpression(tree, context); } + if (ts.isNewExpression(tree)) { return visitor.newExpression(tree, context); } + if (ts.isPropertyAssignment(tree)) { return visitor.propertyAssignment(tree, context); } + if (ts.isVariableStatement(tree)) { return visitor.variableStatement(tree, context); } + if (ts.isVariableDeclarationList(tree)) { return visitor.variableDeclarationList(tree, context); } + if (ts.isVariableDeclaration(tree)) { return visitor.variableDeclaration(tree, context); } + if (ts.isJSDoc(tree)) { return visitor.jsDoc(tree, context); } + if (ts.isArrayLiteralExpression(tree)) { return visitor.arrayLiteralExpression(tree, context); } + if (ts.isShorthandPropertyAssignment(tree)) { return visitor.shorthandPropertyAssignment(tree, context); } + if (ts.isForOfStatement(tree)) { return visitor.forOfStatement(tree, context); } + if (ts.isClassDeclaration(tree)) { return visitor.classDeclaration(tree, context); } + if (ts.isConstructorDeclaration(tree)) { return visitor.constructorDeclaration(tree, context); } + if (ts.isPropertyDeclaration(tree)) { return visitor.propertyDeclaration(tree, context); } + if (ts.isMethodDeclaration(tree)) { return visitor.methodDeclaration(tree, context); } + if (ts.isInterfaceDeclaration(tree)) { return visitor.interfaceDeclaration(tree, context); } + if (ts.isPropertySignature(tree)) { return visitor.propertySignature(tree, context); } + if (ts.isAsExpression(tree)) { return visitor.asExpression(tree, context); } + if (ts.isPrefixUnaryExpression(tree)) { return visitor.prefixUnaryExpression(tree, context); } + if (ts.isSpreadAssignment(tree)) { + if (context.textOf(tree) === '...') { return visitor.ellipsis(tree, context); } + return visitor.spreadAssignment(tree, context); + } + if (ts.isSpreadElement(tree)) { + if (context.textOf(tree) === '...') { return visitor.ellipsis(tree, context); } + return visitor.spreadElement(tree, context); + } + if (ts.isTemplateExpression(tree)) { return visitor.templateExpression(tree, context); } + if (ts.isNonNullExpression(tree)) { return visitor.nonNullExpression(tree, context); } + if (ts.isParenthesizedExpression(tree)) { return visitor.parenthesizedExpression(tree, context); } + if (ts.isVoidExpression(tree)) { return visitor.maskingVoidExpression(tree, context); } + + context.reportUnsupported(tree); + + if (this.options.bestEffort !== false) { + // When doing best-effort conversion and we don't understand the node type, just return the complete text of it as-is + return new OTree([context.textOf(tree)]); + } else { + // Otherwise, show a placeholder indicating we don't recognize the type + const nodeKind = ts.SyntaxKind[tree.kind]; + return new UnknownSyntax([`<${nodeKind} ${context.textOf(tree)}>`], [ + '\n', + ...nodeChildren(tree).map(this.convert.bind(this)) + ], { + indent: 2, + }); + } + } + + /** + * Attach any leading whitespace and comments to the given output tree + * + * Regardless of whether it's declared to be able to accept such or not. + */ + private attachLeadingTrivia(node: ts.Node, transformed: OTree): OTree { + // Add comments and leading whitespace + const leadingRanges = scanText(this.sourceFile.text, node.getFullStart(), node.getStart(this.sourceFile)); + + const precede: OTree[] = []; + for (const range of leadingRanges) { + switch (range.type) { + case 'other': + precede.push(new OTree([repeatNewlines(this.sourceFile.text.substring(range.pos, range.end))], [], { + renderOnce: `ws-${range.pos}` + })); + break; + case 'linecomment': + case 'blockcomment': + precede.push(this.handler.commentRange(commentRangeFromTextRange(range), this)); + break; + } + } + + // FIXME: No trailing comments for now, they're too tricky + + if (precede.length > 0 && !transformed.isEmpty) { + return new OTree([...precede, transformed], [], { canBreakLine: true }); + } else { + return transformed; + } + } +} + +/** + * Interface for AST handlers + * + * C is the type of hierarchical context the handler uses. Context + * needs 2 operations: a constructor for a default context, and a + * merge operation to combine 2 contexts to yield a new one. + * + * Otherwise, the handler should return an OTree for every type + * of AST node. + */ +export interface AstHandler { + readonly defaultContext: C; + mergeContext(old: C, update: C): C; + + sourceFile(node: ts.SourceFile, context: AstConverter): OTree; + commentRange(node: ts.CommentRange, context: AstConverter): OTree; + importStatement(node: ImportStatement, context: AstConverter): OTree; + stringLiteral(node: ts.StringLiteral, children: AstConverter): OTree; + functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree; + identifier(node: ts.Identifier, children: AstConverter): OTree; + block(node: ts.Block, children: AstConverter): OTree; + parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree; + returnStatement(node: ts.ReturnStatement, context: AstConverter): OTree; + binaryExpression(node: ts.BinaryExpression, context: AstConverter): OTree; + ifStatement(node: ts.IfStatement, context: AstConverter): OTree; + propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree; + callExpression(node: ts.CallExpression, context: AstConverter): OTree; + expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree; + token(node: ts.Token, context: AstConverter): OTree; + objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree; + newExpression(node: ts.NewExpression, context: AstConverter): OTree; + propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree; + variableStatement(node: ts.VariableStatement, context: AstConverter): OTree; + variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree; + variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree; + jsDoc(node: ts.JSDoc, context: AstConverter): OTree; + arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree; + shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree; + forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree; + classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree; + constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree; + propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree; + methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree; + interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree; + propertySignature(node: ts.PropertySignature, context: AstConverter): OTree; + asExpression(node: ts.AsExpression, context: AstConverter): OTree; + prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree; + spreadElement(node: ts.SpreadElement, context: AstConverter): OTree; + spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree; + templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree; + nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree; + parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree; + maskingVoidExpression(node: ts.VoidExpression, context: AstConverter): OTree; + noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, context: AstConverter): OTree; + + // Not a node, called when we recognize a spread element/assignment that is only + // '...' and nothing else. + ellipsis(node: ts.SpreadElement | ts.SpreadAssignment, context: AstConverter): OTree; +} + +export function nimpl(node: ts.Node, context: AstConverter, options: { additionalInfo?: string} = {}) { + const children = nodeChildren(node).map(c => context.convert(c)); + + let syntaxKind = ts.SyntaxKind[node.kind]; + if (syntaxKind === 'FirstPunctuation') { + // These have the same identifier but this name is more descriptive + syntaxKind = 'OpenBraceToken'; + } + + const parts = [`(${syntaxKind}`]; + if (options.additionalInfo) { parts.push(`{${options.additionalInfo}}`); } + parts.push(context.textOf(node)); + + return new UnknownSyntax([parts.join(' ')], children.length > 0 ? ['\n', ...children] : [], { + indent: 2, + suffix: ')', + separator: '\n', + canBreakLine: true + }); +} + +export interface ConvertOptions { + /** + * If enabled, don't translate the text of unknown nodes + * + * @default true + */ + bestEffort?: boolean; +} + +interface ClassifiedNode { + node: ts.Node; + visible: boolean; + maskingVoid?: ts.VoidExpression; +} + +function filterVisible(nodes: ReadonlyArray): ts.Node[] { + return assignVisibility(nodes).map(c => c.visible ? c.node : c.maskingVoid).filter(notUndefined); +} + +function assignVisibility(nodes: ReadonlyArray): ClassifiedNode[] { + const ret: ClassifiedNode[] = []; + + let visible = true; + for (const node of nodes) { + const maskingVoid = extractMaskingVoidExpression(node); + if (visible && maskingVoid) { visible = false; } + + ret.push({ node, maskingVoid, visible }); + + if (!visible) { + const showing = extractShowingVoidExpression(node); + if (showing) { + visible = true; + } + } + } + + return ret; +} + +function notUndefined(x: A | undefined): x is A { + return x !== undefined; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/index.ts b/packages/jsii-sampiler/lib/index.ts new file mode 100644 index 0000000000..16b185ccbe --- /dev/null +++ b/packages/jsii-sampiler/lib/index.ts @@ -0,0 +1,3 @@ +export * from './translate'; +export { renderTree } from './o-tree'; +export { PythonVisitor } from './languages/python'; \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/jsii/jsii-utils.ts b/packages/jsii-sampiler/lib/jsii/jsii-utils.ts new file mode 100644 index 0000000000..278e90cace --- /dev/null +++ b/packages/jsii-sampiler/lib/jsii/jsii-utils.ts @@ -0,0 +1,63 @@ +import ts = require('typescript'); +import { AstConverter } from '../converter'; + +export function isStructInterface(name: string) { + return !name.startsWith('I'); +} + +export function isStructType(type: ts.Type) { + return type.isClassOrInterface() + && hasFlag(type.objectFlags, ts.ObjectFlags.Interface) + && isStructInterface(type.symbol.name); +} + +function hasFlag(flags: A, test: A) { + // tslint:disable-next-line:no-bitwise + return (flags & test) !== 0; +} + +export interface StructProperty { + name: string; + type: ts.Type | undefined; + questionMark: boolean; +} + +export function propertiesOfStruct(type: ts.Type, context: AstConverter): StructProperty[] { + return type.isClassOrInterface() ? type.getProperties().map(s => { + let propType; + let questionMark = false; + + const propSymbol = type.getProperty(s.name)!; + const symbolDecl = propSymbol.valueDeclaration; + if (ts.isPropertyDeclaration(symbolDecl) || ts.isPropertySignature(symbolDecl)) { + questionMark = symbolDecl.questionToken !== undefined; + propType = symbolDecl.type && context.typeOfType(symbolDecl.type); + } + + return { + name: s.name, + type: propType, + questionMark, + }; + }) : []; +} + +export function parameterAcceptsUndefined(param: ts.ParameterDeclaration, type?: ts.Type): boolean { + if (param.initializer !== undefined) { return true; } + if (param.questionToken !== undefined) { return true; } + if (type) { return typeContainsUndefined(type); } + return false; +} + +export function structPropertyAcceptsUndefined(prop: StructProperty): boolean { + return prop.questionMark || (!!prop.type && typeContainsUndefined(prop.type)); +} + +/** + * This is a simplified check that should be good enough for most purposes + */ +function typeContainsUndefined(type: ts.Type): boolean { + if (type.getFlags() === ts.TypeFlags.Undefined) { return true; } + if (type.isUnion()) { return type.types.some(typeContainsUndefined); } + return false; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/languages/default.ts b/packages/jsii-sampiler/lib/languages/default.ts new file mode 100644 index 0000000000..0c405ded07 --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/default.ts @@ -0,0 +1,217 @@ +import ts = require('typescript'); +import { AstConverter, AstHandler, nimpl } from "../converter"; +import { OTree } from '../o-tree'; +import { ImportStatement } from '../typescript/imports'; + +/** + * A basic visitor that applies for most curly-braces-based languages + */ +export abstract class DefaultVisitor implements AstHandler { + public abstract readonly defaultContext: C; + + public abstract mergeContext(old: C, update: C): C; + + public commentRange(node: ts.CommentRange, context: AstConverter): OTree { + return new OTree([ + context.textAt(node.pos, node.end), + node.hasTrailingNewLine ? '\n' : '' + ]); + } + + public sourceFile(node: ts.SourceFile, context: AstConverter): OTree { + return new OTree(context.convertAll(node.statements)); + } + + public jsDoc(_node: ts.JSDoc, _context: AstConverter): OTree { + // Already handled by other doc handlers + return new OTree([]); + } + + public importStatement(node: ImportStatement, context: AstConverter): OTree { + return this.notImplemented(node.node, context); + } + + public functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree { + return this.notImplemented(node, children); + } + + public stringLiteral(node: ts.StringLiteral, _children: AstConverter): OTree { + return new OTree([JSON.stringify(node.text)]); + } + + public noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, _context: AstConverter): OTree { + return new OTree([JSON.stringify(node.text)]); + } + + public identifier(node: ts.Identifier, _children: AstConverter): OTree { + return new OTree([node.text]); + } + + public block(node: ts.Block, children: AstConverter): OTree { + return new OTree(['{'], ['\n', ...children.convertAll(node.statements)], { + indent: 4, + suffix: '}', + }); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree { + return this.notImplemented(node, children); + } + + public returnStatement(node: ts.ReturnStatement, children: AstConverter): OTree { + return new OTree(['return ', children.convert(node.expression)]); + } + + public binaryExpression(node: ts.BinaryExpression, context: AstConverter): OTree { + return new OTree([ + context.convert(node.left), + ' ', + context.textOf(node.operatorToken), + ' ', + context.convert(node.right) + ]); + } + + public prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree { + + return new OTree([ + UNARY_OPS[node.operator], + context.convert(node.operand) + ]); + } + + public ifStatement(node: ts.IfStatement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree { + return new OTree([context.convert(node.expression), '.', context.convert(node.name)]); + } + + public callExpression(node: ts.CallExpression, context: AstConverter): OTree { + return new OTree([ + context.convert(node.expression), + '(', + new OTree([], context.convertAll(node.arguments), { separator: ', ' }), + ')']); + } + + public expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree { + return new OTree([context.convert(node.expression)], [], { canBreakLine: true }); + } + + public token(node: ts.Token, context: AstConverter): OTree { + return new OTree([context.textOf(node)]); + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public newExpression(node: ts.NewExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public variableStatement(node: ts.VariableStatement, context: AstConverter): OTree { + return new OTree([context.convert(node.declarationList)], [], { canBreakLine: true }); + } + + public variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree { + return new OTree([], context.convertAll(node.declarations)); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree { + return new OTree(['['], context.convertAll(node.elements), { + separator: ', ', + suffix: ']', + }); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public propertySignature(node: ts.PropertySignature, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public asExpression(node: ts.AsExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public spreadElement(node: ts.SpreadElement, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public ellipsis(_node: ts.SpreadElement | ts.SpreadAssignment, _context: AstConverter): OTree { + return new OTree(['...']); + } + + public templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree { + return this.notImplemented(node, context); + } + + public nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree { + // We default we drop the non-null assertion + return context.convert(node.expression); + } + + public parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree { + return new OTree(['(', context.convert(node.expression), ')']); + } + + public maskingVoidExpression(_node: ts.VoidExpression, _context: AstConverter): OTree { + // Don't render anything by default when nodes are masked + return new OTree([]); + } + + private notImplemented(node: ts.Node, context: AstConverter) { + context.reportUnsupported(node); + return nimpl(node, context); + } +} + +const UNARY_OPS: {[op in ts.PrefixUnaryOperator]: string} = { + [ts.SyntaxKind.PlusPlusToken]: '++', + [ts.SyntaxKind.MinusMinusToken]: '--', + [ts.SyntaxKind.PlusToken]: '+', + [ts.SyntaxKind.MinusToken]: '-', + [ts.SyntaxKind.TildeToken]: '~', + [ts.SyntaxKind.ExclamationToken]: '~', +}; diff --git a/packages/jsii-sampiler/lib/languages/python.ts b/packages/jsii-sampiler/lib/languages/python.ts new file mode 100644 index 0000000000..c67cecfaaa --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/python.ts @@ -0,0 +1,540 @@ +import ts = require('typescript'); +import { AstConverter, nimpl } from "../converter"; +import { isStructType, parameterAcceptsUndefined, propertiesOfStruct, StructProperty, structPropertyAcceptsUndefined } from '../jsii/jsii-utils'; +import { NO_SYNTAX, OTree, renderTree } from "../o-tree"; +import { matchAst, nodeOfType, stripCommentMarkers, voidExpressionString } from '../typescript/ast-utils'; +import { ImportStatement } from '../typescript/imports'; +import { startsWithUppercase } from "../util"; +import { DefaultVisitor } from './default'; + +interface StructVar { + variableName: string; + type: ts.Type | undefined; +} + +type ReturnFromTree = { value?: A; }; + +interface PythonLanguageContext { + /** + * Whether we're currently rendering a parameter in tail position + * + * If so, and the parameter is of type struct, explode it to keyword args + * and return its information in `returnExplodedParameter`. + */ + readonly tailPositionParameter?: boolean; + + /** + * Used to return details about any exploded parameter + */ + readonly returnExplodedParameter?: ReturnFromTree; + + /** + * Whether we're currently rendering a value/expression in tail position + * + * If so, and the expression seems to be of a struct type, explode it + * to keyword args. + */ + readonly tailPositionArgument?: boolean; + + /** + * Whether object literal members should render themselves as dict + * members or keyword args + */ + readonly renderObjectLiteralAsKeywords?: boolean; + + /** + * In a code block, if any parameter is exploded, information about the parameter here + */ + readonly explodedParameter?: StructVar; + + /** + * Whether we're rendering a method or property inside a class + */ + readonly inClass?: boolean; + + /** + * If we're in a method, what is it's name + * + * (Used to render super() call.); + */ + readonly currentMethodName?: string; +} + +type PythonVisitorContext = AstConverter; + +export interface PythonVisitorOptions { + disclaimer?: string; +} + +export class PythonVisitor extends DefaultVisitor { + public readonly defaultContext = {}; + + constructor(private readonly options: PythonVisitorOptions = {}) { + super(); + } + + public mergeContext(old: PythonLanguageContext, update: PythonLanguageContext) { + return Object.assign({}, old, update); + } + + public commentRange(node: ts.CommentRange, context: PythonVisitorContext): OTree { + const commentText = stripCommentMarkers(context.textAt(node.pos, node.end), node.kind === ts.SyntaxKind.MultiLineCommentTrivia); + const hashLines = commentText.split('\n').map(l => `# ${l}`).join('\n'); + const needsAdditionalTrailer = node.kind !== ts.SyntaxKind.MultiLineCommentTrivia || !node.hasTrailingNewLine; + + return new OTree([hashLines, needsAdditionalTrailer ? '\n' : ''], [], { + // Make sure comment is rendered exactly once in the output tree, no + // matter how many source nodes it is attached to. + renderOnce: `comment-${node.pos}` + }); + } + + public sourceFile(node: ts.SourceFile, context: PythonVisitorContext): OTree { + const rendered = super.sourceFile(node, context); + if (this.options.disclaimer) { + return new OTree(['# ' + this.options.disclaimer, rendered]); + } + return rendered; + } + + public importStatement(node: ImportStatement, context: PythonVisitorContext): OTree { + const moduleName = this.convertModuleReference(node.packageName); + if (node.imports.import === 'full') { + return new OTree([`import ${moduleName} as ${mangleIdentifier(node.imports.alias)}`], [], { + canBreakLine: true + }); + } + if (node.imports.import === 'selective') { + const imports = node.imports.elements.map(im => + im.alias + ? `${mangleIdentifier(im.sourceName)} as ${mangleIdentifier(im.alias)}` + : mangleIdentifier(im.sourceName)); + + return new OTree([`from ${moduleName} import ${imports.join(', ')}`], [], { + canBreakLine: true + }); + } + + return nimpl(node.node, context); + } + + public token(node: ts.Token, context: PythonVisitorContext): OTree { + const text = context.textOf(node); + const mapped = TOKEN_REWRITES[text]; + if (mapped) { return new OTree([mapped]); } + return super.token(node, context); + } + + public identifier(node: ts.Identifier, context: PythonVisitorContext) { + const originalIdentifier = node.text; + + // tslint:disable-next-line:max-line-length + const explodedParameter = context.currentContext.explodedParameter; + // tslint:disable-next-line:max-line-length + if (context.currentContext.tailPositionArgument && explodedParameter && explodedParameter.type && explodedParameter.variableName === originalIdentifier) { + return new OTree([], + propertiesOfStruct(explodedParameter.type, context).map(prop => new OTree([prop.name, '=', prop.name])), + { separator: ', ' }); + } + + return new OTree([mangleIdentifier(originalIdentifier)]); + } + + public functionDeclaration(node: ts.FunctionDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context, { isConstructor: true }); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: PythonVisitorContext): OTree { + return this.functionLike(node, context); + } + + public expressionStatement(node: ts.ExpressionStatement, context: PythonVisitorContext): OTree { + const text = context.textOf(node); + if (text === 'true') { return new OTree(['True']); } + if (text === 'false') { return new OTree(['False']); } + + return super.expressionStatement(node, context); + } + + // tslint:disable-next-line:max-line-length + public functionLike(node: ts.FunctionLikeDeclarationBase, context: PythonVisitorContext, opts: { isConstructor?: boolean } = {}): OTree { + const methodName = opts.isConstructor ? '__init__' : renderTree(context.convert(node.name)); + + const [paramDecls, explodedParameter] = this.convertFunctionCallParameters(node.parameters, context); + + const ret = new OTree([ + 'def ', + methodName, + '(', + new OTree([], [ + context.currentContext.inClass ? 'self' : undefined, + ...paramDecls, + ], { + separator: ', ', + }), + '): ', + ], [context.updateContext({ explodedParameter, currentMethodName: methodName }).convert(node.body)], { + canBreakLine: true + }); + + return ret; + } + + public block(node: ts.Block, context: PythonVisitorContext): OTree { + if (node.statements.length === 0) { + return new OTree([], ['\npass'], { indent: 4, canBreakLine: true }); + } + + return new OTree([], context.convertAll(node.statements), { + separator: '', + indent: 4, + canBreakLine: true, + }); + } + + public callExpression(node: ts.CallExpression, context: PythonVisitorContext): OTree { + let expressionText: OTree | string = context.convert(node.expression); + + if (matchAst(node.expression, nodeOfType(ts.SyntaxKind.SuperKeyword)) && context.currentContext.currentMethodName) { + expressionText = 'super().' + context.currentContext.currentMethodName; + } + + return new OTree([ + expressionText, + '(', + this.convertFunctionCallArguments(node.arguments, context), + ')'], [], { canBreakLine: true }); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: PythonVisitorContext) { + const fullText = context.textOf(node); + if (fullText in BUILTIN_FUNCTIONS) { + return new OTree([BUILTIN_FUNCTIONS[fullText]]); + } + + const explodedParameter = context.currentContext.explodedParameter; + + // We might be in a context where we've exploded this struct into arguments, + // in which case we will return just the accessed variable. + if (explodedParameter && context.textOf(node.expression) === explodedParameter.variableName) { + return context.convert(node.name); + } + + return super.propertyAccessExpression(node, context); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, context: PythonVisitorContext): OTree { + const type = node.type && context.typeOfType(node.type); + + if (context.currentContext.tailPositionParameter && type && isStructType(type)) { + // Return the parameter that we exploded so that we can use this information + // while translating the body. + if (context.currentContext.returnExplodedParameter) { + context.currentContext.returnExplodedParameter.value = { + variableName: context.textOf(node.name), + type, + }; + } + + // Explode to fields + return new OTree([], ['*', ...propertiesOfStruct(type, context).map(renderStructProperty)], { separator: ', ' }); + } + + const suffix = parameterAcceptsUndefined(node, type) ? '=None' : ''; + + return new OTree([context.convert(node.name), suffix]); + + function renderStructProperty(prop: StructProperty): string { + const sfx = structPropertyAcceptsUndefined(prop) ? '=None' : ''; + return prop.name + sfx; + } + } + + public ifStatement(node: ts.IfStatement, context: PythonVisitorContext): OTree { + const ifStmt = new OTree( + ['if ', context.convert(node.expression), ': '], + [context.convert(node.thenStatement)], { canBreakLine: true }); + const elseStmt = node.elseStatement ? new OTree([`else: `], [context.convert(node.elseStatement)], { canBreakLine: true }) : undefined; + + return elseStmt ? new OTree([], [ifStmt, elseStmt], { + separator: '\n', + canBreakLine: true + }) : ifStmt; + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: PythonVisitorContext): OTree { + const type = context.typeOfExpression(node); + + // We render in one of three modes: + // + // - If we're in tail position, we render as keyword arguments if we don't know + // the type, OR we know the type and the type is a struct. + // - Otherwise, if we know the type AND it's a struct we render a class constructor + // (with keyword arguments for the literal members) + // - Otherwise, we render as a dict literal, using dict literal members. + let prefix = '{'; + let suffix = '}'; + let renderObjectLiteralAsKeywords = false; + + const isUnknownType = !type || !type.symbol; + const isKnownStruct = type && isStructType(type); + + if (context.currentContext.tailPositionArgument && (isUnknownType || isKnownStruct)) { + prefix = ''; + suffix = ''; + renderObjectLiteralAsKeywords = true; + } else if (type && isKnownStruct) { + prefix = type.symbol.name + '('; + suffix = ')'; + renderObjectLiteralAsKeywords = true; + } + + return new OTree([prefix], context.updateContext({ renderObjectLiteralAsKeywords }).convertAll(node.properties), { + suffix: context.mirrorNewlineBefore(node.properties[0], suffix), + separator: ', ', + indent: 4, + }); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: PythonVisitorContext): OTree { + return new OTree(['['], context.convertAll(node.elements), { + suffix: context.mirrorNewlineBefore(node.elements[0], ']'), + separator: ', ', + indent: 4, + }); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: PythonVisitorContext): OTree { + let before = '"'; + let mid = '": '; + + if (context.currentContext.renderObjectLiteralAsKeywords) { + before = ''; + mid = '='; + } + + // node.name is either an identifier or a string literal. The string literal + // needs to be converted differently. + let name = context.convert(node.name); + matchAst(node.name, nodeOfType('stringLiteral', ts.SyntaxKind.StringLiteral), captured => { + name = new OTree([mangleIdentifier(captured.stringLiteral.text)]); + }); + + return new OTree([ + before, + name, + mid, + context.updateContext({ tailPositionArgument: false }).convert(node.initializer) + ], [], { canBreakLine: true }); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: PythonVisitorContext): OTree { + let before = '"'; + let mid = '": '; + + if (context.currentContext.renderObjectLiteralAsKeywords) { + before = ''; + mid = '='; + } + + return new OTree([ + before, + context.convert(node.name), + mid, + context.convert(node.name) + ], [], { canBreakLine: true }); + } + + public newExpression(node: ts.NewExpression, context: PythonVisitorContext): OTree { + return new OTree([ + context.convert(node.expression), + '(', + this.convertFunctionCallArguments(node.arguments, context), + ')' + ], [], { canBreakLine: true }); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: PythonVisitorContext): OTree { + return new OTree([ + context.convert(node.name), + ' = ', + context.convert(node.initializer) + ], [], { canBreakLine: true }); + } + + public thisKeyword() { + return new OTree(['self']); + } + + public forOfStatement(node: ts.ForOfStatement, context: PythonVisitorContext): OTree { + // This is what a "for (const x of ...)" looks like in the AST + let variableName = '???'; + + matchAst(node.initializer, + nodeOfType(ts.SyntaxKind.VariableDeclarationList, + nodeOfType('var', ts.SyntaxKind.VariableDeclaration)), + bindings => { + variableName = mangleIdentifier(context.textOf(bindings.var.name)); + }); + + return new OTree([ + 'for ', + variableName, + ' in ', + context.convert(node.expression), + ': ' + ], [context.convert(node.statement)], { canBreakLine: true }); + } + + public classDeclaration(node: ts.ClassDeclaration, context: PythonVisitorContext): OTree { + const heritage = flat(Array.from(node.heritageClauses || []).map(h => Array.from(h.types))).map(t => context.convert(t.expression)); + const hasHeritage = heritage.length > 0; + + const members = context.updateContext({ inClass: true }).convertAll(node.members); + if (members.length === 0) { + members.push(new OTree(['\npass'], [])); + } + + const ret = new OTree([ + 'class ', + node.name ? context.textOf(node.name) : '???', + hasHeritage ? '(' : '', + ...heritage, + hasHeritage ? ')' : '', + ': ', + ], members, { + indent: 4, + canBreakLine: true + }); + + return ret; + } + + public propertyDeclaration(_node: ts.PropertyDeclaration, _context: PythonVisitorContext): OTree { + return new OTree([]); + } + + /** + * We have to do something special here + * + * Best-effort, we remember the fields of struct interfaces and keep track of + * them. Fortunately we can determine from the name whether what to do. + */ + public interfaceDeclaration(_node: ts.InterfaceDeclaration, _context: PythonVisitorContext): OTree { + // Whatever we do, nothing here will have a representation + return NO_SYNTAX; + } + + public propertySignature(_node: ts.PropertySignature, _context: PythonVisitorContext): OTree { + // Does not represent in Python + return NO_SYNTAX; + } + + public asExpression(node: ts.AsExpression, context: PythonVisitorContext): OTree { + return context.convert(node.expression); + } + + public templateExpression(node: ts.TemplateExpression, context: PythonVisitorContext): OTree { + const parts = ['f"']; + if (node.head.rawText) { parts.push(quoteStringLiteral(node.head.rawText)); } + for (const span of node.templateSpans) { + parts.push('{' + context.textOf(span.expression) + '}'); + if (span.literal.rawText) { parts.push(quoteStringLiteral(span.literal.rawText)); } + } + parts.push('"'); + + return new OTree([parts.join('')]); + } + + public maskingVoidExpression(node: ts.VoidExpression, _context: PythonVisitorContext): OTree { + const arg = voidExpressionString(node); + if (arg === 'block') { return new OTree(['# ...'], [], { canBreakLine: true }); } + if (arg === '...') { return new OTree(['...']); } + return NO_SYNTAX; + } + + protected convertModuleReference(ref: string) { + return ref.replace(/^@/, '').replace(/\//g, '.').replace(/-/g, '_'); + } + + /** + * Convert parameters + * + * If the last one has the type of a known struct, explode to keyword-only arguments. + * + * Returns a pair of [decls, excploded-var-name]. + */ + // tslint:disable-next-line:max-line-length + private convertFunctionCallParameters(params: ts.NodeArray | undefined, context: PythonVisitorContext): [Array, StructVar | undefined] { + if (!params || params.length === 0) { return [[], undefined]; } + + const returnExplodedParameter: ReturnFromTree = {}; + + // Convert the last element differently + const converted: Array = params.length > 0 ? [ + ...context.convertAll(params.slice(0, params.length - 1)), + context.updateContext({ + tailPositionParameter: true, + returnExplodedParameter + }).convert(last(params)) + ] : []; + + return [ converted, returnExplodedParameter.value ]; + } + + /** + * Convert arguments. + * + * If the last argument: + * + * - is an object literal, explode it. + * - is itself an exploded argument in our call signature, explode the fields + */ + private convertFunctionCallArguments(args: ts.NodeArray | undefined, context: PythonVisitorContext) { + if (!args) { return NO_SYNTAX; } + + const converted: Array = context.convertLastDifferently(args, { + tailPositionArgument: true, + }); + + return new OTree([], converted, { separator: ', ', indent: 4 }); + } +} + +function mangleIdentifier(originalIdentifier: string) { + if (startsWithUppercase(originalIdentifier)) { + // Probably a class, leave as-is + return originalIdentifier; + } else { + // Turn into snake-case + return originalIdentifier.replace(/[^A-Z][A-Z]/g, m => m[0].substr(0, 1) + '_' + m.substr(1).toLowerCase()); + } +} + +const BUILTIN_FUNCTIONS: {[key: string]: string} = { + 'console.log': 'print', + 'console.error': 'sys.stderr.write', + 'Math.random': 'random.random' +}; + +const TOKEN_REWRITES: {[key: string]: string} = { + this: 'self', + true: 'True', + false: 'False' +}; + +function flat(xs: A[][]): A[] { + return Array.prototype.concat.apply([], xs); +} + +function last(xs: ReadonlyArray): A { + return xs[xs.length - 1]; +} + +function quoteStringLiteral(x: string) { + return x.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/languages/visualize.ts b/packages/jsii-sampiler/lib/languages/visualize.ts new file mode 100644 index 0000000000..837b0f3c74 --- /dev/null +++ b/packages/jsii-sampiler/lib/languages/visualize.ts @@ -0,0 +1,186 @@ +import ts = require('typescript'); +import { AstConverter, AstHandler, nimpl } from "../converter"; +import { OTree } from '../o-tree'; +import { ImportStatement } from '../typescript/imports'; + +export class VisualizeAstVisitor implements AstHandler { + public readonly defaultContext: void = undefined; + + constructor(private readonly includeHandlerNames?: boolean) { + } + + public mergeContext(_old: void, _update: void): void { + return undefined; + } + + public commentRange(node: ts.CommentRange, context: AstConverter): OTree { + return new OTree(['(Comment', context.textAt(node.pos, node.end)], [], { suffix: ')' }); + } + + public jsDoc(_node: ts.JSDoc, _context: AstConverter): OTree { + // Already handled by other doc handlers + return new OTree([]); + } + + public sourceFile(node: ts.SourceFile, context: AstConverter): OTree { + return new OTree(context.convertAll(node.statements)); + } + + public importStatement(node: ImportStatement, context: AstConverter): OTree { + return this.defaultNode('importStatement', node.node, context); + } + + public functionDeclaration(node: ts.FunctionDeclaration, children: AstConverter): OTree { + return this.defaultNode('functionDeclaration', node, children); + } + + public stringLiteral(node: ts.StringLiteral, children: AstConverter): OTree { + return this.defaultNode('stringLiteral', node, children); + } + + public identifier(node: ts.Identifier, children: AstConverter): OTree { + return this.defaultNode('identifier', node, children); + } + + public block(node: ts.Block, children: AstConverter): OTree { + return this.defaultNode('block', node, children); + } + + public parameterDeclaration(node: ts.ParameterDeclaration, children: AstConverter): OTree { + return this.defaultNode('parameterDeclaration', node, children); + } + + public returnStatement(node: ts.ReturnStatement, children: AstConverter): OTree { + return this.defaultNode('returnStatement', node, children); + } + + public binaryExpression(node: ts.BinaryExpression, children: AstConverter): OTree { + return this.defaultNode('binaryExpression', node, children); + } + + public ifStatement(node: ts.IfStatement, context: AstConverter): OTree { + return this.defaultNode('ifStatement', node, context); + } + + public propertyAccessExpression(node: ts.PropertyAccessExpression, context: AstConverter): OTree { + return this.defaultNode('propertyAccessExpression', node, context); + } + + public callExpression(node: ts.CallExpression, context: AstConverter): OTree { + return this.defaultNode('callExpression', node, context); + } + + public expressionStatement(node: ts.ExpressionStatement, context: AstConverter): OTree { + return this.defaultNode('expressionStatement', node, context); + } + + public token(node: ts.Token, context: AstConverter): OTree { + return this.defaultNode('token', node, context); + } + + public objectLiteralExpression(node: ts.ObjectLiteralExpression, context: AstConverter): OTree { + return this.defaultNode('objectLiteralExpression', node, context); + } + + public newExpression(node: ts.NewExpression, context: AstConverter): OTree { + return this.defaultNode('newExpression', node, context); + } + + public propertyAssignment(node: ts.PropertyAssignment, context: AstConverter): OTree { + return this.defaultNode('propertyAssignment', node, context); + } + + public variableStatement(node: ts.VariableStatement, context: AstConverter): OTree { + return this.defaultNode('variableStatement', node, context); + } + + public variableDeclarationList(node: ts.VariableDeclarationList, context: AstConverter): OTree { + return this.defaultNode('variableDeclarationList', node, context); + } + + public variableDeclaration(node: ts.VariableDeclaration, context: AstConverter): OTree { + return this.defaultNode('variableDeclaration', node, context); + } + + public arrayLiteralExpression(node: ts.ArrayLiteralExpression, context: AstConverter): OTree { + return this.defaultNode('arrayLiteralExpression', node, context); + } + + public shorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, context: AstConverter): OTree { + return this.defaultNode('shorthandPropertyAssignment', node, context); + } + + public forOfStatement(node: ts.ForOfStatement, context: AstConverter): OTree { + return this.defaultNode('forOfStatement', node, context); + } + + public classDeclaration(node: ts.ClassDeclaration, context: AstConverter): OTree { + return this.defaultNode('classDeclaration', node, context); + } + + public constructorDeclaration(node: ts.ConstructorDeclaration, context: AstConverter): OTree { + return this.defaultNode('constructorDeclaration', node, context); + } + + public propertyDeclaration(node: ts.PropertyDeclaration, context: AstConverter): OTree { + return this.defaultNode('propertyDeclaration', node, context); + } + + public methodDeclaration(node: ts.MethodDeclaration, context: AstConverter): OTree { + return this.defaultNode('methodDeclaration', node, context); + } + + public interfaceDeclaration(node: ts.InterfaceDeclaration, context: AstConverter): OTree { + return this.defaultNode('interfaceDeclaration', node, context); + } + + public propertySignature(node: ts.PropertySignature, context: AstConverter): OTree { + return this.defaultNode('propertySignature', node, context); + } + + public asExpression(node: ts.AsExpression, context: AstConverter): OTree { + return this.defaultNode('asExpression', node, context); + } + + public prefixUnaryExpression(node: ts.PrefixUnaryExpression, context: AstConverter): OTree { + return this.defaultNode('prefixUnaryExpression', node, context); + } + + public spreadElement(node: ts.SpreadElement, context: AstConverter): OTree { + return this.defaultNode('spreadElement', node, context); + } + + public spreadAssignment(node: ts.SpreadAssignment, context: AstConverter): OTree { + return this.defaultNode('spreadAssignment', node, context); + } + + public ellipsis(node: ts.SpreadAssignment | ts.SpreadElement, context: AstConverter): OTree { + return this.defaultNode('ellipsis', node, context); + } + + public templateExpression(node: ts.TemplateExpression, context: AstConverter): OTree { + return this.defaultNode('templateExpression', node, context); + } + + public nonNullExpression(node: ts.NonNullExpression, context: AstConverter): OTree { + return this.defaultNode('nonNullExpression', node, context); + } + + public parenthesizedExpression(node: ts.ParenthesizedExpression, context: AstConverter): OTree { + return this.defaultNode('parenthesizedExpression', node, context); + } + + public maskingVoidExpression(node: ts.VoidExpression, context: AstConverter): OTree { + return this.defaultNode('maskingVoidExpression', node, context); + } + + public noSubstitutionTemplateLiteral(node: ts.NoSubstitutionTemplateLiteral, context: AstConverter): OTree { + return this.defaultNode('noSubstitutionTemplateLiteral', node, context); + } + + private defaultNode(handlerName: string, node: ts.Node, context: AstConverter): OTree { + return nimpl(node, context, { + additionalInfo: this.includeHandlerNames ? handlerName : '' + }); + } +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts b/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts new file mode 100644 index 0000000000..c876a38b86 --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/markdown-renderer.ts @@ -0,0 +1,132 @@ +import cm = require('commonmark'); +import { cmNodeChildren, CommonMarkRenderer, prefixLines, RendererContext } from './markdown'; + +/** + * A renderer that will render a CommonMark tree back to MarkDown + */ +export class MarkdownRenderer implements CommonMarkRenderer { + public block_quote(_node: cm.Node, context: RendererContext) { + return para(prefixLines('> ', collapsePara(context.content()))); + } + + public code(node: cm.Node, _context: RendererContext) { + return '`' + node.literal + '`'; + } + + public code_block(node: cm.Node, _context: RendererContext) { + return para('```' + (node.info || '') + '\n' + node.literal + '```'); + } + + public text(node: cm.Node, _context: RendererContext) { + return node.literal || ''; + } + + public softbreak(_node: cm.Node, _context: RendererContext) { + return '\n'; + } + + public linebreak(_node: cm.Node, _context: RendererContext) { + return '\\\n'; + } + + public emph(_node: cm.Node, context: RendererContext) { + return `*${context.content()}*`; + } + + public strong(_node: cm.Node, context: RendererContext) { + return `**${context.content()}**`; + } + + public html_inline(node: cm.Node, _context: RendererContext) { + return node.literal || ''; + } + + public html_block(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } + + public link(node: cm.Node, context: RendererContext) { + return `[${context.content()}](${node.destination || ''})`; + } + + public image(node: cm.Node, context: RendererContext) { + return `![${context.content()}](${node.destination || ''})`; + } + + public document(_node: cm.Node, context: RendererContext) { + // Remove trailing whitespace on every line + return collapsePara(context.content()).replace(/[ \t]+$/gm, ''); + } + + public paragraph(_node: cm.Node, context: RendererContext) { + return para(context.content()); + } + + public list(node: cm.Node, context: RendererContext) { + // A list is not wrapped in a paragraph, but items may contain paragraphs. + // All elements of a list are definitely 'item's. + const items = []; + + let i = 1; + for (const item of cmNodeChildren(node)) { + const firstLinePrefix = determineItemPrefix(node, i); + const hangingPrefix = ' '.repeat(firstLinePrefix.length); + + const rendered = context.recurse(item); + // Prefix the first line with a different text than subsequent lines + const prefixed = firstLinePrefix + prefixLines(hangingPrefix, rendered).substr(hangingPrefix.length); + + items.push(prefixed); + + i += 1; + } + + return para(items.join('\n')); + } + + public item(_node: cm.Node, context: RendererContext) { + return collapsePara(context.content()); + } + + public heading(node: cm.Node, context: RendererContext) { + return para('#'.repeat(node.level) + ' ' + context.content()); + } + + public thematic_break(_node: cm.Node, _context: RendererContext) { + return '---\n'; + } + + public custom_block(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } + + public custom_inline(_node: cm.Node, context: RendererContext) { + return `${context.content()}`; + } +} + +/* +function trimEmptyLines(x: string) { + return x.replace(/^\n+/, '').replace(/\n+$/, ''); +} +*/ + +const PARA_BREAK = '\u001d'; + +function para(x: string) { + return `${PARA_BREAK}${x}${PARA_BREAK}`; +} + +/** + * Collapse paragraph markers + */ +function collapsePara(x: string, brk: string = '\n\n') { + return x.replace(/^\u001d+/, '').replace(/\u001d+$/, '').replace(/\u001d+/g, brk); +} + +function determineItemPrefix(listNode: cm.Node, index: number) { + if (listNode.listType === 'bullet') { + return '* '; + } + return `${index}${listNode.listDelimiter} `; +} diff --git a/packages/jsii-sampiler/lib/markdown/markdown.ts b/packages/jsii-sampiler/lib/markdown/markdown.ts new file mode 100644 index 0000000000..256c29a6a0 --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/markdown.ts @@ -0,0 +1,101 @@ +import cm = require('commonmark'); + +export function transformMarkdown(source: string, renderer: CommonMarkRenderer, transform?: CommonMarkVisitor) { + const parser = new cm.Parser(); + const doc = parser.parse(source); + if (transform) { + visitCommonMarkTree(doc, transform); + } + return renderCommonMarkTree(doc, renderer); +} + +export interface RendererContext { + recurse(node: cm.Node): string; + children(): string[]; + content(): string; +} + +export interface CommonMarkRenderer { + block_quote(node: cm.Node, context: RendererContext): string; + code(node: cm.Node, context: RendererContext): string; + code_block(node: cm.Node, context: RendererContext): string; + text(node: cm.Node, context: RendererContext): string; + softbreak(node: cm.Node, context: RendererContext): string; + linebreak(node: cm.Node, context: RendererContext): string; + emph(node: cm.Node, context: RendererContext): string; + strong(node: cm.Node, context: RendererContext): string; + html_inline(node: cm.Node, context: RendererContext): string; + html_block(node: cm.Node, context: RendererContext): string; + link(node: cm.Node, context: RendererContext): string; + image(node: cm.Node, context: RendererContext): string; + document(node: cm.Node, context: RendererContext): string; + paragraph(node: cm.Node, context: RendererContext): string; + list(node: cm.Node, context: RendererContext): string; + item(node: cm.Node, context: RendererContext): string; + heading(node: cm.Node, context: RendererContext): string; + thematic_break(node: cm.Node, context: RendererContext): string; + custom_block(node: cm.Node, context: RendererContext): string; + custom_inline(node: cm.Node, context: RendererContext): string; +} + +export function renderCommonMarkTree(node: cm.Node, renderer: CommonMarkRenderer) { + const context: RendererContext = { + recurse(n: cm.Node): string { + return renderCommonMarkTree(n, renderer); + }, + + content() { + return this.children().join(''); + }, + + children() { + const parts = []; + for (const child of cmNodeChildren(node)) { + parts.push(renderCommonMarkTree(child, renderer)); + } + return parts; + } + }; + + return renderer[node.type].call(renderer, node, context); +} + +export function visitCommonMarkTree(node: cm.Node, visitor: CommonMarkVisitor) { + visitor[node.type].call(visitor, node); + for (const child of cmNodeChildren(node)) { + visitCommonMarkTree(child, visitor); + } +} + +export function prefixLines(prefix: string, x: string) { + return x.split('\n').map(l => prefix + l).join('\n'); +} + +export function* cmNodeChildren(node: cm.Node): IterableIterator { + for (let child = node.firstChild; child !== null; child = child.next) { + yield child; + } +} + +export interface CommonMarkVisitor { + block_quote(node: cm.Node): void; + code(node: cm.Node): void; + code_block(node: cm.Node): void; + text(node: cm.Node): void; + softbreak(node: cm.Node): void; + linebreak(node: cm.Node): void; + emph(node: cm.Node): void; + strong(node: cm.Node): void; + html_inline(node: cm.Node): void; + html_block(node: cm.Node): void; + link(node: cm.Node): void; + image(node: cm.Node): void; + document(node: cm.Node): void; + paragraph(node: cm.Node): void; + list(node: cm.Node): void; + item(node: cm.Node): void; + heading(node: cm.Node): void; + thematic_break(node: cm.Node): void; + custom_block(node: cm.Node): void; + custom_inline(node: cm.Node): void; +} diff --git a/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts b/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts new file mode 100644 index 0000000000..4229e4bd7b --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/replace-code-renderer.ts @@ -0,0 +1,43 @@ +import cm = require('commonmark'); +import { CommonMarkVisitor } from './markdown'; + +export type CodeReplacer = (code: CodeBlock) => CodeBlock; + +export interface CodeBlock { + source: string; + language: string; +} + +/** + * Renderer that replaces code blocks in a MarkDown document + */ +export class ReplaceCodeTransform implements CommonMarkVisitor { + constructor(private readonly replacer: CodeReplacer) { + } + + public code_block(node: cm.Node) { + const ret = this.replacer({ language: node.info || '', source: node.literal || '' }); + node.info = ret.language; + node.literal = ret.source; + } + + public block_quote(): void { /* nothing */ } + public code(): void { /* nothing */ } + public text(): void { /* nothing */ } + public softbreak(): void { /* nothing */ } + public linebreak(): void { /* nothing */ } + public emph(): void { /* nothing */ } + public strong(): void { /* nothing */ } + public html_inline(): void { /* nothing */ } + public html_block(): void { /* nothing */ } + public link(): void { /* nothing */ } + public image(): void { /* nothing */ } + public document(): void { /* nothing */ } + public paragraph(): void { /* nothing */ } + public list(): void { /* nothing */ } + public item(): void { /* nothing */ } + public heading(): void { /* nothing */ } + public thematic_break(): void { /* nothing */ } + public custom_block(): void { /* nothing */ } + public custom_inline(): void { /* nothing */ } +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/markdown/structure-renderer.ts b/packages/jsii-sampiler/lib/markdown/structure-renderer.ts new file mode 100644 index 0000000000..8e82a9237a --- /dev/null +++ b/packages/jsii-sampiler/lib/markdown/structure-renderer.ts @@ -0,0 +1,55 @@ +import cm = require('commonmark'); +import { CommonMarkRenderer, prefixLines, RendererContext } from './markdown'; + +/** + * A renderer that will render a CommonMark tree to show its structure + */ +export class StructureRenderer implements CommonMarkRenderer { + public block_quote(node: cm.Node, context: RendererContext) { return this.handle('block_quote', node, context); } + public code(node: cm.Node, context: RendererContext) { return this.handle('code', node, context); } + public code_block(node: cm.Node, context: RendererContext) { return this.handle('code_block', node, context); } + public text(node: cm.Node, context: RendererContext) { return this.handle('text', node, context); } + public softbreak(node: cm.Node, context: RendererContext) { return this.handle('softbreak', node, context); } + public linebreak(node: cm.Node, context: RendererContext) { return this.handle('linebreak', node, context); } + public emph(node: cm.Node, context: RendererContext) { return this.handle('emph', node, context); } + public strong(node: cm.Node, context: RendererContext) { return this.handle('strong', node, context); } + public html_inline(node: cm.Node, context: RendererContext) { return this.handle('html_inline', node, context); } + public html_block(node: cm.Node, context: RendererContext) { return this.handle('html_block', node, context); } + public link(node: cm.Node, context: RendererContext) { return this.handle('link', node, context); } + public image(node: cm.Node, context: RendererContext) { return this.handle('image', node, context); } + public document(node: cm.Node, context: RendererContext) { return this.handle('document', node, context); } + public paragraph(node: cm.Node, context: RendererContext) { return this.handle('paragraph', node, context); } + public list(node: cm.Node, context: RendererContext) { return this.handle('list', node, context); } + public item(node: cm.Node, context: RendererContext) { return this.handle('item', node, context); } + public heading(node: cm.Node, context: RendererContext) { return this.handle('heading', node, context); } + public thematic_break(node: cm.Node, context: RendererContext) { return this.handle('thematic_break', node, context); } + public custom_block(node: cm.Node, context: RendererContext) { return this.handle('custom_block', node, context); } + public custom_inline(node: cm.Node, context: RendererContext) { return this.handle('custom_inline', node, context); } + + private handle(name: string, node: cm.Node, context: RendererContext) { + const contents = context.content(); + + const enterText = [name, inspectNode(node)].filter(x => x).join(' '); + + if (contents) { + return `(${enterText}\n${prefixLines(' ', contents)})\n`; + } else { + return `(${enterText})\n`; + } + } +} + +function inspectNode(n: cm.Node): string { + const INTERESTING_KEYS = [ + 'literal', 'destination', 'title', 'info', 'level', 'listType', 'listTight', 'listStart', 'listDelimiter', + ]; + const ret: any = {}; + // tslint:disable-next-line:forin + for (const key of INTERESTING_KEYS) { + const value = (n as any)[key]; + if (typeof value === 'string' || typeof value === 'number') { + ret[key] = value; + } + } + return JSON.stringify(ret); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/o-tree.ts b/packages/jsii-sampiler/lib/o-tree.ts new file mode 100644 index 0000000000..4b2f763191 --- /dev/null +++ b/packages/jsii-sampiler/lib/o-tree.ts @@ -0,0 +1,201 @@ + +export interface OTreeOptions { + /** + * Adjust indentation with the given number + * + * Indentation affects children. + * + * @default 0 + */ + indent?: number; + + /** + * Separate children with the given string + * + * @default '' + */ + separator?: string; + + /** + * Suffix the token after outdenting + * + * @default '' + */ + suffix?: string; + + /** + * Whether this part of the generated syntax is okay to insert newlines and comments + * + * @default false + */ + canBreakLine?: boolean; + + /** + * If set, a unique key which will cause only one node with the given key to be rendered. + * + * The outermost key is the one that will be rendered. + * + * Used to make it easier to keep the state necessary to render comments + * only once in the output tree, rather than keep the state in the + * language rendered. + * + * @default No conditional rendering + */ + renderOnce?: string; +} + +/** + * "Output" Tree + * + * Tree-like structure that holds sequences of trees and strings, which + * can be rendered to an output stream. + */ +export class OTree { + public static simplify(xs: Array): Array { + return xs.filter(notUndefined).filter(notEmpty); + } + + public readonly attachComment: boolean; + + private readonly prefix: Array; + private readonly children: Array; + + constructor( + prefix: Array, + children?: Array, + private readonly options: OTreeOptions = {}) { + + this.prefix = OTree.simplify(prefix); + this.children = OTree.simplify(children || []); + this.attachComment = !!options.canBreakLine; + } + + public write(sink: OTreeSink) { + if (!sink.tagOnce(this.options.renderOnce)) { return; } + + for (const x of this.prefix) { + sink.write(x); + } + + const popIndent = sink.requestIndentChange(this.options.indent || 0); + let mark = sink.mark(); + for (const child of this.children || []) { + if (this.options.separator && mark.wroteNonWhitespaceSinceMark) { sink.write(this.options.separator); } + mark = sink.mark(); + + sink.write(child); + } + + popIndent(); + + if (this.options.suffix) { + sink.write(this.options.suffix); + } + } + + public get isEmpty() { + return this.prefix.length + this.children.length === 0; + } + + public toString() { + return ``; + } +} + +export const NO_SYNTAX = new OTree([]); + +export class UnknownSyntax extends OTree { +} + +export interface SinkMark { + readonly wroteNonWhitespaceSinceMark: boolean; +} + +export class OTreeSink { + private readonly indentLevels: number[] = [0]; + private readonly fragments = new Array(); + private singletonsRendered = new Set(); + private pendingIndentChange = 0; + + public tagOnce(key: string | undefined): boolean { + if (key === undefined) { return true; } + if (this.singletonsRendered.has(key)) { return false; } + this.singletonsRendered.add(key); + return true; + } + + public mark(): SinkMark { + const self = this; + const markIndex = this.fragments.length; + + return { + get wroteNonWhitespaceSinceMark(): boolean { + return self.fragments.slice(markIndex).some(s => s.match(/[^\s]/)); + } + }; + } + + public write(text: string | OTree) { + if (text instanceof OTree) { + text.write(this); + } else { + if (containsNewline(text)) { + this.applyPendingIndentChange(); + } + this.append(text.replace(/\n/g, '\n' + ' '.repeat(this.currentIndent))); + } + } + + public requestIndentChange(x: number): () => void { + if (x === 0) { return () => undefined; } + + this.pendingIndentChange = x; + const currentIndentState = this.indentLevels.length; + const self = this; + + // Return a pop function which will reset to the current indent state, + // regardless of whether the indent was actually applied or not. + return () => { + self.indentLevels.splice(currentIndentState); + self.pendingIndentChange = 0; + }; + } + + public toString() { + // Strip trailing whitespace from every line + return this.fragments.join('').replace(/[ \t]+$/gm, ''); + } + + private append(x: string) { + this.fragments.push(x); + } + + private applyPendingIndentChange() { + if (this.pendingIndentChange !== 0) { + this.indentLevels.push(this.currentIndent + this.pendingIndentChange); + this.pendingIndentChange = 0; + } + } + + private get currentIndent() { + return this.indentLevels[this.indentLevels.length - 1]; + } +} + +function notUndefined(x: T | undefined): x is T { + return x !== undefined; +} + +function notEmpty(x: OTree | string) { + return x instanceof OTree ? !x.isEmpty : x !== ''; +} + +export function renderTree(tree: OTree): string { + const sink = new OTreeSink(); + tree.write(sink); + return sink.toString(); +} + +function containsNewline(x: string) { + return x.indexOf('\n') !== -1; +} diff --git a/packages/jsii-sampiler/lib/translate.ts b/packages/jsii-sampiler/lib/translate.ts new file mode 100644 index 0000000000..c9bc42a9ce --- /dev/null +++ b/packages/jsii-sampiler/lib/translate.ts @@ -0,0 +1,118 @@ +import fs = require('fs-extra'); +import ts = require('typescript'); +import { AstConverter, AstHandler, ConvertOptions } from './converter'; +import { transformMarkdown } from './markdown/markdown'; +import { MarkdownRenderer } from './markdown/markdown-renderer'; +import { ReplaceCodeTransform } from './markdown/replace-code-renderer'; +import { OTree, renderTree } from './o-tree'; +import { TypeScriptCompiler } from './typescript/ts-compiler'; +import { inTempDir } from './util'; + +export interface Source { + withFile(fn: (fileName: string) => A): A; + withContents(fn: (fileName: string, contents: string) => A): A; +} + +export class FileSource implements Source { + constructor(private readonly fileName: string) { } + + public withFile(fn: (fileName: string) => A): A { + return fn(this.fileName); + } + + public withContents(fn: (fileName: string, contents: string) => A): A { + const contents = fs.readFileSync(this.fileName, 'utf-8'); + return fn(this.fileName, contents); + } +} + +export class LiteralSource implements Source { + constructor(private readonly source: string, private readonly filenameHint = 'index.ts') { } + + public withFile(fn: (fileName: string) => A): A { + return inTempDir(() => { + fs.writeFileSync(this.filenameHint, this.source); + return fn(this.filenameHint); + }); + } + + public withContents(fn: (fileName: string, contents: string) => A): A { + return fn(this.filenameHint, this.source); + } +} + +export interface TranslateMarkdownOptions extends ConvertOptions { + /** + * What language to put in the returned markdown blocks + */ + languageIdentifier?: string; +} + +export function translateMarkdown(markdown: Source, visitor: AstHandler, options: TranslateMarkdownOptions = {}): TranslateResult { + const compiler = new TypeScriptCompiler(); + + let index = 0; + const diagnostics = new Array(); + + const translatedMarkdown = markdown.withContents((filename, contents) => { + return transformMarkdown(contents, new MarkdownRenderer(), new ReplaceCodeTransform(code => { + if (code.language !== 'typescript' && code.language !== 'ts') { return code; } + + index += 1; + const snippetSource = new LiteralSource(code.source, `${filename}-snippet${index}.ts`); + const snippetTranslation = translateSnippet(snippetSource, compiler, visitor, options); + + diagnostics.push(...snippetTranslation.diagnostics); + + return { language: options.languageIdentifier || '', source: renderTree(snippetTranslation.tree) + '\n' }; + })); + }); + + return { tree: new OTree([translatedMarkdown]), diagnostics }; +} + +export type TranslateOptions = ConvertOptions; + +export function translateTypeScript(source: Source, visitor: AstHandler, options: TranslateOptions = {}): TranslateResult { + const compiler = new TypeScriptCompiler(); + + return translateSnippet(source, compiler, visitor, options); +} + +function translateSnippet(source: Source, compiler: TypeScriptCompiler, visitor: AstHandler, options: TranslateOptions = {}): TranslateResult { + return source.withContents((filename, contents) => { + const result = compiler.compileInMemory(filename, contents); + + const converter = new AstConverter(result.rootFile, result.program.getTypeChecker(), visitor, options); + const converted = converter.convert(result.rootFile); + + return { + tree: converted, + diagnostics: converter.diagnostics + }; + }); +} + +export function printDiagnostics(diags: ts.Diagnostic[], stream: NodeJS.WritableStream) { + diags.forEach(d => printDiagnostic(d, stream)); +} + +export function printDiagnostic(diag: ts.Diagnostic, stream: NodeJS.WritableStream) { + const host = { + getCurrentDirectory() { return '.'; }, + getCanonicalFileName(fileName: string) { return fileName; }, + getNewLine() { return '\n'; } + }; + + const message = ts.formatDiagnosticsWithColorAndContext([diag], host); + stream.write(message); +} + +export function isErrorDiagnostic(diag: ts.Diagnostic) { + return diag.category === ts.DiagnosticCategory.Error; +} + +export interface TranslateResult { + tree: OTree; + diagnostics: ts.Diagnostic[]; +} diff --git a/packages/jsii-sampiler/lib/typescript/ast-utils.ts b/packages/jsii-sampiler/lib/typescript/ast-utils.ts new file mode 100644 index 0000000000..0d5b474e60 --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/ast-utils.ts @@ -0,0 +1,334 @@ +import ts = require('typescript'); + +export function stripCommentMarkers(comment: string, multiline: boolean) { + if (multiline) { + // The text *must* start with '/*' and end with '*/'. + // Strip leading '*' from every remaining line (first line because of '**', + // other lines because of continuations. + return comment.substring(2, comment.length - 2) + .replace(/^[ \t]+/g, '') // Strip all leading whitepace + .replace(/[ \t]+$/g, '') // Strip all trailing whitepace + .replace(/^[ \t]*\*[ \t]?/gm, ''); // Strip "* " from start of line + } else { + // The text *must* start with '//' + return comment.replace(/^\/\/[ \t]?/gm, ''); + } +} + +export function stringFromLiteral(expr: ts.Expression) { + if (ts.isStringLiteral(expr)) { + return expr.text; + } + return '???'; +} + +/** + * All types of nodes that can be captured using `nodeOfType`, and the type of Node they map to + */ +export type CapturableNodes = { + [ts.SyntaxKind.ImportDeclaration]: ts.ImportDeclaration, + [ts.SyntaxKind.VariableDeclaration]: ts.VariableDeclaration, + [ts.SyntaxKind.ExternalModuleReference]: ts.ExternalModuleReference, + [ts.SyntaxKind.NamespaceImport]: ts.NamespaceImport, + [ts.SyntaxKind.NamedImports]: ts.NamedImports, + [ts.SyntaxKind.ImportSpecifier]: ts.ImportSpecifier, + [ts.SyntaxKind.StringLiteral]: ts.StringLiteral, +}; + +export type AstMatcher = (nodes?: ts.Node[]) => A | undefined; + +/** + * Return AST children of the given node + * + * Difference with node.getChildren(): + * + * - node.getChildren() must take a SourceFile (will fail if it doesn't get it) + * and returns a mix of abstract and concrete syntax nodes. + * - This function function will ONLY return abstract syntax nodes. + */ +export function nodeChildren(node: ts.Node): ts.Node[] { + const ret = new Array(); + node.forEachChild(n => { ret.push(n); }); + return ret; +} + +/** + * Match a single node of a given type + * + * Capture name is first so that the IDE can detect eagerly that we're falling into + * that overload and properly autocomplete the recognized node types from CapturableNodes. + * + * Looks like SyntaxList nodes appear in the printed AST, but they don't actually appear + */ +export function nodeOfType(syntaxKind: ts.SyntaxKind, children?: AstMatcher): AstMatcher; +// tslint:disable-next-line:max-line-length +export function nodeOfType(capture: N, capturableNodeType: S, children?: AstMatcher): AstMatcher; +// tslint:disable-next-line:max-line-length +export function nodeOfType(syntaxKindOrCaptureName: ts.SyntaxKind | N, nodeTypeOrChildren?: S | AstMatcher, children?: AstMatcher): AstMatcher | AstMatcher { + const capturing = typeof syntaxKindOrCaptureName === 'string'; // Determine which overload we're in (SyntaxKind is a number) + + const realNext = (capturing ? children : nodeTypeOrChildren as AstMatcher) || DONE; + const realCapture = capturing ? syntaxKindOrCaptureName as N : undefined; + const realSyntaxKind = capturing ? nodeTypeOrChildren : syntaxKindOrCaptureName; + + return (nodes) => { + for (const node of nodes || []) { + if (node.kind === realSyntaxKind) { + const ret = realNext(nodeChildren(node)); + if (!ret) { continue; } + + if (realCapture) { + return Object.assign(ret, { [realCapture]: node as CapturableNodes[S] }) as any; + } + return ret; + } + } + return undefined; + }; +} + +export function anyNode(): AstMatcher<{}>; +export function anyNode(children: AstMatcher): AstMatcher; +export function anyNode(children?: AstMatcher): AstMatcher | AstMatcher<{}> { + const realNext = children || DONE; + return nodes => { + for (const node of nodes || []) { + const m = realNext(nodeChildren(node)); + if (m) { return m; } + } + return undefined; + }; +} + +// Does not capture deeper because how would we even represent that? +// tslint:disable-next-line:max-line-length +export function allOfType(s: S, name: N, children?: AstMatcher): AstMatcher<{[key in N]: Array}> { + type ArrayType = Array; + type ReturnType = {[key in N]: ArrayType}; + const realNext = children || DONE; + + return nodes => { + let ret: ReturnType | undefined; + for (const node of nodes || []) { + if (node.kind === s) { + if (realNext(nodeChildren(node))) { + if (!ret) { ret = { [name]: new Array() } as ReturnType; } + ret[name].push(node as any); + } + } + } + return ret; + }; +} + +export const DONE: AstMatcher<{}> = () => ({}); + +/** + * Run a matcher against a node and return (or invoke a callback with) the accumulated bindings + */ +export function matchAst(node: ts.Node, matcher: AstMatcher): A | undefined; +export function matchAst(node: ts.Node, matcher: AstMatcher, cb: (bindings: A) => void): boolean; +export function matchAst(node: ts.Node, matcher: AstMatcher, cb?: (bindings: A) => void): boolean | A | undefined { + const matched = matcher([node]); + if (cb) { + if (matched) { cb(matched); } + return !!matched; + } + return matched; +} + +/* +function zip(xs: Iterable, ys: Iterable): IterableIterator<[A, B | undefined]>; +function zip(xs: Iterable, ys: Iterable, defY: C): IterableIterator<[A, B | C]>; +function* zip(xs: Iterable, ys: Iterable, defY?: C): IterableIterator<[A, B | C]> { + const iterX = xs[Symbol.iterator](); + const iterY = ys[Symbol.iterator](); + + let x = iterX.next(); + let y = iterY.next(); + while (!x.done) { + yield [x.value, !y.done ? y.value : defY as any]; + + x = iterX.next(); + if (!y.done) { y = iterY.next(); } + } +} +*/ + +/** + * Count the newlines in a given piece of string that aren't in comment blocks + */ +export function countNakedNewlines(str: string) { + let ret = 0; + scanText(str, 0, str.length) + .filter(s => s.type === 'other' || s.type === 'blockcomment') + .forEach(s => { + if (s.type === 'other') { + // Count newlines in non-comments + for (let i = s.pos; i < s.end; i++) { + if (str[i] === '\n') { ret++; } + } + } else { + // Discount newlines at the end of block comments + if (s.hasTrailingNewLine) { ret--; } + } + }); + return ret; +} + +export function repeatNewlines(str: string) { + return '\n'.repeat(Math.min(2, countNakedNewlines(str))); +} + +const WHITESPACE = [' ', '\t', '\r', '\n']; + +/** + * Extract single-line and multi-line comments from the given string + * + * Rewritten because I can't get ts.getLeadingComments and ts.getTrailingComments to do what I want. + */ +export function extractComments(text: string, start: number): ts.CommentRange[] { + return scanText(text, start) + .filter(s => s.type === 'blockcomment' || s.type === 'linecomment') + .map(commentRangeFromTextRange); +} + +export function commentRangeFromTextRange(rng: TextRange): ts.CommentRange { + return { + kind: rng.type === 'blockcomment' ? ts.SyntaxKind.MultiLineCommentTrivia : ts.SyntaxKind.SingleLineCommentTrivia, + pos: rng.pos, + end: rng.end, + hasTrailingNewLine: rng.hasTrailingNewLine + }; +} + +interface TextRange { + pos: number; + end: number; + type: 'linecomment' | 'blockcomment' | 'other'; + hasTrailingNewLine: boolean; +} + +/** + * Extract spans of comments and non-comments out of the string + * + * Stop at 'end' when given, or the first non-whitespace character in a + * non-comment if not given. + */ +export function scanText(text: string, start: number, end?: number): TextRange[] { + const ret: TextRange[] = []; + + let pos = start; + const stopAtCode = end === undefined; + if (end === undefined) { end = text.length; } + while (pos < end) { + const ch = text[pos]; + + if (WHITESPACE.includes(ch)) { pos++; continue; } + + if (ch === '/' && text[pos + 1] === '/') { + accumulateTextBlock(); + scanSinglelineComment(); + continue; + } + + if (ch === '/' && text[pos + 1] === '*') { + accumulateTextBlock(); + scanMultilineComment(); + continue; + } + + // Non-whitespace, non-comment, must be regular token. End if we're not scanning + // to a particular location, otherwise continue. + if (stopAtCode) { + break; + } + + pos++; + } + + accumulateTextBlock(); + + return ret; + + function scanMultilineComment() { + const endOfComment = findNext('*/', pos + 2); + ret.push({ + type: 'blockcomment', + hasTrailingNewLine: ['\n', '\r'].includes(text[endOfComment + 2]), + pos, + end: endOfComment + 2 + }); + pos = endOfComment + 2; + start = pos; + } + + function scanSinglelineComment() { + const nl = Math.min(findNext('\r', pos + 2), findNext('\n', pos + 2)); + ret.push({ + type: 'linecomment', + hasTrailingNewLine: true, + pos, + end: nl + }); + pos = nl + 1; + start = pos; + } + + function accumulateTextBlock() { + if (pos - start > 0) { + ret.push({ + type: 'other', + hasTrailingNewLine: false, + pos: start, + end: pos + }); + start = pos; + } + } + + function findNext(sub: string, startPos: number) { + const f = text.indexOf(sub, startPos); + if (f === -1) { return text.length; } + return f; + } +} + +const VOID_SHOW_KEYWORD = 'show'; + +export function extractMaskingVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + const expr = extractVoidExpression(node); + if (!expr) { return undefined; } + if (ts.isStringLiteral(expr.expression) && expr.expression.text === VOID_SHOW_KEYWORD) { + return undefined; + } + return expr; +} + +export function extractShowingVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + const expr = extractVoidExpression(node); + if (!expr) { return undefined; } + if (ts.isStringLiteral(expr.expression) && expr.expression.text === VOID_SHOW_KEYWORD) { + return expr; + } + return undefined; +} + +/** + * Return the string argument to a void expression if it exists + */ +export function voidExpressionString(node: ts.VoidExpression): string | undefined { + if (ts.isStringLiteral(node.expression)) { return node.expression.text; } + return undefined; +} + +/** + * We use void directives as pragmas. Extract the void directives here + */ +export function extractVoidExpression(node: ts.Node): ts.VoidExpression | undefined { + if (ts.isVoidExpression(node)) { return node; } + if (ts.isExpressionStatement(node)) { return extractVoidExpression(node.expression); } + if (ts.isParenthesizedExpression(node)) { return extractVoidExpression(node.expression); } + if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.CommaToken) { return extractVoidExpression(node.left); } + return undefined; +} diff --git a/packages/jsii-sampiler/lib/typescript/imports.ts b/packages/jsii-sampiler/lib/typescript/imports.ts new file mode 100644 index 0000000000..55970f355c --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/imports.ts @@ -0,0 +1,76 @@ +import ts = require('typescript'); +import { AstConverter } from '../converter'; +import { allOfType, matchAst, nodeOfType, stringFromLiteral } from "./ast-utils"; + +/** + * Our own unification of import statements + */ +export interface ImportStatement { + node: ts.Node; + packageName: string; + imports: FullImport | SelectiveImport; +} + +export type FullImport = { import: 'full', alias: string }; +export type SelectiveImport = { import: 'selective', elements: ImportBinding[] }; + +export interface ImportBinding { + sourceName: string; + alias?: string; +} + +export function analyzeImportEquals(node: ts.ImportEqualsDeclaration, context: AstConverter): ImportStatement { + let moduleName = '???'; + matchAst(node.moduleReference, + nodeOfType('ref', ts.SyntaxKind.ExternalModuleReference), + bindings => { + moduleName = stringFromLiteral(bindings.ref.expression); + }); + + return { + node, + packageName: moduleName, + imports: { import: 'full', alias: context.textOf(node.name) } + }; +} + +export function analyzeImportDeclaration(node: ts.ImportDeclaration, context: AstConverter): ImportStatement { + const packageName = stringFromLiteral(node.moduleSpecifier); + + const starBindings = matchAst(node, + nodeOfType(ts.SyntaxKind.ImportDeclaration, + nodeOfType(ts.SyntaxKind.ImportClause, + nodeOfType('namespace', ts.SyntaxKind.NamespaceImport)))); + + if (starBindings) { + return { + node, + packageName, + imports: { import: 'full', alias: context.textOf(starBindings.namespace.name) } + }; + } + + const namedBindings = matchAst(node, + nodeOfType(ts.SyntaxKind.ImportDeclaration, + nodeOfType(ts.SyntaxKind.ImportClause, + nodeOfType(ts.SyntaxKind.NamedImports, + allOfType(ts.SyntaxKind.ImportSpecifier, 'specifiers'))))); + + const elements: ImportBinding[] = []; + if (namedBindings) { + elements.push(...namedBindings.specifiers.map(spec => ( + // regular import { name }, renamed import { propertyName, name } + spec.propertyName ? { + sourceName: context.textOf(spec.propertyName), + alias: spec.name ? context.textOf(spec.name) : '???' + } : { + sourceName: spec.name ? context.textOf(spec.name) : '???' + }))); + } + + return { + node, + packageName, + imports: { import: 'selective', elements } + }; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/typescript/ts-compiler.ts b/packages/jsii-sampiler/lib/typescript/ts-compiler.ts new file mode 100644 index 0000000000..74397c1250 --- /dev/null +++ b/packages/jsii-sampiler/lib/typescript/ts-compiler.ts @@ -0,0 +1,85 @@ +import ts = require('typescript'); + +export class TypeScriptCompiler { + private readonly realHost: ts.CompilerHost; + + constructor() { + this.realHost = ts.createCompilerHost(STANDARD_COMPILER_OPTIONS, true); + } + + public createInMemoryCompilerHost(sourcePath: string, sourceContents: string): ts.CompilerHost { + const realHost = this.realHost; + const sourceFile = ts.createSourceFile(sourcePath, sourceContents, ts.ScriptTarget.Latest); + + return { + fileExists: filePath => filePath === sourcePath || realHost.fileExists(filePath), + directoryExists: realHost.directoryExists && realHost.directoryExists.bind(realHost), + getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost), + getDirectories: realHost.getDirectories && realHost.getDirectories.bind(realHost), + getCanonicalFileName: fileName => realHost.getCanonicalFileName(fileName), + getNewLine: realHost.getNewLine.bind(realHost), + getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost), + getSourceFile: (fileName, languageVersion, onError, shouldCreateNewSourceFile) => fileName === sourcePath + ? sourceFile + : realHost.getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile), + readFile: filePath => filePath === sourcePath + ? sourceContents + : realHost.readFile(filePath), + useCaseSensitiveFileNames: () => realHost.useCaseSensitiveFileNames(), + writeFile(_fileName, _data) { /* nothing */ } + }; + } + + public compileInMemory(filename: string, contents: string): CompilationResult { + if (!filename.endsWith('.ts')) { + // Necessary or the TypeScript compiler won't compile the file. + filename += '.ts'; + } + + const program = ts.createProgram({ + rootNames: [filename], + options: STANDARD_COMPILER_OPTIONS, + host: this.createInMemoryCompilerHost(filename, contents), + }); + + const rootFiles = program.getSourceFiles().filter(f => f.fileName === filename); + if (rootFiles.length === 0) { + throw new Error(`Oopsie -- couldn't find root file back`); + } + const rootFile = rootFiles[0]; + + return { program, rootFile }; + } +} + +export interface CompilationResult { + program: ts.Program; + rootFile: ts.SourceFile; +} + +export const STANDARD_COMPILER_OPTIONS: ts.CompilerOptions = { + alwaysStrict: true, + charset: 'utf8', + declaration: true, + experimentalDecorators: true, + inlineSourceMap: true, + inlineSources: true, + lib: ['lib.es2016.d.ts', 'lib.es2017.object.d.ts', 'lib.es2017.string.d.ts'], + module: ts.ModuleKind.CommonJS, + noEmitOnError: true, + noFallthroughCasesInSwitch: true, + noImplicitAny: true, + noImplicitReturns: true, + noImplicitThis: true, + noUnusedLocals: true, + noUnusedParameters: true, + resolveJsonModule: true, + strict: true, + strictNullChecks: true, + strictPropertyInitialization: true, + stripInternal: true, + target: ts.ScriptTarget.ES2018, + // Incremental builds + incremental: true, + tsBuildInfoFile: '.tsbuildinfo', +}; \ No newline at end of file diff --git a/packages/jsii-sampiler/lib/util.ts b/packages/jsii-sampiler/lib/util.ts new file mode 100644 index 0000000000..f4c79948a2 --- /dev/null +++ b/packages/jsii-sampiler/lib/util.ts @@ -0,0 +1,26 @@ +import fs = require('fs-extra'); +import os = require('os'); +import path = require('path'); +import { renderTree, Source, translateTypeScript } from '.'; +import { VisualizeAstVisitor } from './languages/visualize'; + +export function startsWithUppercase(x: string) { + return x.match(/^[A-Z]/); +} + +export function inTempDir(block: () => T): T { + const origDir = process.cwd(); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii')); + process.chdir(tmpDir); + const ret = block(); + process.chdir(origDir); + fs.removeSync(tmpDir); + return ret; +} + +export function visualizeTypeScriptAst(source: Source) { + const vis = translateTypeScript(source, new VisualizeAstVisitor(true), { + bestEffort: false + }); + return renderTree(vis.tree) + '\n'; +} diff --git a/packages/jsii-sampiler/package-lock.json b/packages/jsii-sampiler/package-lock.json new file mode 100644 index 0000000000..14706618a0 --- /dev/null +++ b/packages/jsii-sampiler/package-lock.json @@ -0,0 +1,4917 @@ +{ + "name": "jsii-samples", + "version": "0.16.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helpers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz", + "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/commonmark": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.4.tgz", + "integrity": "sha512-7koSjp08QxKoS1/+3T15+kD7+vqOUvZRHvM8PutF3Xsk5aAEkdlIGRsHJ3/XsC3izoqTwBdRW/vH7rzCKkIicA==", + "dev": true + }, + "@types/fs-extra": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", + "integrity": "sha512-bCtL5v9zdbQW86yexOlXWTEGvLNqWxMFyi7gQA7Gcthbezr2cPSOb8SkESVKA937QD5cIwOFLDFt0MQoXOEr9Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.0.18", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.18.tgz", + "integrity": "sha512-jcDDXdjTcrQzdN06+TSVsPPqxvsZA/5QkYfIZlq1JMw7FdP5AZylbOc+6B/cuDurctRe+MziUMtQ3xQdrbjqyQ==", + "dev": true, + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", + "dev": true + }, + "@types/node": { + "version": "12.6.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz", + "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.0.tgz", + "integrity": "sha512-hY0o+kcz9M6kH32NUeb6VURghqMuCVkiUx+8Btsqhj4Hhov/hVGUx9DmBJeIkzlp1uAQK4wngQBCjqWdUUkFyA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw==", + "dev": true + }, + "abab": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.1.tgz", + "integrity": "sha512-1zSbbCuoIjafKZ3mblY5ikvAb0ODUbqBnFuUb7f6uLeQhhGJ0vEV4ntmtxKLT2WgXCO94E07BjunsIw1jOMPZw==", + "dev": true + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.3.tgz", + "integrity": "sha512-vkR40VwS2SYO98AIeFvzWWh+xyc2qi9s7OoXSFEGIP/rOJKzjnhykaZJNnHdoq4BL2gGxI5EZOU16z896EYnOQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "bser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.0.tgz", + "integrity": "sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "commonmark": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.0.tgz", + "integrity": "sha512-Wc3kvAIm0EK85pHsM95Fev31wEN6/zQpwd2qcLDL8psjHRoUFvUeGHevIJAdToWUuFoX8WI/gmeDauqy32xgJQ==", + "requires": { + "entities": "~ 1.1.1", + "mdurl": "~ 1.0.1", + "minimist": "~ 1.2.0", + "string.prototype.repeat": "^0.2.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.1.tgz", + "integrity": "sha512-cp/Tb1oA/rh2X7vqeSOvM+TSo3UkJLX70eNihgVEvnzwAgikjkTFr/QVgRCaxjm0knCNQzNoxxxcw2zO2LJdZA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.0.0", + "string.prototype.trimright": "^2.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", + "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hosted-git-info": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "memory-streams": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz", + "integrity": "sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==", + "dev": true, + "requires": { + "readable-stream": "~1.0.2" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nwsapi": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "prompts": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.2.1.tgz", + "integrity": "sha512-VObPvJiWPhpZI6C5m60XOzTfnYg/xc/an+r9VYymj9WJW3B/DIH+REzjpAACPf8brwPeP+7vz3bIim3S+AaMjw==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, + "psl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.1.tgz", + "integrity": "sha512-2KLd5fKOdAfShtY2d/8XDWVRnmp3zp40Qt6ge2zBPFARLXOGUf2fHD5eg+TV/5oxBtQKVhjUaKFsAaE4HnwfSA==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "react-is": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sisteransi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.3.tgz", + "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string.prototype.repeat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", + "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=" + }, + "string.prototype.trimleft": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.0.0.tgz", + "integrity": "sha1-aLaqjhYsaoDnbjqKDC50cYbicf8=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimright": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.0.0.tgz", + "integrity": "sha1-q0pW2AKgH75yk+EehPJNyBZGYd0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typescript": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", + "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==" + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/packages/jsii-sampiler/package.json b/packages/jsii-sampiler/package.json new file mode 100644 index 0000000000..b21481f984 --- /dev/null +++ b/packages/jsii-sampiler/package.json @@ -0,0 +1,47 @@ +{ + "name": "jsii-sampiler", + "version": "0.16.0", + "description": "Translate TypeScript code snippets to other languages", + "main": "lib/index.js", + "bin": { + "jsii-samples": "bin/jsii-samples" + }, + "scripts": { + "build": "tsc", + "test": "jest", + "demo": "npm run build && bin/jsii-samples examples/controlflow.ts", + "incomplete-demo": "npm run build && time node bin/jsii-samples examples/incomplete.ts" + }, + "devDependencies": { + "@types/commonmark": "^0.27.4", + "@types/fs-extra": "^8.0.0", + "@types/jest": "^24.0.18", + "@types/node": "^12.6.8", + "@types/yargs": "^13.0.0", + "jest": "^24.9.0", + "memory-streams": "^0.1.3", + "typescript": "^3.5.3" + }, + "dependencies": { + "commonmark": "^0.29.0", + "fs-extra": "^8.1.0", + "typescript": "~3.6.2", + "yargs": "^13.3.0" + }, + "jest": { + "moduleFileExtensions": [ + "js" + ] + }, + "license": "Apache-2.0", + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/jsii.git", + "directory": "packages/jsii-samples" + } +} diff --git a/packages/jsii-sampiler/test/markdown/roundtrip.test.ts b/packages/jsii-sampiler/test/markdown/roundtrip.test.ts new file mode 100644 index 0000000000..5307b2576f --- /dev/null +++ b/packages/jsii-sampiler/test/markdown/roundtrip.test.ts @@ -0,0 +1,164 @@ +import { transformMarkdown } from "../../lib/markdown/markdown"; +import { MarkdownRenderer } from "../../lib/markdown/markdown-renderer"; +import { StructureRenderer } from "../../lib/markdown/structure-renderer"; + +const DEBUG = false; + +test('can roundtrip markdown', () => { + expectOutput(` +# Hello + +Yes please. + +> this +> +> works +`, ` +# Hello + +Yes please. + +> this +> +> works +`); +}); + +test('can roundtrip lists', () => { + expectOutput(` +* A list. +* Another list. + * A nested list. + +1. We might have numbers. +2. Yes it's a numbered list. + `, ` +* A list. +* Another list. + + * A nested list. + +1. We might have numbers. +2. Yes it's a numbered list. + `); +}); + +test('list with paragraphs', () => { + expectOutput(` +* A list. +* Another list. + + Para2. + `, ` +* A list. +* Another list. + + Para2. + `); +}); + +test('can roundtrip complex hyperlink texts', () => { + expectOutput(` +This is a [hyperlink](https://amazonaws.com). + +![Image though](fun.gif). + +This is a [` + '`' + `monospace hyperlink` + '`' + `](https://amazonaws.com). + `, ` +This is a [hyperlink](https://amazonaws.com). + +![Image though](fun.gif). + +This is a [` + '`' + `monospace hyperlink` + '`' + `](https://amazonaws.com). + `); +}); + +test('fenced code block', () => { + expectOutput([ + 'before', + '```ts', + 'banana', + ' second', + '```', + 'after', + ].join('\n'), [ + 'before', + '', + '```ts', + 'banana', + ' second', + '```', + '', + 'after', + ].join('\n')); +}); + +test('indented code block', () => { + expectOutput([ + 'before', + '', + ' banana', + ' second', + '', + 'after', + ].join('\n'), [ + 'before', + '', + '```', + 'banana', + ' second', + '```', + '', + 'after', + ].join('\n')); +}); + +test('code block followed by heading leaves paragraph marker', () => { + expectOutput([ + '```', + 'code_here', + '```', + '', + '# Heading', + ].join('\n'), [ + '```', + 'code_here', + '```', + '', + '# Heading', + ].join('\n')); +}); + +test('emphases', () => { + expectOutput(` +Text with *emphasis* and **strongness**. + +Other style _emphasis_ and __strongness__. + `, ` +Text with *emphasis* and **strongness**. + +Other style *emphasis* and **strongness**. + `); +}); + +test('headings', () => { + expectOutput(` +## Heading 2 +### Heading 3 + `, ` +## Heading 2 + +### Heading 3 + `); +}); + +function expectOutput(source: string, expected: string) { + if (DEBUG) { + const struct = new StructureRenderer(); + // tslint:disable-next-line:no-console + console.log(transformMarkdown(source, struct)); + } + + const output = transformMarkdown(source, new MarkdownRenderer()); + expect(output.trim()).toEqual(expected.trim()); +} \ No newline at end of file diff --git a/packages/jsii-sampiler/test/otree.test.ts b/packages/jsii-sampiler/test/otree.test.ts new file mode 100644 index 0000000000..1763c18e6e --- /dev/null +++ b/packages/jsii-sampiler/test/otree.test.ts @@ -0,0 +1,50 @@ +import { OTree, renderTree } from "../lib/o-tree"; + +test('test indentation', () => { + const tree = new OTree(['{'], + ['\na', '\nb', '\nc'], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual('{\n a,\n b,\n c\n}'); +}); + +test('collapse subsequent unused indentation', () => { + const tree = new OTree(['{'], + [new OTree([], ['\na', '\nb', '\nc'], { indent: 4, separator: ', ' })], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual('{\n a,\n b,\n c\n}'); +}); + +test('don not collapse subsequent USED indentation', () => { + const tree = new OTree(['{'], + [ + '\na', + new OTree(['\n{'], ['\na', '\nb', '\nc'], { indent: 4, separator: ', ', suffix: '\n}' }), + '\nb', + ], + { + separator: ', ', + indent: 4, + suffix: '\n}', + }); + + expect(renderTree(tree)).toEqual([ + '{', + ' a,', + ' {', + ' a,', + ' b,', + ' c', + ' },', + ' b', + '}'].join('\n')); +}); diff --git a/packages/jsii-sampiler/test/python/calls.test.ts b/packages/jsii-sampiler/test/python/calls.test.ts new file mode 100644 index 0000000000..14dfe7a163 --- /dev/null +++ b/packages/jsii-sampiler/test/python/calls.test.ts @@ -0,0 +1,197 @@ +import { expectPython } from "./python"; + +test('function call', async () => { + expectPython(` + callSomeFunction(1, 2, 3); + `, ` + call_some_function(1, 2, 3) + `); +}); + +test('method call', async () => { + expectPython(` + someObject.callSomeFunction(1, 2, 3); + `, ` + some_object.call_some_function(1, 2, 3) + `); +}); + +test('static function call', async () => { + expectPython(` + SomeObject.callSomeFunction(1, 2, 3); + `, ` + SomeObject.call_some_function(1, 2, 3) + `); +}); + +test('translate this to self when calling', async () => { + expectPython(` + callSomeFunction(this, 25); + `, ` + call_some_function(self, 25) + `); +}); + +test('translate this to self on LHS of object accessor', async () => { + expectPython(` + this.callSomeFunction(25); + `, ` + self.call_some_function(25) + `); +}); + +test('translate object literals in function call', async () => { + expectPython(` + foo(25, { foo: 3, banana: "hello" }); + `, ` + foo(25, foo=3, banana="hello") + `); +}); + +test('translate object literals with newlines', async () => { + expectPython(` + foo(25, { + foo: 3, + banana: "hello" + }); + `, ` + foo(25, + foo=3, + banana="hello" + ) + `); +}); + +test('translate object literals with multiple newlines', async () => { + expectPython(` + foo(25, { + foo: 3, + + banana: "hello" + }); + `, ` + foo(25, + foo=3, + + banana="hello" + ) + `); +}); + +test('translate object literals only one level deep', async () => { + // FIXME: This is wrong! We need the types here! + expectPython(` + foo(25, { foo: 3, deeper: { a: 1, b: 2 }); + `, ` + foo(25, foo=3, deeper={"a": 1, "b": 2}) + `); +}); + +test('translate object literals second level with newlines', async () => { + expectPython(` + foo(25, { foo: 3, deeper: { + a: 1, + b: 2 + }); + `, ` + foo(25, foo=3, deeper={ + "a": 1, + "b": 2 + }) + `); +}); + +test('will type deep structs directly if type info is available', () => { + expectPython(` + interface BaseDeeperStruct { + a: number; + } + interface DeeperStruct extends BaseDeeperStruct { + b: number; + } + + interface OuterStruct { + foo: number; + deeper: DeeperStruct; + } + + function foo(x: number, outer: OuterStruct) { } + + foo(25, { foo: 3, deeper: { + a: 1, + b: 2 + }); + `, ` + def foo(x, *, foo, deeper): + pass + + foo(25, foo=3, deeper=DeeperStruct( + a=1, + b=2 + )) + `); +}); + +test('default arguments get =None appended', () => { + expectPython(` + function foo(x: string | undefined, y: string = 'hello', z?: string) { + console.log(x, y, z); + } + `, ` + def foo(x=None, y=None, z=None): + print(x, y, z) + `); +}); + +test('default struct fields get =None appended', () => { + expectPython(` + interface Struct { + x: string | undefined; + y?: string; + } + function foo(s: Struct) { + console.log(s.x, s.y); + } + `, ` + def foo(*, x=None, y=None): + print(x, y) + `); +}); + +test('list of structs', () => { + expectPython(` + foo({ + list: [{ + a: 1, + b: 2 + }, { + a: 3, + b: 4, + }] + }); + `, ` + foo( + list=[{ + "a": 1, + "b": 2 + }, { + "a": 3, + "b": 4 + }] + ) + `); +}); + +test('literal map argument doesnt get keyworded', () => { + // requires type information to work + expectPython(` + function foo(xs: {[key: string]: string}) { } + + foo({ foo: 'bar', schmoo: 'schmar' }) + `, ` + def foo(xs): + pass + + foo({"foo": "bar", "schmoo": "schmar"}) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/classes.test.ts b/packages/jsii-sampiler/test/python/classes.test.ts new file mode 100644 index 0000000000..10571b3d53 --- /dev/null +++ b/packages/jsii-sampiler/test/python/classes.test.ts @@ -0,0 +1,166 @@ +import { expectPython } from "./python"; + +test('class declaration with fields and constructor', async () => { + // FIXME: This whitespace is not entirely correct, but it's not horrible + // and I don't know how to fix it for now. + expectPython(` + class MyClass { + private readonly x: string; + + constructor(y: string) { + this.x = y; + } + } + `, ` + class MyClass: + + def __init__(self, y): + self.x = y + `); +}); + +test('whitespace between multiple members', () => { + expectPython(` + class MyClass { + constructor(y: string) { + this.x = y; + } + + public hello() { + console.log(this.x); + } + + public bye() { + console.log('bye'); + } + } + `, ` + class MyClass: + def __init__(self, y): + self.x = y + + def hello(self): + print(self.x) + + def bye(self): + print("bye") + `); +}); + +test('whitespace between multiple empty members', () => { + expectPython(` + class MyClass { + constructor(y: string) { + this.x = y; + } + + public hello() { + } + + public bye() { + } + } + `, ` + class MyClass: + def __init__(self, y): + self.x = y + + def hello(self): + pass + + def bye(self): + pass + `); +}); + +test('invisible interfaces do not affect whitespace', async () => { + expectPython(` + class MyClass1 { + } + + interface ThisWillNotBeRendered { + } + + class MyClass2 { + } + `, ` + class MyClass1: + pass + + class MyClass2: + pass + `); +}); + +test.skip('class with implicit declaration', async () => { + expectPython(` + class MyClass { + private readonly x = 'bloep'; + } + `, ` + class MyClass: + def __init__(self): + self.x = 'bloep' + `); +}); + +test('class with inheritance', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + } + `, ` + class MyClass(cdk.SomeOtherClass): + pass + `); +}); + +test('class with inheritance and super class', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + constructor(x: string, y: string) { + super(x); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def __init__(self, x, y): + super().__init__(x) + `); +}); + +test('class with method', async () => { + expectPython(` + class MyClass extends cdk.SomeOtherClass { + public someMethod(x: string) { + console.log(x); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def some_method(self, x): + print(x) + `); +}); + +test('class with props argument', async () => { + expectPython(` + interface MyClassProps { + readonly prop1: string; + readonly prop2: number; + } + + class MyClass extends cdk.SomeOtherClass { + constructor(scope: cdk.Construct, id: string, props: MyClassProps) { + super(scope, id, props); + + print(props.prop1); + } + } + `, ` + class MyClass(cdk.SomeOtherClass): + def __init__(self, scope, id, *, prop1, prop2): + super().__init__(scope, id, prop1=prop1, prop2=prop2) + + print(prop1) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/comments.test.ts b/packages/jsii-sampiler/test/python/comments.test.ts new file mode 100644 index 0000000000..1fd2ecb011 --- /dev/null +++ b/packages/jsii-sampiler/test/python/comments.test.ts @@ -0,0 +1,84 @@ +import { expectPython } from "./python"; + +test('interleave single line comments with function call', () => { + expectPython(` + someFunction(arg1, { + // A comment before arg2 + arg2: 'string', + + // A comment before arg3 + arg3: 'boo' + }); + `, ` + some_function(arg1, + # A comment before arg2 + arg2="string", + + # A comment before arg3 + arg3="boo" + ) + `); +}); + +test('interleave multiline comments with function call', () => { + expectPython(` + someFunction(arg1, { + /* A comment before arg2 */ + arg2: 'string', + + /* A comment before arg3 */ + arg3: 'boo' + }); + `, ` + some_function(arg1, + # A comment before arg2 + arg2="string", + + # A comment before arg3 + arg3="boo" + ) + `); +}); + +test('no duplication of comments', () => { + // Harder than it looks! + expectPython(` + // Here's a comment + object.member.functionCall(new Class(), "argument"); + `, ` + # Here's a comment + object.member.function_call(Class(), "argument") + `); +}); + +test('empty lines in comments', () => { + expectPython(` + // Here's a comment + // + // Second line + someCall(); + `, ` + # Here's a comment + # + # Second line + some_call() + `); +}); + +test.skip('trailing comments', () => { + expectPython(` + someCall(); // Oh no, it's a call + + otherCall({ + value: 5, // That's a big number + secondValue: 6 // Even bigger + }); + `, ` + some_call() # Oh no, it's a call + + other_call( + value=5, # That's a big number + second_value=6 # Even bigger + ) + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/expressions.test.ts b/packages/jsii-sampiler/test/python/expressions.test.ts new file mode 100644 index 0000000000..1694927696 --- /dev/null +++ b/packages/jsii-sampiler/test/python/expressions.test.ts @@ -0,0 +1,61 @@ +import { expectPython } from "./python"; + +test('as-expression', () => { + expectPython(` + console.log(3 as number); + `, ` + print(3) + `); +}); + +test('prefix unary expression', () => { + expectPython(` + console.log(-3); + `, ` + print(-3) + `); +}); + +test('ellipsis at a random place', () => { + expectPython(` + callThisFunction(foo, ...); + `, ` + call_this_function(foo, ...) + `); +}); + +test('string interpolation', () => { + expectPython([ + 'const x = "world";', + 'const y = "well";', + 'console.log(`Hello, ${x}, it works ${y}!`);', + ].join('\n'), ` + x = "world" + y = "well" + print(f"Hello, {x}, it works {y}!") + `); +}); + +test('non-null expression', () => { + expectPython([ + 'const x = someObject!.someAttribute;', + ].join('\n'), ` + x = some_object.some_attribute + `); +}); + +test('double-quoted dict keys', () => { + expectPython([ + 'const x = { "key": "value" }', + ].join('\n'), ` + x = {"key": "value"} + `); +}); + +test('backtick string w/o substitutions', () => { + expectPython([ + 'const x = `some string`', + ].join('\n'), ` + x = "some string" + `); +}); diff --git a/packages/jsii-sampiler/test/python/hiding.test.ts b/packages/jsii-sampiler/test/python/hiding.test.ts new file mode 100644 index 0000000000..76dd0e1a7b --- /dev/null +++ b/packages/jsii-sampiler/test/python/hiding.test.ts @@ -0,0 +1,60 @@ +import { expectPython } from "./python"; + +test('hide top level statements using void directive', () => { + expectPython(` + void 1; + function foo(x: number) { + } + void 'show'; + foo(3); + `, ` + foo(3) + `); +}); + +test('hide block level statements using void directive', () => { + expectPython(` + if (true) { + console.log('everything is well'); + void 1; + subprocess.exec('rm -rf /'); + } + + onlyToEndOfBlock(); + `, ` + if True: + print("everything is well") + + only_to_end_of_block() + `); +}); + +test('hide parameter sequence', () => { + expectPython(` + foo(3, (void 1, 4), 5, 6, (void 'show', 7), 8); + `, ` + foo(3, 8) + `); +}); + +test('hide expression with explicit ellipsis', () => { + expectPython(` + foo(3, (void '...', 4), 5, 6, 7); + `, ` + foo(3, ...) + `); +}); + +test('hide statements with explicit ellipsis', () => { + expectPython(` + before(); + void 'block'; + middle(); + void 'show'; + after(); + `, ` + before() + # ... + after() + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/imports.test.ts b/packages/jsii-sampiler/test/python/imports.test.ts new file mode 100644 index 0000000000..6ac8e0bbbe --- /dev/null +++ b/packages/jsii-sampiler/test/python/imports.test.ts @@ -0,0 +1,26 @@ + +import { expectPython } from "./python"; + +test('import/require', async () => { + await expectPython(` + import mod = require('@scope/some-module'); + `, ` + import scope.some_module as mod + `); +}); + +test('import star-as', async () => { + await expectPython(` + import * as mod from '@scope/some-module'; + `, ` + import scope.some_module as mod + `); +}); + +test('selective import', async () => { + await expectPython(` + import { one, Two, someThree, four as renamed } from '@scope/some-module'; + `, ` + from scope.some_module import one, Two, some_three, four as renamed + `); +}); diff --git a/packages/jsii-sampiler/test/python/misc.test.ts b/packages/jsii-sampiler/test/python/misc.test.ts new file mode 100644 index 0000000000..3639e91b66 --- /dev/null +++ b/packages/jsii-sampiler/test/python/misc.test.ts @@ -0,0 +1,9 @@ +import { expectPython } from "./python"; + +test('booleans render to right primitives', () => { + expectPython(` + callFunction(true, false); + `, ` + call_function(True, False) + `); +}); diff --git a/packages/jsii-sampiler/test/python/python.ts b/packages/jsii-sampiler/test/python/python.ts new file mode 100644 index 0000000000..4a92989a10 --- /dev/null +++ b/packages/jsii-sampiler/test/python/python.ts @@ -0,0 +1,42 @@ +import { LiteralSource, renderTree, translateTypeScript } from "../../lib"; +import { PythonVisitor } from "../../lib/languages/python"; +import { visualizeTypeScriptAst } from "../../lib/util"; + +const DEBUG = false; + +export function ts2python(source: string): string { + const src = new LiteralSource(source, 'test.ts'); + + if (DEBUG) { + // tslint:disable-next-line:no-console + console.log(visualizeTypeScriptAst(src)); + } + const result = translateTypeScript(src, new PythonVisitor()); + + // Very debug. Much print. + // console.log(JSON.stringify(result.tree, undefined, 2)); + + return renderTree(result.tree) + '\n'; +} + +export function expectPython(source: string, expected: string) { + expect(stripEmptyLines(ts2python(source))).toEqual(stripEmptyLines(stripCommonWhitespace(expected))); +} + +function stripCommonWhitespace(x: string) { + const lines = x.split('\n'); + const whitespaces = lines.filter(l => !emptyLine(l.trim())).map(l => l.match(/(\s*)/)![1].length); + const minWS = Math.min(...whitespaces); + return lines.map(l => l.substr(minWS)).join('\n'); +} + +function stripEmptyLines(x: string) { + const lines = x.split('\n'); + while (lines.length > 0 && emptyLine(lines[0])) { lines.splice(0, 1); } + while (lines.length > 0 && emptyLine(lines[lines.length - 1])) { lines.pop(); } + return lines.join('\n'); +} + +function emptyLine(x: string) { + return x.trim() === ''; +} \ No newline at end of file diff --git a/packages/jsii-sampiler/test/python/statements.test.ts b/packages/jsii-sampiler/test/python/statements.test.ts new file mode 100644 index 0000000000..623791518d --- /dev/null +++ b/packages/jsii-sampiler/test/python/statements.test.ts @@ -0,0 +1,100 @@ +import { expectPython } from "./python"; + +test('if', () => { + expectPython(` + if (x == 3) { + console.log('bye'); + } + `, ` + if x == 3: + print("bye") + `); +}); + +test('if/then/else', () => { + expectPython(` + if (x == 3) { + console.log('bye'); + } else { + console.log('toodels'); + } + `, ` + if x == 3: + print("bye") + else: + print("toodels") + `); +}); + +test('multiline if/then/else', () => { + expectPython(` + if (x == 3) { + x += 1; + console.log('bye'); + } else { + console.log('toodels'); + } + `, ` + if x == 3: + x += 1 + print("bye") + else: + print("toodels") + `); +}); + +test('empty control block', () => { + expectPython(` + if (x == 3) { + } + `, ` + if x == 3: + pass + `); +}); + +test('block without braces', () => { + expectPython(` + if (x == 3) console.log('hello'); + `, ` + if x == 3: print("hello") + `); +}); + +test('for/of loop', () => { + expectPython(` + for (const x of xs) { + console.log(x); + } + `, ` + for x in xs: + print(x) + `); +}); + +test('whitespace between statements', () => { + expectPython(` + statementOne(); + + statementTwo(); + `, ` + statement_one() + + statement_two() + `); +}); + +test('whitespace between statements in a block', () => { + expectPython(` + if (condition) { + statementOne(); + + statementTwo(); + } + `, ` + if condition: + statement_one() + + statement_two() + `); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/tsconfig.json b/packages/jsii-sampiler/tsconfig.json new file mode 100644 index 0000000000..3dd58625bc --- /dev/null +++ b/packages/jsii-sampiler/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "commonjs", + "lib": ["es2016", "es2017.object", "es2017.string"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "strictPropertyInitialization": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "composite": true + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "examples" + ] +} diff --git a/packages/jsii-spec/package-lock.json b/packages/jsii-spec/package-lock.json index 9609bafbbc..7799a89806 100644 --- a/packages/jsii-spec/package-lock.json +++ b/packages/jsii-spec/package-lock.json @@ -3281,10 +3281,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", diff --git a/packages/jsii/lib/helpers.ts b/packages/jsii/lib/helpers.ts index ba49acb1c6..e062e25e0d 100644 --- a/packages/jsii/lib/helpers.ts +++ b/packages/jsii/lib/helpers.ts @@ -45,7 +45,7 @@ async function inTempDir(block: () => Promise): Promise { process.chdir(tmpDir); const ret = await block(); process.chdir(origDir); - // await fs.remove(tmpDir); + await fs.remove(tmpDir); return ret; } diff --git a/packages/jsii/package-lock.json b/packages/jsii/package-lock.json index 1e42f666ec..e566c93035 100644 --- a/packages/jsii/package-lock.json +++ b/packages/jsii/package-lock.json @@ -3263,18 +3263,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-spec": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.15.1.tgz", - "integrity": "sha512-6LZgwsj1jgvHDFYkTCcRI9PKMZ/fEPnQzGkXJbPMWTQGW0hlwmqLBZq0IinWMgKqd3IXBob120d9sGYxCpa9lA==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3316,11 +3304,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", diff --git a/packages/oo-ascii-tree/package-lock.json b/packages/oo-ascii-tree/package-lock.json index e50e526ee3..16b151d98a 100644 --- a/packages/oo-ascii-tree/package-lock.json +++ b/packages/oo-ascii-tree/package-lock.json @@ -3108,10 +3108,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", From b033ba00fbfd4d9dc029a38ea912dd936d754dd3 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 27 Sep 2019 17:41:59 +0200 Subject: [PATCH 2/8] Don't forget to add newline to disclaimer --- packages/jsii-sampiler/lib/languages/python.ts | 2 +- .../jsii-sampiler/test/python/statements.test.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/jsii-sampiler/lib/languages/python.ts b/packages/jsii-sampiler/lib/languages/python.ts index c67cecfaaa..4c871d3291 100644 --- a/packages/jsii-sampiler/lib/languages/python.ts +++ b/packages/jsii-sampiler/lib/languages/python.ts @@ -92,7 +92,7 @@ export class PythonVisitor extends DefaultVisitor { public sourceFile(node: ts.SourceFile, context: PythonVisitorContext): OTree { const rendered = super.sourceFile(node, context); if (this.options.disclaimer) { - return new OTree(['# ' + this.options.disclaimer, rendered]); + return new OTree(['# ' + this.options.disclaimer + '\n', rendered]); } return rendered; } diff --git a/packages/jsii-sampiler/test/python/statements.test.ts b/packages/jsii-sampiler/test/python/statements.test.ts index 623791518d..99d1b610bd 100644 --- a/packages/jsii-sampiler/test/python/statements.test.ts +++ b/packages/jsii-sampiler/test/python/statements.test.ts @@ -1,4 +1,5 @@ import { expectPython } from "./python"; +import { LiteralSource, PythonVisitor, translateTypeScript, renderTree } from "../../lib"; test('if', () => { expectPython(` @@ -97,4 +98,16 @@ test('whitespace between statements in a block', () => { statement_two() `); +}); + +test('prepend disclaimer', () => { + const src = new LiteralSource('console.log("hello");', 'test.ts'); + + const result = translateTypeScript(src, new PythonVisitor({ + disclaimer: 'Do not write this code' + })); + + expect(renderTree(result.tree)).toEqual( +`# Do not write this code +print("hello")`); }); \ No newline at end of file From a89944c67bf91a6d9e46a1b4aed220c4098c8920 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 1 Oct 2019 16:29:29 +0200 Subject: [PATCH 3/8] Make the CLI utility dispatch to different types of commands --- packages/jsii-build-tools/package-lock.json | 8 +- packages/jsii-sampiler/bin/jsii-sampiler | 2 + packages/jsii-sampiler/bin/jsii-sampiler.ts | 86 +++++++++++++++++++++ packages/jsii-sampiler/bin/jsii-snippet | 2 - packages/jsii-sampiler/bin/jsii-snippet.ts | 52 ------------- packages/jsii-sampiler/package-lock.json | 61 ++++++++++++--- packages/jsii-sampiler/package.json | 4 +- 7 files changed, 143 insertions(+), 72 deletions(-) create mode 100755 packages/jsii-sampiler/bin/jsii-sampiler create mode 100644 packages/jsii-sampiler/bin/jsii-sampiler.ts delete mode 100755 packages/jsii-sampiler/bin/jsii-snippet delete mode 100644 packages/jsii-sampiler/bin/jsii-snippet.ts diff --git a/packages/jsii-build-tools/package-lock.json b/packages/jsii-build-tools/package-lock.json index eee163e112..23a9a2a3eb 100644 --- a/packages/jsii-build-tools/package-lock.json +++ b/packages/jsii-build-tools/package-lock.json @@ -8,7 +8,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -18,14 +17,12 @@ "graceful-fs": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==", - "dev": true + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -33,8 +30,7 @@ "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" } } } diff --git a/packages/jsii-sampiler/bin/jsii-sampiler b/packages/jsii-sampiler/bin/jsii-sampiler new file mode 100755 index 0000000000..d778d67448 --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-sampiler @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./jsii-sampiler.js'); diff --git a/packages/jsii-sampiler/bin/jsii-sampiler.ts b/packages/jsii-sampiler/bin/jsii-sampiler.ts new file mode 100644 index 0000000000..7e57c7221d --- /dev/null +++ b/packages/jsii-sampiler/bin/jsii-sampiler.ts @@ -0,0 +1,86 @@ +import yargs = require('yargs'); +import { FileSource, isErrorDiagnostic, LiteralSource, printDiagnostics, + renderTree, translateMarkdown, TranslateResult, translateTypeScript } from '../lib'; +import { PythonVisitor } from '../lib/languages/python'; +import { VisualizeAstVisitor } from '../lib/languages/visualize'; + +async function main() { + const argv = yargs + .usage('$0 [args]') + .command('snippet [file]', 'Translate a single snippet', command => command + .positional('file', { type: 'string', describe: 'The file to translate (leave out for stdin)' }) + .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) + , async args => { + const result = translateTypeScript( + await makeFileSource(args.file || '-', 'stdin.ts'), + makeVisitor(args)); + renderResult(result); + }) + .command('markdown ', 'Translate a MarkDown file', command => command + .positional('file', { type: 'string', describe: 'The file to translate (leave out for stdin)' }) + .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) + , async args => { + const result = translateMarkdown( + await makeFileSource(args.file || '-', 'stdin.md'), + makeVisitor(args)); + renderResult(result); + return 5; + }) + .demandCommand() + .help() + .strict() // Error on wrong command + .version(require('../package.json').version) + .showHelpOnFail(false) + .argv; + + // Evaluating .argv triggers the parsing but the command gets implicitly executed, + // so we don't need the output. + Array.isArray(argv); +} + +function makeVisitor(args: { python?: boolean }) { + if (args.python) { return new PythonVisitor(); } + // Default to visualizing AST, including nodes we don't recognize yet + return new VisualizeAstVisitor(); +} + +async function makeFileSource(fileName: string, stdinName: string) { + if (fileName === '-') { + return new LiteralSource(await readStdin(), stdinName); + } + return new FileSource(fileName); +} + +async function readStdin(): Promise { + process.stdin.setEncoding('utf8'); + + const parts: string[] = []; + + return new Promise((resolve, reject) => { + process.stdin.on('readable', () => { + const chunk = process.stdin.read(); + if (chunk !== null) { parts.push(`${chunk}`); } + }); + + process.stdin.on('error', reject); + process.stdin.on('end', () => resolve(parts.join(''))); + }); +} + +function renderResult(result: TranslateResult) { + process.stdout.write(renderTree(result.tree) + '\n'); + + if (result.diagnostics.length > 0) { + printDiagnostics(result.diagnostics, process.stderr); + + if (result.diagnostics.some(isErrorDiagnostic)) { + process.exit(1); + } + } +} + +main().catch(e => { + // tslint:disable-next-line:no-console + console.error(e); + process.exit(1); +}); \ No newline at end of file diff --git a/packages/jsii-sampiler/bin/jsii-snippet b/packages/jsii-sampiler/bin/jsii-snippet deleted file mode 100755 index 407f7e294a..0000000000 --- a/packages/jsii-sampiler/bin/jsii-snippet +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('./jsii-snippet.js'); diff --git a/packages/jsii-sampiler/bin/jsii-snippet.ts b/packages/jsii-sampiler/bin/jsii-snippet.ts deleted file mode 100644 index ea521016b1..0000000000 --- a/packages/jsii-sampiler/bin/jsii-snippet.ts +++ /dev/null @@ -1,52 +0,0 @@ -import fs = require("fs"); -import yargs = require('yargs'); -import { FileSource, isErrorDiagnostic, LiteralSource, printDiagnostics, - renderTree, translateMarkdown, TranslateOptions, translateTypeScript } from '../lib'; -import { PythonVisitor } from '../lib/languages/python'; -import { VisualizeAstVisitor } from '../lib/languages/visualize'; - -async function main() { - const argv = yargs - .usage('$0 [file]') - .option('python', { alias: 'p', boolean: true, description: 'Translate snippets to Python' }) - .option('markdown', { alias: 'm', boolean: true, description: 'Parse input as MarkDown and translate snippets inside it' }) - .help() - .version(require('../package.json').version) - .argv; - - const options: TranslateOptions = {}; - - let visitor; - if (argv.python) { visitor = new PythonVisitor(); } - if (!visitor) { - // Default to visualizing AST, including nodes we don't recognize yet - visitor = new VisualizeAstVisitor(); - options.bestEffort = false; - } - - const fakeInputFileName = argv.markdown ? 'stdin.md' : 'stdin.ts'; - - const source = argv._.length > 0 - ? new FileSource(argv._[0]) - : new LiteralSource(fs.readFileSync(0, "utf-8"), fakeInputFileName); - - const result = argv.markdown - ? translateMarkdown(source, visitor, options) - : translateTypeScript(source, visitor, options); - - process.stdout.write(renderTree(result.tree) + '\n'); - - if (result.diagnostics.length > 0) { - printDiagnostics(result.diagnostics, process.stderr); - - if (result.diagnostics.some(isErrorDiagnostic)) { - process.exit(1); - } - } -} - -main().catch(e => { - // tslint:disable-next-line:no-console - console.error(e); - process.exit(1); -}); \ No newline at end of file diff --git a/packages/jsii-sampiler/package-lock.json b/packages/jsii-sampiler/package-lock.json index 14706618a0..0130f4fc8e 100644 --- a/packages/jsii-sampiler/package-lock.json +++ b/packages/jsii-sampiler/package-lock.json @@ -1,5 +1,5 @@ { - "name": "jsii-samples", + "name": "jsii-sampiler", "version": "0.16.0", "lockfileVersion": 1, "requires": true, @@ -494,18 +494,18 @@ "dev": true }, "@types/yargs": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.0.tgz", - "integrity": "sha512-hY0o+kcz9M6kH32NUeb6VURghqMuCVkiUx+8Btsqhj4Hhov/hVGUx9DmBJeIkzlp1uAQK4wngQBCjqWdUUkFyA==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", + "integrity": "sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", "dev": true }, "abab": { @@ -2689,6 +2689,26 @@ "prompts": "^2.0.1", "realpath-native": "^1.1.0", "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } } } } @@ -2979,6 +2999,26 @@ "slash": "^2.0.0", "strip-bom": "^3.0.0", "yargs": "^13.3.0" + }, + "dependencies": { + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } } }, "jest-serializer": { @@ -4888,11 +4928,12 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz", + "integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==", "requires": { "cliui": "^5.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", diff --git a/packages/jsii-sampiler/package.json b/packages/jsii-sampiler/package.json index b21481f984..067664b451 100644 --- a/packages/jsii-sampiler/package.json +++ b/packages/jsii-sampiler/package.json @@ -17,7 +17,7 @@ "@types/fs-extra": "^8.0.0", "@types/jest": "^24.0.18", "@types/node": "^12.6.8", - "@types/yargs": "^13.0.0", + "@types/yargs": "^13.0.3", "jest": "^24.9.0", "memory-streams": "^0.1.3", "typescript": "^3.5.3" @@ -26,7 +26,7 @@ "commonmark": "^0.29.0", "fs-extra": "^8.1.0", "typescript": "~3.6.2", - "yargs": "^13.3.0" + "yargs": "^14.0.0" }, "jest": { "moduleFileExtensions": [ From 1c0dd74f5aeda0c270e0597bc3627caeea50519b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 2 Oct 2019 10:45:17 +0200 Subject: [PATCH 4/8] Fix build --- packages/jsii-diff/package-lock.json | 4 ++++ .../jsii-dotnet-jsonmodel/package-lock.json | 4 ++++ .../package-lock.json | 8 +++++++ .../jsii-dotnet-runtime/package-lock.json | 7 ++++++ packages/jsii-java-runtime/package-lock.json | 4 ++++ packages/jsii-kernel/package-lock.json | 16 +++++++++++++ packages/jsii-pacmak/lib/targets/python.ts | 2 +- packages/jsii-pacmak/package-lock.json | 24 +++++++++++++++++++ .../expected.jsii-calc-base/python/README.md | 1 - .../expected.jsii-calc-lib/python/README.md | 1 - .../test/expected.jsii-calc/python/README.md | 8 +++---- .../python/src/jsii_calc/__init__.py | 5 ++-- packages/jsii-reflect/package-lock.json | 12 ++++++++++ packages/jsii-ruby-runtime/package-lock.json | 8 +++++++ packages/jsii-runtime/package-lock.json | 16 +++++++++++++ packages/jsii-spec/package-lock.json | 4 ++++ packages/jsii/package-lock.json | 4 ++++ packages/oo-ascii-tree/package-lock.json | 4 ++++ 18 files changed, 123 insertions(+), 9 deletions(-) diff --git a/packages/jsii-diff/package-lock.json b/packages/jsii-diff/package-lock.json index 57662100ae..a4fa916882 100644 --- a/packages/jsii-diff/package-lock.json +++ b/packages/jsii-diff/package-lock.json @@ -2183,6 +2183,10 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/jsii-dotnet-jsonmodel/package-lock.json b/packages/jsii-dotnet-jsonmodel/package-lock.json index fc48387ac4..aeb69a3d23 100644 --- a/packages/jsii-dotnet-jsonmodel/package-lock.json +++ b/packages/jsii-dotnet-jsonmodel/package-lock.json @@ -9,6 +9,10 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/jsii-dotnet-runtime-test/package-lock.json b/packages/jsii-dotnet-runtime-test/package-lock.json index 20846d9c3d..737ade7226 100644 --- a/packages/jsii-dotnet-runtime-test/package-lock.json +++ b/packages/jsii-dotnet-runtime-test/package-lock.json @@ -9,6 +9,14 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true + }, + "jsii-dotnet-runtime": { + "version": "file:../jsii-dotnet-runtime", + "dev": true } } } diff --git a/packages/jsii-dotnet-runtime/package-lock.json b/packages/jsii-dotnet-runtime/package-lock.json index 35de3d5c38..912736dcdb 100644 --- a/packages/jsii-dotnet-runtime/package-lock.json +++ b/packages/jsii-dotnet-runtime/package-lock.json @@ -9,6 +9,13 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true + }, + "jsii-dotnet-jsonmodel": { + "version": "file:../jsii-dotnet-jsonmodel" + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/jsii-java-runtime/package-lock.json b/packages/jsii-java-runtime/package-lock.json index 7185a24fd0..97d9d07206 100644 --- a/packages/jsii-java-runtime/package-lock.json +++ b/packages/jsii-java-runtime/package-lock.json @@ -9,6 +9,10 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/jsii-kernel/package-lock.json b/packages/jsii-kernel/package-lock.json index 4d5f3448ac..b12ba366cc 100644 --- a/packages/jsii-kernel/package-lock.json +++ b/packages/jsii-kernel/package-lock.json @@ -2393,6 +2393,22 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", "integrity": "sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==", "dev": true + }, + "@scope/jsii-calc-base": { + "version": "file:../jsii-calc-base", + "dev": true + }, + "@scope/jsii-calc-lib": { + "version": "file:../jsii-calc-lib", + "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true } } } diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 7351a9c6f3..967787b517 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -3,9 +3,9 @@ import path = require('path'); import { CodeMaker, toSnakeCase } from 'codemaker'; import * as escapeStringRegexp from 'escape-string-regexp'; import * as reflect from 'jsii-reflect'; +import * as sampiler from 'jsii-sampiler'; import * as spec from 'jsii-spec'; import { Stability } from 'jsii-spec'; -import * as sampiler from 'jsii-sampiler'; import { Generator, GeneratorOptions } from '../generator'; import { warn } from '../logging'; import { md2rst } from '../markdown'; diff --git a/packages/jsii-pacmak/package-lock.json b/packages/jsii-pacmak/package-lock.json index 86bd27f129..c0fde82f4c 100644 --- a/packages/jsii-pacmak/package-lock.json +++ b/packages/jsii-pacmak/package-lock.json @@ -2263,6 +2263,30 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "@scope/jsii-calc-lib": { + "version": "file:../jsii-calc-lib", + "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true + }, + "jsii-dotnet-jsonmodel": { + "version": "file:../jsii-dotnet-jsonmodel", + "dev": true + }, + "jsii-dotnet-runtime": { + "version": "file:../jsii-dotnet-runtime", + "dev": true + }, + "jsii-java-runtime": { + "version": "file:../jsii-java-runtime", + "dev": true } } } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md index 8b13789179..e69de29bb2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/README.md @@ -1 +0,0 @@ - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md index 8b13789179..e69de29bb2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/README.md @@ -1 +0,0 @@ - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md b/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md index a1643cddc6..e90486664b 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/README.md @@ -12,8 +12,8 @@ heading will be used as the Sphinx topic name. Otherwise, the name of the module ## Code Samples -```ts -/* This is totes a magic comment in here, just you wait! */ -const foo = 'bar'; +```python +# Example may have issues. See https://github.com/aws/jsii/issues/826 +# This is totes a magic comment in here, just you wait! +foo = "bar" ``` - diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py index 6b03d4e61f..d5fe83cc35 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py @@ -763,8 +763,9 @@ class ClassWithDocs(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.ClassWithDocs" :customAttribute:: hasAValue Example:: - function anExample() { - } + # Example may have issues. See https://github.com/aws/jsii/issues/826 + def an_example(): + pass """ def __init__(self) -> None: jsii.create(ClassWithDocs, self, []) diff --git a/packages/jsii-reflect/package-lock.json b/packages/jsii-reflect/package-lock.json index 7c7daa84d9..4ceac41f80 100644 --- a/packages/jsii-reflect/package-lock.json +++ b/packages/jsii-reflect/package-lock.json @@ -4920,6 +4920,18 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "@scope/jsii-calc-lib": { + "version": "file:../jsii-calc-lib", + "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true } } } diff --git a/packages/jsii-ruby-runtime/package-lock.json b/packages/jsii-ruby-runtime/package-lock.json index 15d04910a3..3b2d37724d 100644 --- a/packages/jsii-ruby-runtime/package-lock.json +++ b/packages/jsii-ruby-runtime/package-lock.json @@ -9,6 +9,14 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true } } } diff --git a/packages/jsii-runtime/package-lock.json b/packages/jsii-runtime/package-lock.json index 341b4d0f9c..fdcdcf5590 100644 --- a/packages/jsii-runtime/package-lock.json +++ b/packages/jsii-runtime/package-lock.json @@ -5680,6 +5680,22 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", "integrity": "sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==", "dev": true + }, + "@scope/jsii-calc-base": { + "version": "file:../jsii-calc-base", + "dev": true + }, + "@scope/jsii-calc-lib": { + "version": "file:../jsii-calc-lib", + "dev": true + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true + }, + "jsii-calc": { + "version": "file:../jsii-calc", + "dev": true } } } diff --git a/packages/jsii-spec/package-lock.json b/packages/jsii-spec/package-lock.json index 7799a89806..2b29d0f5f8 100644 --- a/packages/jsii-spec/package-lock.json +++ b/packages/jsii-spec/package-lock.json @@ -5047,6 +5047,10 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/jsii/package-lock.json b/packages/jsii/package-lock.json index e566c93035..f249d84467 100644 --- a/packages/jsii/package-lock.json +++ b/packages/jsii/package-lock.json @@ -5066,6 +5066,10 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } diff --git a/packages/oo-ascii-tree/package-lock.json b/packages/oo-ascii-tree/package-lock.json index 16b151d98a..9d17a1bdb9 100644 --- a/packages/oo-ascii-tree/package-lock.json +++ b/packages/oo-ascii-tree/package-lock.json @@ -4863,6 +4863,10 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "jsii-build-tools": { + "version": "file:../jsii-build-tools", + "dev": true } } } From 65782ad66b5306871bc1b8edf7b04fa09de28d96 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 2 Oct 2019 14:19:11 +0200 Subject: [PATCH 5/8] Fix build --- packages/jsii-pacmak/lib/targets/python.ts | 4 ++-- packages/jsii-pacmak/package.json | 1 + packages/jsii-sampiler/package.json | 10 ++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index ebd0639ff6..22343174a0 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -705,7 +705,7 @@ class Struct extends BasePythonClassType { private emitGetter(member: StructField, code: CodeMaker, resolver: TypeResolver) { code.line('@property'); code.openBlock(`def ${member.pythonName}(self) -> ${member.typeAnnotation(resolver)}`); - member.emitDocString(code, { documentableItem: `prop-${this.pythonName}` }); + member.emitDocString(code); code.line(`return self._values.get('${member.pythonName}')`); code.closeBlock(); } @@ -770,7 +770,7 @@ class StructField implements PythonBase { } public emitDocString(code: CodeMaker) { - emitDocString(code, this.docs); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); } public emit(code: CodeMaker, resolver: TypeResolver) { diff --git a/packages/jsii-pacmak/package.json b/packages/jsii-pacmak/package.json index 44fe5a1b21..66c3f750fc 100644 --- a/packages/jsii-pacmak/package.json +++ b/packages/jsii-pacmak/package.json @@ -40,6 +40,7 @@ "fs-extra": "^8.1.0", "jsii-reflect": "^0.18.0", "jsii-spec": "^0.18.0", + "jsii-sampiler": "^0.18.0", "spdx-license-list": "^6.1.0", "xmlbuilder": "^13.0.2", "yargs": "^14.0.0" diff --git a/packages/jsii-sampiler/package.json b/packages/jsii-sampiler/package.json index 067664b451..eb00fe262f 100644 --- a/packages/jsii-sampiler/package.json +++ b/packages/jsii-sampiler/package.json @@ -1,16 +1,14 @@ { "name": "jsii-sampiler", - "version": "0.16.0", + "version": "0.18.0", "description": "Translate TypeScript code snippets to other languages", "main": "lib/index.js", "bin": { - "jsii-samples": "bin/jsii-samples" + "jsii-sampiler": "bin/jsii-sampiler" }, "scripts": { "build": "tsc", - "test": "jest", - "demo": "npm run build && bin/jsii-samples examples/controlflow.ts", - "incomplete-demo": "npm run build && time node bin/jsii-samples examples/incomplete.ts" + "test": "jest" }, "devDependencies": { "@types/commonmark": "^0.27.4", @@ -42,6 +40,6 @@ "repository": { "type": "git", "url": "https://github.com/aws/jsii.git", - "directory": "packages/jsii-samples" + "directory": "packages/jsii-sampiler" } } From 0fd2e10fe5ece535e88fd1987a1b14deba66517c Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 2 Oct 2019 18:00:59 +0200 Subject: [PATCH 6/8] TS 3.6.3 requires slightly more strictness with intersection types apparently --- packages/jsii-diff/package-lock.json | 125 ------------------ packages/jsii-kernel/package-lock.json | 24 ---- packages/jsii-pacmak/package-lock.json | 64 --------- packages/jsii-reflect/package-lock.json | 117 ---------------- packages/jsii-runtime/package-lock.json | 76 +---------- packages/jsii-sampiler/lib/o-tree.ts | 2 +- .../jsii-sampiler/lib/typescript/ast-utils.ts | 2 +- packages/jsii-sampiler/package-lock.json | 2 +- packages/jsii-spec/package-lock.json | 4 - packages/jsii/package-lock.json | 12 -- packages/oo-ascii-tree/package-lock.json | 4 - 11 files changed, 5 insertions(+), 427 deletions(-) diff --git a/packages/jsii-diff/package-lock.json b/packages/jsii-diff/package-lock.json index cbea087382..8a3cd06c96 100644 --- a/packages/jsii-diff/package-lock.json +++ b/packages/jsii-diff/package-lock.json @@ -1244,11 +1244,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1391,20 +1386,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz", - "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1467,12 +1448,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -2967,12 +2942,6 @@ } } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3799,63 +3768,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.17.0.tgz", - "integrity": "sha512-gqmjiydYaKPalk1mnjszTkgQOIb2l8yGT3VNrd5cwf9FArNsqNBcYrkgGjbcR5Vn2X7imilBhISj/S0sBW54nQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.1.0", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "log4js": "^5.1.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "~3.6.3", - "yargs": "^14.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", - "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", - "dev": true - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-reflect": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.17.0.tgz", - "integrity": "sha512-xwImRGqSjQwPEun4isrCLerdoxKxk+Vs/lhPvatj9fSLpFw56xHZmkHBtwVl5o2jbBuQQGY3C/o6wBFNrlllgw==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "oo-ascii-tree": "^0.17.0", - "yargs": "^14.0.0" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4311,12 +4223,6 @@ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", "dev": true }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -4369,11 +4275,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4683,15 +4584,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -5116,17 +5008,6 @@ } } }, - "sort-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", - "integrity": "sha512-OgXPErPJM/rBK5OhzIJ+etib/BmLQ1JY55Nb/ElhoWUec62pXNF/X6DrecHq3NW5OAGX0KxYD7m0HtgB9dvGeA==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", - "minimist": "^1.2.0" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5202,12 +5083,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "spdx-license-list": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.1.0.tgz", - "integrity": "sha512-xiaE3KtBiylVmZrlux8tHR28HZgZ921HTXbx2fEZaDloRjbBOro79LeKttcQJ5MSDYFKG7in9v2GTAEhcR9/Qg==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/packages/jsii-kernel/package-lock.json b/packages/jsii-kernel/package-lock.json index 7a38ee1045..bc597fa3f1 100644 --- a/packages/jsii-kernel/package-lock.json +++ b/packages/jsii-kernel/package-lock.json @@ -391,14 +391,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -3606,22 +3598,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", diff --git a/packages/jsii-pacmak/package-lock.json b/packages/jsii-pacmak/package-lock.json index 5c1cf8b947..12812a0b44 100644 --- a/packages/jsii-pacmak/package-lock.json +++ b/packages/jsii-pacmak/package-lock.json @@ -359,10 +359,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -1111,16 +1107,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "codemaker": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/codemaker/-/codemaker-0.17.0.tgz", - "integrity": "sha512-cjLBnMB6o3P9/U1h+WAR/y3w3uVjKYeVo+TvhJtDBv8fhmGPe5t68cJ++6aXFyUWpOrbX9cAUyfMKVhXqERYPw==", - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "fs-extra": "^8.1.0" - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1144,11 +1130,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3617,46 +3598,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-dotnet-jsonmodel": { - "version": "file:../jsii-dotnet-jsonmodel", - "dev": true - }, - "jsii-dotnet-runtime": { - "version": "file:../jsii-dotnet-runtime", - "dev": true - }, - "jsii-java-runtime": { - "version": "file:../jsii-java-runtime", - "dev": true - }, - "jsii-reflect": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-0.17.0.tgz", - "integrity": "sha512-xwImRGqSjQwPEun4isrCLerdoxKxk+Vs/lhPvatj9fSLpFw56xHZmkHBtwVl5o2jbBuQQGY3C/o6wBFNrlllgw==", - "requires": { - "colors": "^1.3.3", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "oo-ascii-tree": "^0.17.0", - "yargs": "^14.0.0" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4179,11 +4120,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", diff --git a/packages/jsii-reflect/package-lock.json b/packages/jsii-reflect/package-lock.json index fe1aae3ae5..11fcb1f183 100644 --- a/packages/jsii-reflect/package-lock.json +++ b/packages/jsii-reflect/package-lock.json @@ -1251,20 +1251,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz", - "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -2799,12 +2785,6 @@ } } }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3636,49 +3616,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii/-/jsii-0.17.0.tgz", - "integrity": "sha512-gqmjiydYaKPalk1mnjszTkgQOIb2l8yGT3VNrd5cwf9FArNsqNBcYrkgGjbcR5Vn2X7imilBhISj/S0sBW54nQ==", - "dev": true, - "requires": { - "case": "^1.6.2", - "colors": "^1.3.3", - "deep-equal": "^1.1.0", - "fs-extra": "^8.1.0", - "jsii-spec": "^0.17.0", - "log4js": "^5.1.0", - "semver": "^6.3.0", - "sort-json": "^2.0.0", - "spdx-license-list": "^6.1.0", - "typescript": "~3.6.3", - "yargs": "^14.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3811,36 +3748,6 @@ "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", "dev": true }, - "log4js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-5.1.0.tgz", - "integrity": "sha512-QtXrBGZiIwfwBrH9zF2uQarvBuJ5+Icqx9fW+nQL4pnmPITJw8n6kh3bck5IkcTDBQatDeKqUMXXX41fp0TIqw==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4155,12 +4062,6 @@ } } }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -4213,11 +4114,6 @@ "mimic-fn": "^1.0.0" } }, - "oo-ascii-tree": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-0.17.0.tgz", - "integrity": "sha512-HgDeHCPtIkWl10uDp9fFk69lfb+iXjvVGXXYEpci+G+B2sg0uqMInccGsgGK306z1qGFe/Vxt4Mocas+OtQcLg==" - }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -4519,15 +4415,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -5617,10 +5504,6 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true } } } diff --git a/packages/jsii-runtime/package-lock.json b/packages/jsii-runtime/package-lock.json index 14e83dc8cf..41db634dbc 100644 --- a/packages/jsii-runtime/package-lock.json +++ b/packages/jsii-runtime/package-lock.json @@ -386,14 +386,6 @@ "@types/yargs": "^13.0.0" } }, - "@scope/jsii-calc-base": { - "version": "file:../jsii-calc-base", - "dev": true - }, - "@scope/jsii-calc-lib": { - "version": "file:../jsii-calc-lib", - "dev": true - }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -2678,14 +2670,6 @@ "readable-stream": "^2.0.0" } }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" - } - }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -4553,32 +4537,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-calc": { - "version": "file:../jsii-calc", - "dev": true - }, - "jsii-kernel": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-kernel/-/jsii-kernel-0.17.0.tgz", - "integrity": "sha512-NEm+th1s/p/n5v867G/btH+k5E6XcYFde5wWdvP4cOsMB7kO4//MGwebJ7KjCDw2RtnZ8k1YiCsWTVoRaDhUrg==", - "requires": { - "jsii-spec": "^0.17.0", - "source-map": "^0.7.3", - "tar": "^4.4.11" - } - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4928,23 +4886,6 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "minipass": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.8.6.tgz", - "integrity": "sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.2.tgz", - "integrity": "sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ==", - "requires": { - "minipass": "^2.2.1" - } - }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -6649,20 +6590,6 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "tar": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.12.tgz", - "integrity": "sha512-4GwpJwdSjIHlUrWd/1yJrl63UqcqjJyVglgIwn4gcG+Lrp9TXpZ1ZRrGLIRBNqLTUvz6yoPJrX4B/MISxY/Ukg==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, "terser": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.2.tgz", @@ -7407,7 +7334,8 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true }, "yargs": { "version": "13.2.4", diff --git a/packages/jsii-sampiler/lib/o-tree.ts b/packages/jsii-sampiler/lib/o-tree.ts index 4b2f763191..a81ae58be5 100644 --- a/packages/jsii-sampiler/lib/o-tree.ts +++ b/packages/jsii-sampiler/lib/o-tree.ts @@ -130,7 +130,7 @@ export class OTreeSink { return { get wroteNonWhitespaceSinceMark(): boolean { - return self.fragments.slice(markIndex).some(s => s.match(/[^\s]/)); + return self.fragments.slice(markIndex).some(s => !!s.match(/[^\s]/)); } }; } diff --git a/packages/jsii-sampiler/lib/typescript/ast-utils.ts b/packages/jsii-sampiler/lib/typescript/ast-utils.ts index 0d5b474e60..8f622e4029 100644 --- a/packages/jsii-sampiler/lib/typescript/ast-utils.ts +++ b/packages/jsii-sampiler/lib/typescript/ast-utils.ts @@ -62,7 +62,7 @@ export function nodeChildren(node: ts.Node): ts.Node[] { */ export function nodeOfType(syntaxKind: ts.SyntaxKind, children?: AstMatcher): AstMatcher; // tslint:disable-next-line:max-line-length -export function nodeOfType(capture: N, capturableNodeType: S, children?: AstMatcher): AstMatcher; +export function nodeOfType(capture: N, capturableNodeType: S, children?: AstMatcher): AstMatcher & {[key in N]: CapturableNodes[S]}>; // tslint:disable-next-line:max-line-length export function nodeOfType(syntaxKindOrCaptureName: ts.SyntaxKind | N, nodeTypeOrChildren?: S | AstMatcher, children?: AstMatcher): AstMatcher | AstMatcher { const capturing = typeof syntaxKindOrCaptureName === 'string'; // Determine which overload we're in (SyntaxKind is a number) diff --git a/packages/jsii-sampiler/package-lock.json b/packages/jsii-sampiler/package-lock.json index 0130f4fc8e..07a48d1e57 100644 --- a/packages/jsii-sampiler/package-lock.json +++ b/packages/jsii-sampiler/package-lock.json @@ -1,6 +1,6 @@ { "name": "jsii-sampiler", - "version": "0.16.0", + "version": "0.18.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/jsii-spec/package-lock.json b/packages/jsii-spec/package-lock.json index 84ddd0e90a..dc54a217cf 100644 --- a/packages/jsii-spec/package-lock.json +++ b/packages/jsii-spec/package-lock.json @@ -5657,10 +5657,6 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true } } } diff --git a/packages/jsii/package-lock.json b/packages/jsii/package-lock.json index 1f731255a8..dde3f3458a 100644 --- a/packages/jsii/package-lock.json +++ b/packages/jsii/package-lock.json @@ -3679,18 +3679,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true - }, - "jsii-spec": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/jsii-spec/-/jsii-spec-0.17.0.tgz", - "integrity": "sha512-ODzm1u4ETN0kZvC5b7OiVNwq2vPwCiBc5DkuFdT/EBD3DjHqRI7i6BFD0nz4+ig9UafS4pZ8br9djXQF4b72EQ==", - "requires": { - "jsonschema": "^1.2.4" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", diff --git a/packages/oo-ascii-tree/package-lock.json b/packages/oo-ascii-tree/package-lock.json index 6aad58e0fa..7cc5f28df6 100644 --- a/packages/oo-ascii-tree/package-lock.json +++ b/packages/oo-ascii-tree/package-lock.json @@ -5447,10 +5447,6 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "jsii-build-tools": { - "version": "file:../jsii-build-tools", - "dev": true } } } From 15274f27f8c2b8cfc4c052b3cdd0ee43d69671a2 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 2 Oct 2019 18:01:23 +0200 Subject: [PATCH 7/8] Remove zip implementation --- .../jsii-sampiler/lib/typescript/ast-utils.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/jsii-sampiler/lib/typescript/ast-utils.ts b/packages/jsii-sampiler/lib/typescript/ast-utils.ts index 8f622e4029..95cefee736 100644 --- a/packages/jsii-sampiler/lib/typescript/ast-utils.ts +++ b/packages/jsii-sampiler/lib/typescript/ast-utils.ts @@ -137,24 +137,6 @@ export function matchAst(node: ts.Node, matcher: AstMatcher, cb?: (binding return matched; } -/* -function zip(xs: Iterable, ys: Iterable): IterableIterator<[A, B | undefined]>; -function zip(xs: Iterable, ys: Iterable, defY: C): IterableIterator<[A, B | C]>; -function* zip(xs: Iterable, ys: Iterable, defY?: C): IterableIterator<[A, B | C]> { - const iterX = xs[Symbol.iterator](); - const iterY = ys[Symbol.iterator](); - - let x = iterX.next(); - let y = iterY.next(); - while (!x.done) { - yield [x.value, !y.done ? y.value : defY as any]; - - x = iterX.next(); - if (!y.done) { y = iterY.next(); } - } -} -*/ - /** * Count the newlines in a given piece of string that aren't in comment blocks */ From bfa4f5ac0723e75ad365d87d12ed9e6dd57b80de Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 2 Oct 2019 19:01:50 +0200 Subject: [PATCH 8/8] Properly merge Python against master --- packages/jsii-pacmak/lib/targets/python.ts | 3148 ++++++++++---------- 1 file changed, 1563 insertions(+), 1585 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 22343174a0..64c8d4542b 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -10,1917 +10,1895 @@ import { Generator, GeneratorOptions } from '../generator'; import { warn } from '../logging'; import { md2rst } from '../markdown'; import { propertySpec } from '../reflect-hacks'; -import { Target, TargetOptions } from '../target'; +import { Target } from '../target'; import { shell } from '../util'; export default class Python extends Target { - protected readonly generator = new PythonGenerator(); - - constructor(options: TargetOptions) { - super(options); - } - - public async build(sourceDir: string, outDir: string): Promise { - // Format our code to make it easier to read, we do this here instead of trying - // to do it in the code generation phase, because attempting to mix style and - // function makes the code generation harder to maintain and read, while doing - // this here is easy. - // await shell("black", ["--py36", sourceDir], {}); - - // Actually package up our code, both as a sdist and a wheel for publishing. - await shell("python3", ["setup.py", "sdist", "--dist-dir", outDir], { cwd: sourceDir }); - await shell("python3", ["setup.py", "bdist_wheel", "--dist-dir", outDir], { cwd: sourceDir }); - if (await twineIsPresent()) { - await shell("twine", ["check", path.join(outDir, '*')], { cwd: sourceDir }); - } else { - warn('Unable to validate distribution packages because `twine` is not present. ' + protected readonly generator = new PythonGenerator(); + + public async build(sourceDir: string, outDir: string): Promise { + // Format our code to make it easier to read, we do this here instead of trying + // to do it in the code generation phase, because attempting to mix style and + // function makes the code generation harder to maintain and read, while doing + // this here is easy. + // await shell("black", ["--py36", sourceDir], {}); + + // Actually package up our code, both as a sdist and a wheel for publishing. + await shell('python3', ['setup.py', 'sdist', '--dist-dir', outDir], { cwd: sourceDir }); + await shell('python3', ['setup.py', 'bdist_wheel', '--dist-dir', outDir], { cwd: sourceDir }); + if (await twineIsPresent()) { + await shell('twine', ['check', path.join(outDir, '*')], { cwd: sourceDir }); + } else { + warn('Unable to validate distribution packages because `twine` is not present. ' + 'Run `pip3 install twine` to enable distribution package validation.'); - } + } - // Approximating existence check using `pip3 show`. If that fails, assume twine is not there. - async function twineIsPresent(): Promise { - try { - const output = await shell("pip3", ["show", "twine"], { cwd: sourceDir }); - return output.trim() !== ''; - } catch { - return false; - } - } + // Approximating existence check using `pip3 show`. If that fails, assume twine is not there. + async function twineIsPresent(): Promise { + try { + const output = await shell('pip3', ['show', 'twine'], { cwd: sourceDir }); + return output.trim() !== ''; + } catch { + return false; + } } + } } // ################## // # CODE GENERATOR # // ################## -const PYTHON_BUILTIN_TYPES = ["bool", "str", "None"]; +const PYTHON_BUILTIN_TYPES = ['bool', 'str', 'None']; const PYTHON_KEYWORDS = [ - "False", "None", "True", "and", "as", "assert", "async", "await", "break", "class", - "continue", "def", "del", "elif", "else", "except", "finally", "for", "from", - "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", - "raise", "return", "try", "while", "with", "yield" + 'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', + 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', + 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', + 'raise', 'return', 'try', 'while', 'with', 'yield' ]; const pythonModuleNameToFilename = (name: string): string => { - return name.replace(/\./g, "/"); + return name.replace(/\./g, '/'); }; const toPythonIdentifier = (name: string): string => { - if (PYTHON_KEYWORDS.indexOf(name) > -1) { - return name + "_"; - } + if (PYTHON_KEYWORDS.includes(name)) { + return `${name}_`; + } - return name; + return name; }; -const toPythonMethodName = (name: string, protectedItem: boolean = false): string => { - let value = toPythonIdentifier(toSnakeCase(name)); - if (protectedItem) { - value = "_" + value; - } - return value; +const toPythonMethodName = (name: string, protectedItem = false): string => { + let value = toPythonIdentifier(toSnakeCase(name)); + if (protectedItem) { + value = `_${value}`; + } + return value; }; -const toPythonPropertyName = (name: string, constant: boolean = false, protectedItem: boolean = false): string => { - let value = toPythonIdentifier(toSnakeCase(name)); +const toPythonPropertyName = (name: string, constant = false, protectedItem = false): string => { + let value = toPythonIdentifier(toSnakeCase(name)); - if (constant) { - value = value.toUpperCase(); - } + if (constant) { + value = value.toUpperCase(); + } - if (protectedItem) { - value = "_" + value; - } + if (protectedItem) { + value = `_${value}`; + } - return value; + return value; }; const toPythonParameterName = (name: string): string => { - return toPythonIdentifier(toSnakeCase(name)); + return toPythonIdentifier(toSnakeCase(name)); }; const setDifference = (setA: Set, setB: Set): Set => { - const difference = new Set(setA); - for (const elem of setB) { - difference.delete(elem); - } - return difference; + const difference = new Set(setA); + for (const elem of setB) { + difference.delete(elem); + } + return difference; }; const sortMembers = (sortable: PythonBase[], resolver: TypeResolver): PythonBase[] => { - const sorted: PythonBase[] = []; - const seen: Set = new Set(); - - // We're going to take a copy of our sortable item, because it'll make it easier if - // this method doesn't have side effects. - sortable = sortable.slice(); - - // The first thing we want to do, is push any item which is not sortable to the very - // front of the list. This will be things like methods, properties, etc. - for (const item of sortable) { - if (!isSortableType(item)) { - sorted.push(item); - seen.add(item); - } - } - sortable = sortable.filter(i => !seen.has(i)); - - // Now that we've pulled out everything that couldn't possibly have dependencies, - // we will go through the remaining items, and pull off any items which have no - // dependencies that we haven't already sorted. - while (sortable.length > 0) { - for (const item of (sortable as Array)) { - const itemDeps: Set = new Set(item.dependsOn(resolver)); - if (setDifference(itemDeps, seen).size === 0) { - sorted.push(item); - seen.add(item); - - break; - } - } - - const leftover = sortable.filter(i => !seen.has(i)); - if (leftover.length === sortable.length) { - throw new Error("Could not sort members (circular dependency?)."); - } else { - sortable = leftover; - } - } - - return sorted; -}; - -const recurseForNamedTypeReferences = (typeRef: spec.TypeReference): spec.NamedTypeReference[] => { - if (spec.isPrimitiveTypeReference(typeRef)) { - return []; - } else if (spec.isCollectionTypeReference(typeRef)) { - return recurseForNamedTypeReferences(typeRef.collection.elementtype); - } else if (spec.isNamedTypeReference(typeRef)) { - return [typeRef]; - } else if (typeRef.union) { - const types: spec.NamedTypeReference[] = []; - for (const type of typeRef.union.types) { - types.push(...recurseForNamedTypeReferences(type)); - } - return types; + const sorted: PythonBase[] = []; + const seen: Set = new Set(); + + // We're going to take a copy of our sortable item, because it'll make it easier if + // this method doesn't have side effects. + sortable = sortable.slice(); + + // The first thing we want to do, is push any item which is not sortable to the very + // front of the list. This will be things like methods, properties, etc. + for (const item of sortable) { + if (!isSortableType(item)) { + sorted.push(item); + seen.add(item); + } + } + sortable = sortable.filter(i => !seen.has(i)); + + // Now that we've pulled out everything that couldn't possibly have dependencies, + // we will go through the remaining items, and pull off any items which have no + // dependencies that we haven't already sorted. + while (sortable.length > 0) { + for (const item of (sortable as Array)) { + const itemDeps: Set = new Set(item.dependsOn(resolver)); + if (setDifference(itemDeps, seen).size === 0) { + sorted.push(item); + seen.add(item); + + break; + } + } + + const leftover = sortable.filter(i => !seen.has(i)); + if (leftover.length === sortable.length) { + throw new Error('Could not sort members (circular dependency?).'); } else { - throw new Error("Invalid type reference: " + JSON.stringify(typeRef)); + sortable = leftover; } + } + + return sorted; }; interface PythonBase { - readonly pythonName: string; + readonly pythonName: string; - emit(code: CodeMaker, resolver: TypeResolver, opts?: any): void; + emit(code: CodeMaker, resolver: TypeResolver, opts?: any): void; } interface PythonType extends PythonBase { - // The JSII FQN for this item, if this item doesn't exist as a JSII type, then it - // doesn't have a FQN and it should be null; - readonly fqn: string | null; + // The JSII FQN for this item, if this item doesn't exist as a JSII type, then it + // doesn't have a FQN and it should be null; + readonly fqn: string | null; - addMember(member: PythonBase): void; + addMember(member: PythonBase): void; } interface ISortableType { - dependsOn(resolver: TypeResolver): PythonType[]; + dependsOn(resolver: TypeResolver): PythonType[]; } function isSortableType(arg: any): arg is ISortableType { - return arg.dependsOn !== undefined; + return arg.dependsOn !== undefined; } interface PythonTypeOpts { - bases?: spec.TypeReference[]; + bases?: spec.TypeReference[]; } abstract class BasePythonClassType implements PythonType, ISortableType { - protected bases: spec.TypeReference[]; - protected members: PythonBase[]; - - constructor( - protected readonly generator: PythonGenerator, - public readonly pythonName: string, - public readonly fqn: string | null, - opts: PythonTypeOpts, - protected readonly docs: spec.Docs | undefined) { - const { - bases = [], - } = opts; - - this.bases = bases; - this.members = []; - } - - public dependsOn(resolver: TypeResolver): PythonType[] { - const dependencies: PythonType[] = []; - const parent = resolver.getParent(this.fqn!); - - // We need to return any bases that are in the same module at the same level of - // nesting. - const seen: Set = new Set(); - for (const base of this.bases) { - if (spec.isNamedTypeReference(base)) { - if (resolver.isInModule(base)) { - // Given a base, we need to locate the base's parent that is the same as - // our parent, because we only care about dependencies that are at the - // same level of our own. - // TODO: We might need to recurse into our members to also find their - // dependencies. - let baseItem = resolver.getType(base); - let baseParent = resolver.getParent(base); - while (baseParent !== parent) { - baseItem = baseParent; - baseParent = resolver.getParent(baseItem.fqn!); - } - - if (!seen.has(baseItem.fqn!)) { - dependencies.push(baseItem); - seen.add(baseItem.fqn!); - } - } - } - } - - return dependencies; - } - - public addMember(member: PythonBase) { - this.members.push(member); + protected bases: spec.TypeReference[]; + protected members: PythonBase[]; + + public constructor( + protected readonly generator: PythonGenerator, + public readonly pythonName: string, + public readonly fqn: string | null, + opts: PythonTypeOpts, + protected readonly docs: spec.Docs | undefined) { + const { + bases = [], + } = opts; + + this.bases = bases; + this.members = []; + } + + public dependsOn(resolver: TypeResolver): PythonType[] { + const dependencies: PythonType[] = []; + const parent = resolver.getParent(this.fqn!); + + // We need to return any bases that are in the same module at the same level of + // nesting. + const seen: Set = new Set(); + for (const base of this.bases) { + if (spec.isNamedTypeReference(base)) { + if (resolver.isInModule(base)) { + // Given a base, we need to locate the base's parent that is the same as + // our parent, because we only care about dependencies that are at the + // same level of our own. + // TODO: We might need to recurse into our members to also find their + // dependencies. + let baseItem = resolver.getType(base); + let baseParent = resolver.getParent(base); + while (baseParent !== parent) { + baseItem = baseParent; + baseParent = resolver.getParent(baseItem.fqn!); + } + + if (!seen.has(baseItem.fqn!)) { + dependencies.push(baseItem); + seen.add(baseItem.fqn!); + } + } + } + } + + return dependencies; + } + + public addMember(member: PythonBase) { + this.members.push(member); + } + + public emit(code: CodeMaker, resolver: TypeResolver) { + const classParams = this.getClassParams(resolver); + const bases = classParams.length > 0 ? `(${classParams.join(', ')})` : ''; + + code.openBlock(`class ${this.pythonName}${bases}`); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); + + this.emitPreamble(code, resolver); + + if (this.members.length > 0) { + resolver = this.fqn ? resolver.bind(this.fqn) : resolver; + for (const member of sortMembers(this.members, resolver)) { + member.emit(code, resolver); + } + } else { + code.line('pass'); } - public emit(code: CodeMaker, resolver: TypeResolver) { - const classParams = this.getClassParams(resolver); - const bases = classParams.length > 0 ? `(${classParams.join(", ")})` : ""; + code.closeBlock(); + } - code.openBlock(`class ${this.pythonName}${bases}`); - emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); + protected abstract getClassParams(resolver: TypeResolver): string[]; - this.emitPreamble(code, resolver); - - if (this.members.length > 0) { - resolver = this.fqn ? resolver.bind(this.fqn) : resolver; - for (const member of sortMembers(this.members, resolver)) { - member.emit(code, resolver); - } - } else { - code.line("pass"); - } - - code.closeBlock(); - } - - protected abstract getClassParams(resolver: TypeResolver): string[]; - - protected emitPreamble(_code: CodeMaker, _resolver: TypeResolver) { return; } + protected emitPreamble(_code: CodeMaker, _resolver: TypeResolver) { return; } } interface BaseMethodOpts { - abstract?: boolean; - liftedProp?: spec.InterfaceType, - parent?: spec.NamedTypeReference, + abstract?: boolean; + liftedProp?: spec.InterfaceType; + parent?: spec.NamedTypeReference; } interface BaseMethodEmitOpts { - renderAbstract?: boolean; - forceEmitBody?: boolean; + renderAbstract?: boolean; + forceEmitBody?: boolean; } abstract class BaseMethod implements PythonBase { - public readonly abstract: boolean; - - protected readonly abstract implicitParameter: string; - protected readonly jsiiMethod: string; - protected readonly decorator?: string; - protected readonly classAsFirstParameter: boolean = false; - protected readonly returnFromJSIIMethod: boolean = true; - protected readonly shouldEmitBody: boolean = true; - - private readonly liftedProp?: spec.InterfaceType; - private readonly parent?: spec.NamedTypeReference; - - constructor(protected readonly generator: PythonGenerator, - public readonly pythonName: string, - private readonly jsName: string | undefined, - private readonly parameters: spec.Parameter[], - private readonly returns?: spec.OptionalValue, - private readonly docs?: spec.Docs, - opts: BaseMethodOpts = {}) { - this.abstract = !!opts.abstract; - this.liftedProp = opts.liftedProp; - this.parent = opts.parent; - } - - public emit(code: CodeMaker, resolver: TypeResolver, opts?: BaseMethodEmitOpts) { - const { renderAbstract = true, forceEmitBody = false } = opts || {}; - - let returnType: string; - if (this.returns !== undefined) { - returnType = resolver.resolve(this.returns, { forwardReferences: false }); - } else { - returnType = "None"; - } + public readonly abstract: boolean; + + protected readonly abstract implicitParameter: string; + protected readonly jsiiMethod: string; + protected readonly decorator?: string; + protected readonly classAsFirstParameter: boolean = false; + protected readonly returnFromJSIIMethod: boolean = true; + protected readonly shouldEmitBody: boolean = true; + + private readonly liftedProp?: spec.InterfaceType; + private readonly parent?: spec.NamedTypeReference; + + public constructor(protected readonly generator: PythonGenerator, + public readonly pythonName: string, + private readonly jsName: string | undefined, + private readonly parameters: spec.Parameter[], + private readonly returns?: spec.OptionalValue, + private readonly docs?: spec.Docs, + opts: BaseMethodOpts = {}) { + this.abstract = !!opts.abstract; + this.liftedProp = opts.liftedProp; + this.parent = opts.parent; + } + + public emit(code: CodeMaker, resolver: TypeResolver, opts?: BaseMethodEmitOpts) { + const { renderAbstract = true, forceEmitBody = false } = opts || {}; + + let returnType: string; + if (this.returns !== undefined) { + returnType = resolver.resolve(this.returns, { forwardReferences: false }); + } else { + returnType = 'None'; + } - // We cannot (currently?) blindly use the names given to us by the JSII for - // initializers, because our keyword lifting will allow two names to clash. - // This can hopefully be removed once we get https://github.com/aws/jsii/issues/288 - // resolved, so build up a list of all of the prop names so we can check against - // them later. - const liftedPropNames: Set = new Set(); - if (this.liftedProp !== undefined + // We cannot (currently?) blindly use the names given to us by the JSII for + // initializers, because our keyword lifting will allow two names to clash. + // This can hopefully be removed once we get https://github.com/aws/jsii/issues/288 + // resolved, so build up a list of all of the prop names so we can check against + // them later. + const liftedPropNames: Set = new Set(); + if (this.liftedProp !== undefined && this.liftedProp.properties !== undefined && this.liftedProp.properties.length >= 1) { - for (const prop of this.liftedProp.properties) { - liftedPropNames.add(toPythonParameterName(prop.name)); - } - } + for (const prop of this.liftedProp.properties) { + liftedPropNames.add(toPythonParameterName(prop.name)); + } + } - // We need to turn a list of JSII parameters, into Python style arguments with - // gradual typing, so we'll have to iterate over the list of parameters, and - // build the list, converting as we go. - const pythonParams: string[] = [this.implicitParameter]; - for (const param of this.parameters) { - // We cannot (currently?) blindly use the names given to us by the JSII for - // initializers, because our keyword lifting will allow two names to clash. - // This can hopefully be removed once we get https://github.com/aws/jsii/issues/288 - // resolved. - let paramName: string = toPythonParameterName(param.name); - while (liftedPropNames.has(paramName)) { - paramName = `${paramName}_`; - } - - const paramType = resolver.resolve(param, { forwardReferences: false}); - const paramDefault = param.optional ? "=None" : ""; - - pythonParams.push(`${paramName}: ${paramType}${paramDefault}`); - } + // We need to turn a list of JSII parameters, into Python style arguments with + // gradual typing, so we'll have to iterate over the list of parameters, and + // build the list, converting as we go. + const pythonParams: string[] = [this.implicitParameter]; + for (const param of this.parameters) { + // We cannot (currently?) blindly use the names given to us by the JSII for + // initializers, because our keyword lifting will allow two names to clash. + // This can hopefully be removed once we get https://github.com/aws/jsii/issues/288 + // resolved. + let paramName: string = toPythonParameterName(param.name); + while (liftedPropNames.has(paramName)) { + paramName = `${paramName}_`; + } - const documentableArgs = [...this.parameters]; - - // If we have a lifted parameter, then we'll drop the last argument to our params - // and then we'll lift all of the params of the lifted type as keyword arguments - // to the function. - if (this.liftedProp !== undefined) { - // Remove our last item. - pythonParams.pop(); - const liftedProperties = this.getLiftedProperties(resolver); - - if (liftedProperties.length >= 1) { - // All of these parameters are keyword only arguments, so we'll mark them - // as such. - pythonParams.push("*"); - - // Iterate over all of our props, and reflect them into our params. - for (const prop of liftedProperties) { - const paramName = toPythonParameterName(prop.name); - const paramType = resolver.resolve(prop, { forwardReferences: false }); - const paramDefault = prop.optional ? "=None" : ""; - - pythonParams.push(`${paramName}: ${paramType}${paramDefault}`); - } - } - - // Document them as keyword arguments - documentableArgs.push(...liftedProperties); - } else if (this.parameters.length >= 1 && this.parameters[this.parameters.length - 1].variadic) { - // Another situation we could be in, is that instead of having a plain parameter - // we have a variadic parameter where we need to expand the last parameter as a - // *args. - pythonParams.pop(); - - const lastParameter = this.parameters.slice(-1)[0]; - const paramName = toPythonParameterName(lastParameter.name); - const paramType = resolver.resolve( - lastParameter, - { forwardReferences: false, ignoreOptional: true }, - ); - - pythonParams.push(`*${paramName}: ${paramType}`); - } + const paramType = resolver.resolve(param, { forwardReferences: false }); + const paramDefault = param.optional ? '=None' : ''; - if (this.jsName !== undefined) { - code.line(`@jsii.member(jsii_name="${this.jsName}")`); - } + pythonParams.push(`${paramName}: ${paramType}${paramDefault}`); + } - if (this.decorator !== undefined) { - code.line(`@${this.decorator}`); - } + const documentableArgs = [...this.parameters]; + + // If we have a lifted parameter, then we'll drop the last argument to our params + // and then we'll lift all of the params of the lifted type as keyword arguments + // to the function. + if (this.liftedProp !== undefined) { + // Remove our last item. + pythonParams.pop(); + const liftedProperties = this.getLiftedProperties(resolver); + + if (liftedProperties.length >= 1) { + // All of these parameters are keyword only arguments, so we'll mark them + // as such. + pythonParams.push('*'); + + // Iterate over all of our props, and reflect them into our params. + for (const prop of liftedProperties) { + const paramName = toPythonParameterName(prop.name); + const paramType = resolver.resolve(prop, { forwardReferences: false }); + const paramDefault = prop.optional ? '=None' : ''; - if (renderAbstract && this.abstract) { - code.line("@abc.abstractmethod"); + pythonParams.push(`${paramName}: ${paramType}${paramDefault}`); } + } - code.openBlock(`def ${this.pythonName}(${pythonParams.join(", ")}) -> ${returnType}`); - emitDocString(code, this.docs, { arguments: documentableArgs, documentableItem: `method-${this.pythonName}`}); - this.emitBody(code, resolver, renderAbstract, forceEmitBody); - code.closeBlock(); + // Document them as keyword arguments + documentableArgs.push(...liftedProperties); + } else if (this.parameters.length >= 1 && this.parameters[this.parameters.length - 1].variadic) { + // Another situation we could be in, is that instead of having a plain parameter + // we have a variadic parameter where we need to expand the last parameter as a + // *args. + pythonParams.pop(); + + const lastParameter = this.parameters.slice(-1)[0]; + const paramName = toPythonParameterName(lastParameter.name); + const paramType = resolver.resolve( + lastParameter, + { forwardReferences: false, ignoreOptional: true }, + ); + + pythonParams.push(`*${paramName}: ${paramType}`); } - private emitBody(code: CodeMaker, resolver: TypeResolver, renderAbstract: boolean, forceEmitBody: boolean) { - if ((!this.shouldEmitBody && !forceEmitBody) || (renderAbstract && this.abstract)) { - code.line("..."); - } else { - if (this.liftedProp !== undefined) { - this.emitAutoProps(code, resolver); - } + if (this.jsName !== undefined) { + code.line(`@jsii.member(jsii_name="${this.jsName}")`); + } - this.emitJsiiMethodCall(code, resolver); - } + if (this.decorator !== undefined) { + code.line(`@${this.decorator}`); } - private emitAutoProps(code: CodeMaker, resolver: TypeResolver) { - const lastParameter = this.parameters.slice(-1)[0]; - const argName = toPythonParameterName(lastParameter.name); - const typeName = resolver.resolve(lastParameter, {ignoreOptional: true }); + if (renderAbstract && this.abstract) { + code.line('@abc.abstractmethod'); + } - // We need to build up a list of properties, which are mandatory, these are the - // ones we will specifiy to start with in our dictionary literal. - const liftedProps = this.getLiftedProperties(resolver).map(p => new StructField(p)); - const assignments = liftedProps - .map(p => p.pythonName) - .map(v => `${v}=${v}`); + code.openBlock(`def ${this.pythonName}(${pythonParams.join(', ')}) -> ${returnType}`); + emitDocString(code, this.docs, { arguments: documentableArgs, documentableItem: `method-${this.pythonName}` }); + this.emitBody(code, resolver, renderAbstract, forceEmitBody); + code.closeBlock(); + } - code.line(`${argName} = ${typeName}(${assignments.join(', ')})`); - code.line(); + private emitBody(code: CodeMaker, resolver: TypeResolver, renderAbstract: boolean, forceEmitBody: boolean) { + if ((!this.shouldEmitBody && !forceEmitBody) || (renderAbstract && this.abstract)) { + code.line('...'); + } else { + if (this.liftedProp !== undefined) { + this.emitAutoProps(code, resolver); + } + + this.emitJsiiMethodCall(code, resolver); } + } - private emitJsiiMethodCall(code: CodeMaker, resolver: TypeResolver) { - const methodPrefix: string = this.returnFromJSIIMethod ? "return " : ""; + private emitAutoProps(code: CodeMaker, resolver: TypeResolver) { + const lastParameter = this.parameters.slice(-1)[0]; + const argName = toPythonParameterName(lastParameter.name); + const typeName = resolver.resolve(lastParameter, { ignoreOptional: true }); - const jsiiMethodParams: string[] = []; - if (this.classAsFirstParameter) { - if (this.parent === undefined) { - throw new Error("Parent not known."); - } - jsiiMethodParams.push(resolver.resolve({ type: this.parent })); - } - jsiiMethodParams.push(this.implicitParameter); - if (this.jsName !== undefined) { - jsiiMethodParams.push(`"${this.jsName}"`); - } + // We need to build up a list of properties, which are mandatory, these are the + // ones we will specifiy to start with in our dictionary literal. + const liftedProps = this.getLiftedProperties(resolver).map(p => new StructField(p)); + const assignments = liftedProps + .map(p => p.pythonName) + .map(v => `${v}=${v}`); - // If the last arg is variadic, expand the tuple - const params: string[] = []; - for (const param of this.parameters) { - let expr = toPythonParameterName(param.name); - if (param.variadic) { expr = `*${expr}`; } - params.push(expr); - } + code.line(`${argName} = ${typeName}(${assignments.join(', ')})`); + code.line(); + } + + private emitJsiiMethodCall(code: CodeMaker, resolver: TypeResolver) { + const methodPrefix: string = this.returnFromJSIIMethod ? 'return ' : ''; - code.line(`${methodPrefix}jsii.${this.jsiiMethod}(${jsiiMethodParams.join(", ")}, [${params.join(", ")}])`); + const jsiiMethodParams: string[] = []; + if (this.classAsFirstParameter) { + if (this.parent === undefined) { + throw new Error('Parent not known.'); + } + jsiiMethodParams.push(resolver.resolve({ type: this.parent })); + } + jsiiMethodParams.push(this.implicitParameter); + if (this.jsName !== undefined) { + jsiiMethodParams.push(`"${this.jsName}"`); } - private getLiftedProperties(resolver: TypeResolver): spec.Property[] { - const liftedProperties: spec.Property[] = []; + // If the last arg is variadic, expand the tuple + const params: string[] = []; + for (const param of this.parameters) { + let expr = toPythonParameterName(param.name); + if (param.variadic) { expr = `*${expr}`; } + params.push(expr); + } - const stack = [this.liftedProp]; - let current = stack.shift(); - while (current !== undefined) { - // Add any interfaces that this interface depends on, to the list. - if (current.interfaces !== undefined) { - stack.push(...current.interfaces.map(ifc => resolver.dereference(ifc) as spec.InterfaceType)); - } + code.line(`${methodPrefix}jsii.${this.jsiiMethod}(${jsiiMethodParams.join(', ')}, [${params.join(', ')}])`); + } - // Add all of the properties of this interface to our list of properties. - if (current.properties !== undefined) { - liftedProperties.push(...current.properties); - } + private getLiftedProperties(resolver: TypeResolver): spec.Property[] { + const liftedProperties: spec.Property[] = []; - // Finally, grab our next item. - current = stack.shift(); - } + const stack = [this.liftedProp]; + let current = stack.shift(); + while (current !== undefined) { + // Add any interfaces that this interface depends on, to the list. + if (current.interfaces !== undefined) { + stack.push(...current.interfaces.map(ifc => resolver.dereference(ifc) as spec.InterfaceType)); + } + + // Add all of the properties of this interface to our list of properties. + if (current.properties !== undefined) { + liftedProperties.push(...current.properties); + } - return liftedProperties; + // Finally, grab our next item. + current = stack.shift(); } + + return liftedProperties; + } } interface BasePropertyOpts { - abstract?: boolean; - immutable?: boolean; + abstract?: boolean; + immutable?: boolean; } interface BasePropertyEmitOpts { - renderAbstract?: boolean; - forceEmitBody?: boolean; + renderAbstract?: boolean; + forceEmitBody?: boolean; } abstract class BaseProperty implements PythonBase { - public readonly abstract: boolean; - - protected readonly abstract decorator: string; - protected readonly abstract implicitParameter: string; - protected readonly jsiiGetMethod: string; - protected readonly jsiiSetMethod: string; - protected readonly shouldEmitBody: boolean = true; - - private readonly immutable: boolean; - - constructor(public readonly pythonName: string, - private readonly jsName: string, - private readonly type: spec.OptionalValue, - private readonly docs: spec.Docs | undefined, - opts: BasePropertyOpts = {}) { - const { - abstract = false, - immutable = false, - } = opts; - - this.abstract = abstract; - this.immutable = immutable; - } - - public emit(code: CodeMaker, resolver: TypeResolver, opts?: BasePropertyEmitOpts) { - const { renderAbstract = true, forceEmitBody = false } = opts || {}; - const pythonType = resolver.resolve(this.type, { forwardReferences: false }); - - code.line(`@${this.decorator}`); - code.line(`@jsii.member(jsii_name="${this.jsName}")`); - if (renderAbstract && this.abstract) { - code.line("@abc.abstractmethod"); - } - code.openBlock(`def ${this.pythonName}(${this.implicitParameter}) -> ${pythonType}`); - emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); - if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { - code.line(`return jsii.${this.jsiiGetMethod}(${this.implicitParameter}, "${this.jsName}")`); - } else { - code.line("..."); - } - code.closeBlock(); - - if (!this.immutable) { - code.line(`@${this.pythonName}.setter`); - if (renderAbstract && this.abstract) { - code.line("@abc.abstractmethod"); - } - code.openBlock(`def ${this.pythonName}(${this.implicitParameter}, value: ${pythonType})`); - if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { - code.line(`return jsii.${this.jsiiSetMethod}(${this.implicitParameter}, "${this.jsName}", value)`); - } else { - code.line("..."); - } - code.closeBlock(); - } - } + public readonly abstract: boolean; + + protected readonly abstract decorator: string; + protected readonly abstract implicitParameter: string; + protected readonly jsiiGetMethod: string; + protected readonly jsiiSetMethod: string; + protected readonly shouldEmitBody: boolean = true; + + private readonly immutable: boolean; + + public constructor(public readonly pythonName: string, + private readonly jsName: string, + private readonly type: spec.OptionalValue, + private readonly docs: spec.Docs | undefined, + opts: BasePropertyOpts = {}) { + const { + abstract = false, + immutable = false, + } = opts; + + this.abstract = abstract; + this.immutable = immutable; + } + + public emit(code: CodeMaker, resolver: TypeResolver, opts?: BasePropertyEmitOpts) { + const { renderAbstract = true, forceEmitBody = false } = opts || {}; + const pythonType = resolver.resolve(this.type, { forwardReferences: false }); + + code.line(`@${this.decorator}`); + code.line(`@jsii.member(jsii_name="${this.jsName}")`); + if (renderAbstract && this.abstract) { + code.line('@abc.abstractmethod'); + } + code.openBlock(`def ${this.pythonName}(${this.implicitParameter}) -> ${pythonType}`); + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); + if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { + code.line(`return jsii.${this.jsiiGetMethod}(${this.implicitParameter}, "${this.jsName}")`); + } else { + code.line('...'); + } + code.closeBlock(); + + if (!this.immutable) { + code.line(`@${this.pythonName}.setter`); + if (renderAbstract && this.abstract) { + code.line('@abc.abstractmethod'); + } + code.openBlock(`def ${this.pythonName}(${this.implicitParameter}, value: ${pythonType})`); + if ((this.shouldEmitBody || forceEmitBody) && (!renderAbstract || !this.abstract)) { + code.line(`return jsii.${this.jsiiSetMethod}(${this.implicitParameter}, "${this.jsName}", value)`); + } else { + code.line('...'); + } + code.closeBlock(); + } + } } class Interface extends BasePythonClassType { - public emit(code: CodeMaker, resolver: TypeResolver) { - code.line(`@jsii.interface(jsii_type="${this.fqn}")`); + public emit(code: CodeMaker, resolver: TypeResolver) { + code.line(`@jsii.interface(jsii_type="${this.fqn}")`); - // First we do our normal class logic for emitting our members. - super.emit(code, resolver); + // First we do our normal class logic for emitting our members. + super.emit(code, resolver); - // Then, we have to emit a Proxy class which implements our proxy interface. - resolver = this.fqn ? resolver.bind(this.fqn) : resolver; - const proxyBases: string[] = this.bases.map(b => `jsii.proxy_for(${resolver.resolve({ type: b })})`); - code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(", ")})`); - emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); - code.line(`__jsii_type__ = "${this.fqn}"`); + // Then, we have to emit a Proxy class which implements our proxy interface. + resolver = this.fqn ? resolver.bind(this.fqn) : resolver; + const proxyBases: string[] = this.bases.map(b => `jsii.proxy_for(${resolver.resolve({ type: b })})`); + code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(', ')})`); + emitDocString(code, this.docs, { documentableItem: `class-${this.pythonName}` }); + code.line(`__jsii_type__ = "${this.fqn}"`); - if (this.members.length > 0) { - for (const member of this.members) { - member.emit(code, resolver, { forceEmitBody: true }); - } - } else { - code.line("pass"); - } - - code.closeBlock(); + if (this.members.length > 0) { + for (const member of this.members) { + member.emit(code, resolver, { forceEmitBody: true }); + } + } else { + code.line('pass'); } - protected getClassParams(resolver: TypeResolver): string[] { - const params: string[] = this.bases.map(b => resolver.resolve({ type: b })); + code.closeBlock(); + } - params.push("jsii.compat.Protocol"); + protected getClassParams(resolver: TypeResolver): string[] { + const params: string[] = this.bases.map(b => resolver.resolve({ type: b })); - return params; - } + params.push('jsii.compat.Protocol'); - protected emitPreamble(code: CodeMaker, _resolver: TypeResolver) { - code.line("@staticmethod"); - code.openBlock("def __jsii_proxy_class__()"); - code.line(`return ${this.getProxyClassName()}`); - code.closeBlock(); - } + return params; + } - private getProxyClassName(): string { - return `_${this.pythonName}Proxy`; - } + protected emitPreamble(code: CodeMaker, _resolver: TypeResolver) { + code.line('@staticmethod'); + code.openBlock('def __jsii_proxy_class__()'); + code.line(`return ${this.getProxyClassName()}`); + code.closeBlock(); + } + + private getProxyClassName(): string { + return `_${this.pythonName}Proxy`; + } } class InterfaceMethod extends BaseMethod { - protected readonly implicitParameter: string = "self"; - protected readonly jsiiMethod: string = "invoke"; - protected readonly shouldEmitBody: boolean = false; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiMethod: string = 'invoke'; + protected readonly shouldEmitBody: boolean = false; } class InterfaceProperty extends BaseProperty { - protected readonly decorator: string = "property"; - protected readonly implicitParameter: string = "self"; - protected readonly jsiiGetMethod: string = "get"; - protected readonly jsiiSetMethod: string = "set"; - protected readonly shouldEmitBody: boolean = false; + protected readonly decorator: string = 'property'; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiGetMethod: string = 'get'; + protected readonly jsiiSetMethod: string = 'set'; + protected readonly shouldEmitBody: boolean = false; } class Struct extends BasePythonClassType { - protected directMembers = new Array(); + protected directMembers = new Array(); - public addMember(member: PythonBase): void { - if (!(member instanceof StructField)) { - throw new Error('Must add StructField to Struct'); - } - this.directMembers.push(member); + public addMember(member: PythonBase): void { + if (!(member instanceof StructField)) { + throw new Error('Must add StructField to Struct'); } + this.directMembers.push(member); + } - public emit(code: CodeMaker, resolver: TypeResolver) { - resolver = this.fqn ? resolver.bind(this.fqn) : resolver; + public emit(code: CodeMaker, resolver: TypeResolver) { + resolver = this.fqn ? resolver.bind(this.fqn) : resolver; - const baseInterfaces = this.getClassParams(resolver); + const baseInterfaces = this.getClassParams(resolver); - code.line(`@jsii.data_type(jsii_type="${this.fqn}", jsii_struct_bases=[${baseInterfaces.join(', ')}], name_mapping=${this.propertyMap()})`); - code.openBlock(`class ${this.pythonName}(${baseInterfaces.join(', ')})`); - this.emitConstructor(code, resolver); + code.line(`@jsii.data_type(jsii_type="${this.fqn}", jsii_struct_bases=[${baseInterfaces.join(', ')}], name_mapping=${this.propertyMap()})`); + code.openBlock(`class ${this.pythonName}(${baseInterfaces.join(', ')})`); + this.emitConstructor(code, resolver); - for (const member of this.allMembers) { - this.emitGetter(member, code, resolver); - } + for (const member of this.allMembers) { + this.emitGetter(member, code, resolver); + } - this.emitMagicMethods(code); + this.emitMagicMethods(code); - code.closeBlock(); - } + code.closeBlock(); + } - protected getClassParams(resolver: TypeResolver): string[] { - return this.bases.map(b => resolver.resolve({ type: b })); - } + protected getClassParams(resolver: TypeResolver): string[] { + return this.bases.map(b => resolver.resolve({ type: b })); + } - /** + /** * Find all fields (inherited as well) */ - private get allMembers(): StructField[] { - return this.thisInterface.allProperties.map(x => new StructField(propertySpec(x))); - } + private get allMembers(): StructField[] { + return this.thisInterface.allProperties.map(x => new StructField(propertySpec(x))); + } - private get thisInterface() { - if (this.fqn === null) { throw new Error('FQN not set'); } - return this.generator.reflectAssembly.system.findInterface(this.fqn); - } - - private emitConstructor(code: CodeMaker, resolver: TypeResolver) { - const members = this.allMembers; + private get thisInterface() { + if (this.fqn === null) { throw new Error('FQN not set'); } + return this.generator.reflectAssembly.system.findInterface(this.fqn); + } - const kwargs = members.map(m => m.constructorDecl(resolver)); + private emitConstructor(code: CodeMaker, resolver: TypeResolver) { + const members = this.allMembers; - const constructorArguments = kwargs.length > 0 ? ['self', '*', ...kwargs] : ['self']; + const kwargs = members.map(m => m.constructorDecl(resolver)); - code.openBlock(`def __init__(${constructorArguments.join(', ')})`); - this.emitConstructorDocstring(code); + const constructorArguments = kwargs.length > 0 ? ['self', '*', ...kwargs] : ['self']; - // Required properties, those will always be put into the dict - code.line('self._values = {'); - for (const member of members.filter(m => !m.optional)) { - code.line(` '${member.pythonName}': ${member.pythonName},`); - } - code.line('}'); - - // Optional properties, will only be put into the dict if they're not None - for (const member of members.filter(m => m.optional)) { - code.line(`if ${member.pythonName} is not None: self._values["${member.pythonName}"] = ${member.pythonName}`); - } + code.openBlock(`def __init__(${constructorArguments.join(', ')})`); + this.emitConstructorDocstring(code); - code.closeBlock(); + // Required properties, those will always be put into the dict + code.line('self._values = {'); + for (const member of members.filter(m => !m.optional)) { + code.line(` '${member.pythonName}': ${member.pythonName},`); } + code.line('}'); - private emitConstructorDocstring(code: CodeMaker) { - const args: DocumentableArgument[] = this.allMembers.map(m => ({ - name: m.pythonName, - docs: m.docs, - })); - emitDocString(code, this.docs, { arguments: args, documentableItem: `class-${this.pythonName}` }); + // Optional properties, will only be put into the dict if they're not None + for (const member of members.filter(m => m.optional)) { + code.line(`if ${member.pythonName} is not None: self._values["${member.pythonName}"] = ${member.pythonName}`); } - private emitGetter(member: StructField, code: CodeMaker, resolver: TypeResolver) { - code.line('@property'); - code.openBlock(`def ${member.pythonName}(self) -> ${member.typeAnnotation(resolver)}`); - member.emitDocString(code); - code.line(`return self._values.get('${member.pythonName}')`); - code.closeBlock(); - } + code.closeBlock(); + } - private emitMagicMethods(code: CodeMaker) { - code.openBlock(`def __eq__(self, rhs) -> bool`); - code.line('return isinstance(rhs, self.__class__) and rhs._values == self._values'); - code.closeBlock(); + private emitConstructorDocstring(code: CodeMaker) { + const args: DocumentableArgument[] = this.allMembers.map(m => ({ + name: m.pythonName, + docs: m.docs, + })); + emitDocString(code, this.docs, { arguments: args, documentableItem: `class-${this.pythonName}` }); + } - code.openBlock(`def __ne__(self, rhs) -> bool`); - code.line('return not (rhs == self)'); - code.closeBlock(); + private emitGetter(member: StructField, code: CodeMaker, resolver: TypeResolver) { + code.line('@property'); + code.openBlock(`def ${member.pythonName}(self) -> ${member.typeAnnotation(resolver)}`); + member.emitDocString(code); + code.line(`return self._values.get('${member.pythonName}')`); + code.closeBlock(); + } - code.openBlock(`def __repr__(self) -> str`); - code.line(`return '${this.pythonName}(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())`); - code.closeBlock(); - } + private emitMagicMethods(code: CodeMaker) { + code.openBlock('def __eq__(self, rhs) -> bool'); + code.line('return isinstance(rhs, self.__class__) and rhs._values == self._values'); + code.closeBlock(); - private propertyMap() { - const ret = new Array(); - for (const member of this.allMembers) { - ret.push(`'${member.pythonName}': '${member.jsiiName}'`); - } - return `{${ret.join(', ')}}`; - } -} + code.openBlock('def __ne__(self, rhs) -> bool'); + code.line('return not (rhs == self)'); + code.closeBlock(); -class StructField implements PythonBase { - public readonly pythonName: string; - public readonly jsiiName: string; - public readonly docs?: spec.Docs; - private readonly type: spec.OptionalValue; - - constructor(public readonly prop: spec.Property) { - this.pythonName = toPythonPropertyName(prop.name); - this.jsiiName = prop.name; - this.type = prop; - this.docs = prop.docs; - } - - public get optional(): boolean { - return !!this.type.optional; - } + code.openBlock('def __repr__(self) -> str'); + code.line(`return '${this.pythonName}(%s)' % ', '.join(k + '=' + repr(v) for k, v in self._values.items())`); + code.closeBlock(); + } - public isStruct(generator: PythonGenerator): boolean { - return isStruct(generator.reflectAssembly.system, this.type.type); - } - - public constructorDecl(resolver: TypeResolver) { - const opt = this.optional ? '=None' : ''; - return `${this.pythonName}: ${this.typeAnnotation(resolver)}${opt}`; + private propertyMap() { + const ret = new Array(); + for (const member of this.allMembers) { + ret.push(`'${member.pythonName}': '${member.jsiiName}'`); } + return `{${ret.join(', ')}}`; + } +} - /** +class StructField implements PythonBase { + public readonly pythonName: string; + public readonly jsiiName: string; + public readonly docs?: spec.Docs; + private readonly type: spec.OptionalValue; + + public constructor(public readonly prop: spec.Property) { + this.pythonName = toPythonPropertyName(prop.name); + this.jsiiName = prop.name; + this.type = prop; + this.docs = prop.docs; + } + + public get optional(): boolean { + return !!this.type.optional; + } + + public isStruct(generator: PythonGenerator): boolean { + return isStruct(generator.reflectAssembly.system, this.type.type); + } + + public constructorDecl(resolver: TypeResolver) { + const opt = this.optional ? '=None' : ''; + return `${this.pythonName}: ${this.typeAnnotation(resolver)}${opt}`; + } + + /** * Return the Python type annotation for this type */ - public typeAnnotation(resolver: TypeResolver) { - return resolver.resolve( - this.type, - { forwardReferences: false } - ); - } - - public emitDocString(code: CodeMaker) { - emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); - } - - public emit(code: CodeMaker, resolver: TypeResolver) { - const resolvedType = this.typeAnnotation(resolver); - code.line(`${this.pythonName}: ${resolvedType}`); - this.emitDocString(code); - } + public typeAnnotation(resolver: TypeResolver) { + return resolver.resolve( + this.type, + { forwardReferences: false } + ); + } + + public emitDocString(code: CodeMaker) { + emitDocString(code, this.docs, { documentableItem: `prop-${this.pythonName}` }); + } + + public emit(code: CodeMaker, resolver: TypeResolver) { + const resolvedType = this.typeAnnotation(resolver); + code.line(`${this.pythonName}: ${resolvedType}`); + this.emitDocString(code); + } } interface ClassOpts extends PythonTypeOpts { - abstract?: boolean; - interfaces?: spec.NamedTypeReference[]; - abstractBases?: spec.ClassType[]; + abstract?: boolean; + interfaces?: spec.NamedTypeReference[]; + abstractBases?: spec.ClassType[]; } class Class extends BasePythonClassType { - private abstract: boolean; - private abstractBases: spec.ClassType[]; - private interfaces: spec.NamedTypeReference[]; - - constructor(generator: PythonGenerator, name: string, fqn: string, opts: ClassOpts, docs: spec.Docs | undefined) { - super(generator, name, fqn, opts, docs); - - const { abstract = false, interfaces = [], abstractBases = [] } = opts; - - this.abstract = abstract; - this.interfaces = interfaces; - this.abstractBases = abstractBases; - } - - public dependsOn(resolver: TypeResolver): PythonType[] { - const dependencies: PythonType[] = super.dependsOn(resolver); - const parent = resolver.getParent(this.fqn!); - - // We need to return any ifaces that are in the same module at the same level of - // nesting. - const seen: Set = new Set(); - for (const iface of this.interfaces) { - if (resolver.isInModule(iface)) { - // Given a iface, we need to locate the ifaces's parent that is the same - // as our parent, because we only care about dependencies that are at the - // same level of our own. - // TODO: We might need to recurse into our members to also find their - // dependencies. - let ifaceItem = resolver.getType(iface); - let ifaceParent = resolver.getParent(iface); - while (ifaceParent !== parent) { - ifaceItem = ifaceParent; - ifaceParent = resolver.getParent(ifaceItem.fqn!); - } - - if (!seen.has(ifaceItem.fqn!)) { - dependencies.push(ifaceItem); - seen.add(ifaceItem.fqn!); - } - } - } + private readonly abstract: boolean; + private readonly abstractBases: spec.ClassType[]; + private readonly interfaces: spec.NamedTypeReference[]; - return dependencies; - } + public constructor(generator: PythonGenerator, name: string, fqn: string, opts: ClassOpts, docs: spec.Docs | undefined) { + super(generator, name, fqn, opts, docs); + + const { abstract = false, interfaces = [], abstractBases = [] } = opts; + + this.abstract = abstract; + this.interfaces = interfaces; + this.abstractBases = abstractBases; + } + + public dependsOn(resolver: TypeResolver): PythonType[] { + const dependencies: PythonType[] = super.dependsOn(resolver); + const parent = resolver.getParent(this.fqn!); - public emit(code: CodeMaker, resolver: TypeResolver) { - // First we emit our implments decorator - if (this.interfaces.length > 0) { - const interfaces: string[] = this.interfaces.map(b => resolver.resolve({ type: b })); - code.line(`@jsii.implements(${interfaces.join(", ")})`); + // We need to return any ifaces that are in the same module at the same level of + // nesting. + const seen: Set = new Set(); + for (const iface of this.interfaces) { + if (resolver.isInModule(iface)) { + // Given a iface, we need to locate the ifaces's parent that is the same + // as our parent, because we only care about dependencies that are at the + // same level of our own. + // TODO: We might need to recurse into our members to also find their + // dependencies. + let ifaceItem = resolver.getType(iface); + let ifaceParent = resolver.getParent(iface); + while (ifaceParent !== parent) { + ifaceItem = ifaceParent; + ifaceParent = resolver.getParent(ifaceItem.fqn!); } - // Then we do our normal class logic for emitting our members. - super.emit(code, resolver); - - // Then, if our class is Abstract, we have to go through and redo all of - // this logic, except only emiting abstract methods and properties as non - // abstract, and subclassing our initial class. - if (this.abstract) { - resolver = this.fqn ? resolver.bind(this.fqn) : resolver; - - const proxyBases: string[] = [this.pythonName]; - for (const base of this.abstractBases) { - proxyBases.push(`jsii.proxy_for(${resolver.resolve({ type: base })})`); - } - - code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(', ')})`); - - // Filter our list of members to *only* be abstract members, and not any - // other types. - const abstractMembers = this.members.filter( - m => (m instanceof BaseMethod || m instanceof BaseProperty) && m.abstract - ); - if (abstractMembers.length > 0) { - for (const member of abstractMembers) { - member.emit(code, resolver, { renderAbstract: false }); - } - } else { - code.line("pass"); - } - - code.closeBlock(); + if (!seen.has(ifaceItem.fqn!)) { + dependencies.push(ifaceItem); + seen.add(ifaceItem.fqn!); } + } } - protected emitPreamble(code: CodeMaker, _resolver: TypeResolver) { - if (this.abstract) { - code.line("@staticmethod"); - code.openBlock("def __jsii_proxy_class__()"); - code.line(`return ${this.getProxyClassName()}`); - code.closeBlock(); - } + return dependencies; + } + + public emit(code: CodeMaker, resolver: TypeResolver) { + // First we emit our implments decorator + if (this.interfaces.length > 0) { + const interfaces: string[] = this.interfaces.map(b => resolver.resolve({ type: b })); + code.line(`@jsii.implements(${interfaces.join(', ')})`); } - protected getClassParams(resolver: TypeResolver): string[] { - const params: string[] = this.bases.map(b => resolver.resolve({ type: b })); - const metaclass: string = this.abstract ? "JSIIAbstractClass" : "JSIIMeta"; + // Then we do our normal class logic for emitting our members. + super.emit(code, resolver); + + // Then, if our class is Abstract, we have to go through and redo all of + // this logic, except only emiting abstract methods and properties as non + // abstract, and subclassing our initial class. + if (this.abstract) { + resolver = this.fqn ? resolver.bind(this.fqn) : resolver; - params.push(`metaclass=jsii.${metaclass}`); - params.push(`jsii_type="${this.fqn}"`); + const proxyBases: string[] = [this.pythonName]; + for (const base of this.abstractBases) { + proxyBases.push(`jsii.proxy_for(${resolver.resolve({ type: base })})`); + } - return params; + code.openBlock(`class ${this.getProxyClassName()}(${proxyBases.join(', ')})`); + + // Filter our list of members to *only* be abstract members, and not any + // other types. + const abstractMembers = this.members.filter( + m => (m instanceof BaseMethod || m instanceof BaseProperty) && m.abstract + ); + if (abstractMembers.length > 0) { + for (const member of abstractMembers) { + member.emit(code, resolver, { renderAbstract: false }); + } + } else { + code.line('pass'); + } + + code.closeBlock(); } + } - private getProxyClassName(): string { - return `_${this.pythonName}Proxy`; + protected emitPreamble(code: CodeMaker, _resolver: TypeResolver) { + if (this.abstract) { + code.line('@staticmethod'); + code.openBlock('def __jsii_proxy_class__()'); + code.line(`return ${this.getProxyClassName()}`); + code.closeBlock(); } + } + + protected getClassParams(resolver: TypeResolver): string[] { + const params: string[] = this.bases.map(b => resolver.resolve({ type: b })); + const metaclass: string = this.abstract ? 'JSIIAbstractClass' : 'JSIIMeta'; + + params.push(`metaclass=jsii.${metaclass}`); + params.push(`jsii_type="${this.fqn}"`); + + return params; + } + + private getProxyClassName(): string { + return `_${this.pythonName}Proxy`; + } } class StaticMethod extends BaseMethod { - protected readonly decorator?: string = "classmethod"; - protected readonly implicitParameter: string = "cls"; - protected readonly jsiiMethod: string = "sinvoke"; + protected readonly decorator?: string = 'classmethod'; + protected readonly implicitParameter: string = 'cls'; + protected readonly jsiiMethod: string = 'sinvoke'; } class Initializer extends BaseMethod { - protected readonly implicitParameter: string = "self"; - protected readonly jsiiMethod: string = "create"; - protected readonly classAsFirstParameter: boolean = true; - protected readonly returnFromJSIIMethod: boolean = false; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiMethod: string = 'create'; + protected readonly classAsFirstParameter: boolean = true; + protected readonly returnFromJSIIMethod: boolean = false; } class Method extends BaseMethod { - protected readonly implicitParameter: string = "self"; - protected readonly jsiiMethod: string = "invoke"; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiMethod: string = 'invoke'; } class AsyncMethod extends BaseMethod { - protected readonly implicitParameter: string = "self"; - protected readonly jsiiMethod: string = "ainvoke"; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiMethod: string = 'ainvoke'; } class StaticProperty extends BaseProperty { - protected readonly decorator: string = "classproperty"; - protected readonly implicitParameter: string = "cls"; - protected readonly jsiiGetMethod: string = "sget"; - protected readonly jsiiSetMethod: string = "sset"; + protected readonly decorator: string = 'classproperty'; + protected readonly implicitParameter: string = 'cls'; + protected readonly jsiiGetMethod: string = 'sget'; + protected readonly jsiiSetMethod: string = 'sset'; } class Property extends BaseProperty { - protected readonly decorator: string = "property"; - protected readonly implicitParameter: string = "self"; - protected readonly jsiiGetMethod: string = "get"; - protected readonly jsiiSetMethod: string = "set"; + protected readonly decorator: string = 'property'; + protected readonly implicitParameter: string = 'self'; + protected readonly jsiiGetMethod: string = 'get'; + protected readonly jsiiSetMethod: string = 'set'; } class Enum extends BasePythonClassType { - public emit(code: CodeMaker, resolver: TypeResolver) { - code.line(`@jsii.enum(jsii_type="${this.fqn}")`); - return super.emit(code, resolver); - } + public emit(code: CodeMaker, resolver: TypeResolver) { + code.line(`@jsii.enum(jsii_type="${this.fqn}")`); + return super.emit(code, resolver); + } - protected getClassParams(_resolver: TypeResolver): string[] { - return ["enum.Enum"]; - } + protected getClassParams(_resolver: TypeResolver): string[] { + return ['enum.Enum']; + } } class EnumMember implements PythonBase { - constructor(public readonly pythonName: string, private readonly value: string, private readonly docs: spec.Docs | undefined) { - this.pythonName = pythonName; - this.value = value; - } - - public emit(code: CodeMaker, _resolver: TypeResolver) { - code.line(`${this.pythonName} = "${this.value}"`); - emitDocString(code, this.docs, { documentableItem: `enum-${this.pythonName}` }); - } + public constructor(public readonly pythonName: string, private readonly value: string, private readonly docs: spec.Docs | undefined) { + this.pythonName = pythonName; + this.value = value; + } + + public emit(code: CodeMaker, _resolver: TypeResolver) { + code.line(`${this.pythonName} = "${this.value}"`); + emitDocString(code, this.docs, { documentableItem: `enum-${this.pythonName}` }); + } } class Namespace extends BasePythonClassType { - protected getClassParams(_resolver: TypeResolver): string[] { - return []; - } + protected getClassParams(_resolver: TypeResolver): string[] { + return []; + } } interface ModuleOpts { - assembly: spec.Assembly, - assemblyFilename: string; - loadAssembly: boolean; + assembly: spec.Assembly; + assemblyFilename: string; + loadAssembly: boolean; } class Module implements PythonType { - public readonly pythonName: string; - public readonly fqn: string | null; - - private assembly: spec.Assembly; - private assemblyFilename: string; - private loadAssembly: boolean; - private members: PythonBase[]; - - constructor(name: string, fqn: string | null, opts: ModuleOpts) { - this.pythonName = name; - this.fqn = fqn; - - this.assembly = opts.assembly; - this.assemblyFilename = opts.assemblyFilename; - this.loadAssembly = opts.loadAssembly; - this.members = []; + public readonly pythonName: string; + public readonly fqn: string | null; + + private readonly assembly: spec.Assembly; + private readonly assemblyFilename: string; + private readonly loadAssembly: boolean; + private readonly members: PythonBase[]; + + public constructor(name: string, fqn: string | null, opts: ModuleOpts) { + this.pythonName = name; + this.fqn = fqn; + + this.assembly = opts.assembly; + this.assemblyFilename = opts.assemblyFilename; + this.loadAssembly = opts.loadAssembly; + this.members = []; + } + + public addMember(member: PythonBase) { + this.members.push(member); + } + + public emit(code: CodeMaker, resolver: TypeResolver) { + resolver = this.fqn ? resolver.bind(this.fqn, this.pythonName) : resolver; + + // Before we write anything else, we need to write out our module headers, this + // is where we handle stuff like imports, any required initialization, etc. + code.line('import abc'); + code.line('import datetime'); + code.line('import enum'); + code.line('import typing'); + code.line(); + code.line('import jsii'); + code.line('import jsii.compat'); + code.line('import publication'); + code.line(); + code.line('from jsii.python import classproperty'); + + // Go over all of the modules that we need to import, and import them. + this.emitDependencyImports(code, resolver); + + // Determine if we need to write out the kernel load line. + if (this.loadAssembly) { + code.line( + '__jsii_assembly__ = jsii.JSIIAssembly.load(' + + `"${this.assembly.name}", ` + + `"${this.assembly.version}", ` + + '__name__, ' + + `"${this.assemblyFilename}")` + ); } - public addMember(member: PythonBase) { - this.members.push(member); + // Emit all of our members. + for (const member of sortMembers(this.members, resolver)) { + member.emit(code, resolver); } - public emit(code: CodeMaker, resolver: TypeResolver) { - resolver = this.fqn ? resolver.bind(this.fqn, this.pythonName) : resolver; - - // Before we write anything else, we need to write out our module headers, this - // is where we handle stuff like imports, any required initialization, etc. - code.line("import abc"); - code.line("import datetime"); - code.line("import enum"); - code.line("import typing"); - code.line(); - code.line("import jsii"); - code.line("import jsii.compat"); - code.line("import publication"); - code.line(); - code.line("from jsii.python import classproperty"); - - // Go over all of the modules that we need to import, and import them. - this.emitDependencyImports(code, resolver); - - // Determine if we need to write out the kernel load line. - if (this.loadAssembly) { - code.line( - `__jsii_assembly__ = jsii.JSIIAssembly.load(` + - `"${this.assembly.name}", ` + - `"${this.assembly.version}", ` + - `__name__, ` + - `"${this.assemblyFilename}")` - ); - } + // Whatever names we've exported, we'll write out our __all__ that lists them. + const exportedMembers = this.members.map(m => `"${m.pythonName}"`); + if (this.loadAssembly) { + exportedMembers.push('"__jsii_assembly__"'); + } + code.line(`__all__ = [${exportedMembers.sort().join(', ')}]`); - // Emit all of our members. - for (const member of sortMembers(this.members, resolver)) { - member.emit(code, resolver); - } + // Finally, we'll use publication to ensure that all of the non-public names + // get hidden from dir(), tab-complete, etc. + code.line(); + code.line('publication.publish()'); + } - // Whatever names we've exported, we'll write out our __all__ that lists them. - const exportedMembers = this.members.map(m => `"${m.pythonName}"`); - if (this.loadAssembly) { - exportedMembers.push(`"__jsii_assembly__"`); - } - code.line(`__all__ = [${exportedMembers.sort().join(", ")}]`); + private emitDependencyImports(code: CodeMaker, _resolver: TypeResolver) { + const deps = Array.from( + new Set([ + ...Object.values(this.assembly.dependencies || {}).map(d => { + return d.targets!.python!.module; + }), + ]) + ); - // Finally, we'll use publication to ensure that all of the non-public names - // get hidden from dir(), tab-complete, etc. + for (const [idx, moduleName] of deps.sort().entries()) { + // If this our first dependency, add a blank line to format our imports + // slightly nicer. + if (idx === 0) { code.line(); - code.line("publication.publish()"); - } - - private emitDependencyImports(code: CodeMaker, _resolver: TypeResolver) { - const deps = Array.from( - new Set([ - ...Object.values(this.assembly.dependencies || {}).map(d => { - return (d as spec.PackageVersion).targets!.python!.module; - }), - ]) - ); - - for (const [idx, moduleName] of deps.sort().entries()) { - // If this our first dependency, add a blank line to format our imports - // slightly nicer. - if (idx === 0) { - code.line(); - } - - code.line(`import ${moduleName}`); - } + } + + code.line(`import ${moduleName}`); } + } } interface PackageData { - filename: string; - data: string | null; + filename: string; + data: string | null; } class Package { - public readonly name: string; - public readonly version: string; - public readonly metadata: spec.Assembly; - - private modules: Map; - private data: Map; - - constructor(name: string, version: string, metadata: spec.Assembly) { - this.name = name; - this.version = version; - this.metadata = metadata; - - this.modules = new Map(); - this.data = new Map(); - } - - public addModule(module: Module) { - this.modules.set(module.pythonName, module); - } - - public addData(module: Module, filename: string, data: string | null) { - if (!this.data.has(module.pythonName)) { - this.data.set(module.pythonName, new Array()); - } - - this.data.get(module.pythonName)!.push({filename, data}); - } - - public write(code: CodeMaker, resolver: TypeResolver) { - const modules = [...this.modules.values()].sort((a, b) => a.pythonName.localeCompare(b.pythonName)); - - // Iterate over all of our modules, and write them out to disk. - for (const mod of modules) { - const filename = path.join("src", pythonModuleNameToFilename(mod.pythonName), "__init__.py"); - - code.openFile(filename); - mod.emit(code, resolver); - code.closeFile(filename); - } - - // Handle our package data. - const packageData: {[key: string]: string[]} = {}; - for (const [mod, pdata] of this.data) { - for (const data of pdata) { - if (data.data != null) { - const filepath = path.join("src", pythonModuleNameToFilename(mod), data.filename); - - code.openFile(filepath); - code.line(data.data); - code.closeFile(filepath); - } - } - - packageData[mod] = pdata.map(pd => pd.filename); - } - - // Compute our list of dependencies - const dependencies: string[] = []; - const expectedDeps = this.metadata.dependencies || {}; - for (const depName of Object.keys(expectedDeps)) { - const depInfo = expectedDeps[depName]; - // We need to figure out what our version range is. - // Basically, if it starts with Zero we want to restrict things to - // ~=X.Y.Z. If it does not start with zero, then we want to do ~=X.Y,>=X.Y.Z. - const versionParts = depInfo.version.split("."); - let versionSpecifier: string; - if (versionParts[0] === "0") { - versionSpecifier = `~=${versionParts.slice(0, 3).join(".")}`; - } else { - versionSpecifier = `~=${versionParts.slice(0, 2).join(".")},>=${versionParts.slice(0, 3).join(".")}`; - } - - dependencies.push(`${depInfo.targets!.python!.distName}${versionSpecifier}`); - } - - code.openFile("README.md"); - if (this.metadata.readme) { - code.line(convertSnippetsInMarkdown(this.metadata.readme.markdown, 'README.md')); - } - - code.line(this.metadata.readme && this.metadata.readme.markdown); - code.closeFile("README.md"); - - // Strip " (build abcdef)" from the jsii version - const jsiiVersionSimple = this.metadata.jsiiVersion.replace(/ .*$/, ''); - - const setupKwargs = { - name: this.name, - version: this.version, - description: this.metadata.description, - url: this.metadata.homepage, - long_description_content_type: "text/markdown", - author: this.metadata.author.name + ( - this.metadata.author.email !== undefined ? "<" + this.metadata.author.email + ">" : "" - ), - project_urls: { - Source: this.metadata.repository.url, - }, - package_dir: {"": "src"}, - packages: modules.map(m => m.pythonName), - package_data: packageData, - python_requires: ">=3.6", - install_requires: [`jsii~=${jsiiVersionSimple}`, "publication>=0.0.3"].concat(dependencies), - }; - - // We Need a setup.py to make this Package, actually a Package. - // TODO: - // - License - // - Classifiers - code.openFile("setup.py"); - code.line("import json"); - code.line("import setuptools"); - code.line(); - code.line('kwargs = json.loads("""'); - code.line(JSON.stringify(setupKwargs, null, 4)); - code.line('""")'); - code.line(); - code.openBlock("with open('README.md') as fp"); - code.line("kwargs['long_description'] = fp.read()"); - code.closeBlock(); - code.line(); - code.line("setuptools.setup(**kwargs)"); - code.closeFile("setup.py"); - - // Because we're good citizens, we're going to go ahead and support pyproject.toml - // as well. - // TODO: Might be easier to just use a TOML library to write this out. - code.openFile("pyproject.toml"); - code.line("[build-system]"); - code.line('requires = ["setuptools >= 38.6.0", "wheel >= 0.31.0"]'); - code.line('build-backend = "setuptools.build_meta"'); - code.closeFile("pyproject.toml"); - - // We also need to write out a MANIFEST.in to ensure that all of our required - // files are included. - code.openFile("MANIFEST.in"); - code.line("include pyproject.toml"); - code.closeFile("MANIFEST.in"); - } + public readonly name: string; + public readonly version: string; + public readonly metadata: spec.Assembly; + + private readonly modules: Map; + private readonly data: Map; + + public constructor(name: string, version: string, metadata: spec.Assembly) { + this.name = name; + this.version = version; + this.metadata = metadata; + + this.modules = new Map(); + this.data = new Map(); + } + + public addModule(module: Module) { + this.modules.set(module.pythonName, module); + } + + public addData(module: Module, filename: string, data: string | null) { + if (!this.data.has(module.pythonName)) { + this.data.set(module.pythonName, []); + } + + this.data.get(module.pythonName)!.push({ filename, data }); + } + + public write(code: CodeMaker, resolver: TypeResolver) { + const modules = [...this.modules.values()].sort((a, b) => a.pythonName.localeCompare(b.pythonName)); + + // Iterate over all of our modules, and write them out to disk. + for (const mod of modules) { + const filename = path.join('src', pythonModuleNameToFilename(mod.pythonName), '__init__.py'); + + code.openFile(filename); + mod.emit(code, resolver); + code.closeFile(filename); + } + + // Handle our package data. + const packageData: {[key: string]: string[]} = {}; + for (const [mod, pdata] of this.data) { + for (const data of pdata) { + if (data.data != null) { + const filepath = path.join('src', pythonModuleNameToFilename(mod), data.filename); + + code.openFile(filepath); + code.line(data.data); + code.closeFile(filepath); + } + } + + packageData[mod] = pdata.map(pd => pd.filename); + } + + // Compute our list of dependencies + const dependencies: string[] = []; + const expectedDeps = this.metadata.dependencies || {}; + for (const depName of Object.keys(expectedDeps)) { + const depInfo = expectedDeps[depName]; + // We need to figure out what our version range is. + // Basically, if it starts with Zero we want to restrict things to + // ~=X.Y.Z. If it does not start with zero, then we want to do ~=X.Y,>=X.Y.Z. + const versionParts = depInfo.version.split('.'); + let versionSpecifier: string; + if (versionParts[0] === '0') { + versionSpecifier = `~=${versionParts.slice(0, 3).join('.')}`; + } else { + versionSpecifier = `~=${versionParts.slice(0, 2).join('.')},>=${versionParts.slice(0, 3).join('.')}`; + } + + dependencies.push(`${depInfo.targets!.python!.distName}${versionSpecifier}`); + } + + code.openFile('README.md'); + if (this.metadata.readme) { + code.line(convertSnippetsInMarkdown(this.metadata.readme.markdown, 'README.md')); + } + code.closeFile('README.md'); + + // Strip " (build abcdef)" from the jsii version + const jsiiVersionSimple = this.metadata.jsiiVersion.replace(/ .*$/, ''); + + /* eslint-disable @typescript-eslint/camelcase */ + const setupKwargs = { + name: this.name, + version: this.version, + description: this.metadata.description, + url: this.metadata.homepage, + long_description_content_type: 'text/markdown', + author: this.metadata.author.name + ( + this.metadata.author.email !== undefined ? `<${this.metadata.author.email}>` : '' + ), + project_urls: { + Source: this.metadata.repository.url, + }, + package_dir: { '': 'src' }, + packages: modules.map(m => m.pythonName), + package_data: packageData, + python_requires: '>=3.6', + install_requires: [`jsii~=${jsiiVersionSimple}`, 'publication>=0.0.3'].concat(dependencies), + }; + /* eslint-enable @typescript-eslint/camelcase */ + + // We Need a setup.py to make this Package, actually a Package. + // TODO: + // - License + // - Classifiers + code.openFile('setup.py'); + code.line('import json'); + code.line('import setuptools'); + code.line(); + code.line('kwargs = json.loads("""'); + code.line(JSON.stringify(setupKwargs, null, 4)); + code.line('""")'); + code.line(); + code.openBlock("with open('README.md') as fp"); + code.line("kwargs['long_description'] = fp.read()"); + code.closeBlock(); + code.line(); + code.line('setuptools.setup(**kwargs)'); + code.closeFile('setup.py'); + + // Because we're good citizens, we're going to go ahead and support pyproject.toml + // as well. + // TODO: Might be easier to just use a TOML library to write this out. + code.openFile('pyproject.toml'); + code.line('[build-system]'); + code.line('requires = ["setuptools >= 38.6.0", "wheel >= 0.31.0"]'); + code.line('build-backend = "setuptools.build_meta"'); + code.closeFile('pyproject.toml'); + + // We also need to write out a MANIFEST.in to ensure that all of our required + // files are included. + code.openFile('MANIFEST.in'); + code.line('include pyproject.toml'); + code.closeFile('MANIFEST.in'); + } } type FindModuleCallback = (fqn: string) => spec.Assembly | spec.PackageVersion; type FindTypeCallback = (fqn: string) => spec.Type; interface TypeResolverOpts { - forwardReferences?: boolean; - ignoreOptional?: boolean; + forwardReferences?: boolean; + ignoreOptional?: boolean; } class TypeResolver { - private readonly types: Map; - private boundTo?: string; - private readonly stdTypesRe = new RegExp("^(datetime\\.datetime|typing\\.[A-Z][a-z]+|jsii\\.Number)$"); - private readonly boundRe: RegExp; - private readonly moduleName?: string; - private readonly moduleRe: RegExp; - private readonly findModule: FindModuleCallback; - private readonly findType: FindTypeCallback; - - constructor(types: Map, - findModule: FindModuleCallback, - findType: FindTypeCallback, - boundTo?: string, - moduleName?: string) { - this.types = types; - this.findModule = findModule; - this.findType = findType; - this.moduleName = moduleName; - this.boundTo = boundTo !== undefined ? this.toPythonFQN(boundTo) : boundTo; - - if (this.moduleName !== undefined) { - this.moduleRe = new RegExp(`^(${escapeStringRegexp(this.moduleName)})\\.(.+)$`); - } - - if (this.boundTo !== undefined) { - this.boundRe = new RegExp(`^(${escapeStringRegexp(this.boundTo)})\\.(.+)$`); - } - } - - public bind(fqn: string, moduleName?: string): TypeResolver { - return new TypeResolver( - this.types, - this.findModule, - this.findType, - fqn, - moduleName !== undefined ? moduleName : this.moduleName, - ); - } - - public isInModule(typeRef: spec.NamedTypeReference | string): boolean { - const pythonType = typeof typeRef !== "string" ? this.toPythonFQN(typeRef.fqn) : typeRef; - return this.moduleRe.test(pythonType); - } - - public isInNamespace(typeRef: spec.NamedTypeReference | string): boolean { - const pythonType = typeof typeRef !== "string" ? this.toPythonFQN(typeRef.fqn) : typeRef; - return this.boundRe.test(pythonType); - } - - public getParent(typeRef: spec.NamedTypeReference | string): PythonType { - const fqn = typeof typeRef !== "string" ? typeRef.fqn : typeRef; - const [, parentFQN] = fqn.match(/^(.+)\.[^\.]+$/) as string[]; - const parent = this.types.get(parentFQN); - - if (parent === undefined) { - throw new Error(`Could not find parent: ${parentFQN}`); - } - - return parent; - } - - public getType(typeRef: spec.NamedTypeReference): PythonType { - const type = this.types.get(typeRef.fqn); - - if (type === undefined) { - throw new Error(`Could not locate type: "${typeRef.fqn}"`); - } - - return type; - } - - public dereference(typeRef: string | spec.NamedTypeReference): spec.Type { - if (typeof typeRef !== 'string') { - typeRef = typeRef.fqn; - } - return this.findType(typeRef); - } - - public resolve( - typeInstance: spec.OptionalValue, - opts: TypeResolverOpts = { forwardReferences: true, ignoreOptional: false }): string { - const { - forwardReferences = true, - } = opts; - - const optional = opts.ignoreOptional ? false : !!typeInstance.optional; - // First, we need to resolve our given type reference into the Python type. - let pythonType = this.toPythonType(typeInstance.type, { optional }); - - // If we split our types by any of the "special" characters that can't appear in - // identifiers (like "[],") then we will get a list of all of the identifiers, - // no matter how nested they are. The downside is we might get trailing/leading - // spaces or empty items so we'll need to trim and filter this list. - const types = pythonType.split(/[\[\],]/).map((s: string) => s.trim()).filter(s => s !== ""); - - for (const innerType of types) { - // Built in types do not need formatted in any particular way. - if (PYTHON_BUILTIN_TYPES.indexOf(innerType) > -1) { - continue; - } - - // These are not exactly built in types, but they're also not types that - // this resolver has to worry about. - if (this.stdTypesRe.test(innerType)) { - continue; - } - - // If our resolver is bound to the same module as the type we're trying to - // resolve, then we'll implement the needed logic to use module relative naming - // and to handle forward references (if needed). - if (this.isInModule(innerType)) { - // If our type is part of the same namespace, then we'll return a namespace - // relative name, otherwise a module relative name. - let typeName: string; - if (this.isInNamespace(innerType)) { - [, , typeName] = innerType.match(this.boundRe) as string[]; - } else { - [, , typeName] = innerType.match(this.moduleRe) as string[]; - } - - // This re will look for the entire type, boxed by either the start/end of - // a string, a comma, a space, a quote, or open/closing brackets. This will - // ensure that we only match whole type names, and not partial ones. - const re = new RegExp('((?:^|[[,\\s])"?)' + innerType + '("?(?:$|[\\],\\s]))'); - - // We need to handle forward references, our caller knows if we're able to - // use them in the current context or not, so if not, we'll wrap our forward - // reference in quotes. - // We have special logic here for checking if our thing is actually *in* - // our module, behond what we've already done, because our other logic will - // work for submodules, but this can't. - if (!forwardReferences && this.isInModule(innerType)) { - pythonType = pythonType.replace(re, `$1"${innerType}"$2`); - } - - // Now that we've gotten forward references out of the way, we will want - // to replace the entire type string, with just the type portion. - pythonType = pythonType.replace(re, `$1${typeName}$2`); - } - } - - return pythonType; - } - - private toPythonType(typeRef: spec.TypeReference, opts: { optional: boolean }): string { - let pythonType: string; - - // Get the underlying python type. - if (spec.isPrimitiveTypeReference(typeRef)) { - pythonType = this.toPythonPrimitive(typeRef.primitive); - } else if (spec.isCollectionTypeReference(typeRef)) { - pythonType = this.toPythonCollection(typeRef); - } else if (spec.isNamedTypeReference(typeRef)) { - pythonType = this.toPythonFQN(typeRef.fqn); - } else if (typeRef.union) { - const types = new Array(); - for (const subtype of typeRef.union.types) { - types.push(this.toPythonType(subtype, opts)); - } - pythonType = `typing.Union[${types.join(", ")}]`; + private readonly types: Map; + private readonly boundTo?: string; + private readonly stdTypesRe = new RegExp('^(datetime\\.datetime|typing\\.[A-Z][a-z]+|jsii\\.Number)$'); + private readonly boundRe: RegExp; + private readonly moduleName?: string; + private readonly moduleRe: RegExp; + private readonly findModule: FindModuleCallback; + private readonly findType: FindTypeCallback; + + public constructor(types: Map, + findModule: FindModuleCallback, + findType: FindTypeCallback, + boundTo?: string, + moduleName?: string) { + this.types = types; + this.findModule = findModule; + this.findType = findType; + this.moduleName = moduleName; + this.boundTo = boundTo !== undefined ? this.toPythonFQN(boundTo) : boundTo; + + if (this.moduleName !== undefined) { + this.moduleRe = new RegExp(`^(${escapeStringRegexp(this.moduleName)})\\.(.+)$`); + } + + if (this.boundTo !== undefined) { + this.boundRe = new RegExp(`^(${escapeStringRegexp(this.boundTo)})\\.(.+)$`); + } + } + + public bind(fqn: string, moduleName?: string): TypeResolver { + return new TypeResolver( + this.types, + this.findModule, + this.findType, + fqn, + moduleName !== undefined ? moduleName : this.moduleName, + ); + } + + public isInModule(typeRef: spec.NamedTypeReference | string): boolean { + const pythonType = typeof typeRef !== 'string' ? this.toPythonFQN(typeRef.fqn) : typeRef; + return this.moduleRe.test(pythonType); + } + + public isInNamespace(typeRef: spec.NamedTypeReference | string): boolean { + const pythonType = typeof typeRef !== 'string' ? this.toPythonFQN(typeRef.fqn) : typeRef; + return this.boundRe.test(pythonType); + } + + public getParent(typeRef: spec.NamedTypeReference | string): PythonType { + const fqn = typeof typeRef !== 'string' ? typeRef.fqn : typeRef; + const [, parentFQN] = /^(.+)\.[^.]+$/.exec(fqn) as string[]; + const parent = this.types.get(parentFQN); + + if (parent === undefined) { + throw new Error(`Could not find parent: ${parentFQN}`); + } + + return parent; + } + + public getType(typeRef: spec.NamedTypeReference): PythonType { + const type = this.types.get(typeRef.fqn); + + if (type === undefined) { + throw new Error(`Could not locate type: "${typeRef.fqn}"`); + } + + return type; + } + + public dereference(typeRef: string | spec.NamedTypeReference): spec.Type { + if (typeof typeRef !== 'string') { + typeRef = typeRef.fqn; + } + return this.findType(typeRef); + } + + public resolve( + typeInstance: spec.OptionalValue, + opts: TypeResolverOpts = { forwardReferences: true, ignoreOptional: false }): string { + const { + forwardReferences = true, + } = opts; + + const optional = opts.ignoreOptional ? false : !!typeInstance.optional; + // First, we need to resolve our given type reference into the Python type. + let pythonType = this.toPythonType(typeInstance.type, { optional }); + + // If we split our types by any of the "special" characters that can't appear in + // identifiers (like "[],") then we will get a list of all of the identifiers, + // no matter how nested they are. The downside is we might get trailing/leading + // spaces or empty items so we'll need to trim and filter this list. + const types = pythonType.split(/[[\],]/).map((s: string) => s.trim()).filter(s => s !== ''); + + for (const innerType of types) { + // Built in types do not need formatted in any particular way. + if (PYTHON_BUILTIN_TYPES.includes(innerType)) { + continue; + } + + // These are not exactly built in types, but they're also not types that + // this resolver has to worry about. + if (this.stdTypesRe.test(innerType)) { + continue; + } + + // If our resolver is bound to the same module as the type we're trying to + // resolve, then we'll implement the needed logic to use module relative naming + // and to handle forward references (if needed). + if (this.isInModule(innerType)) { + // If our type is part of the same namespace, then we'll return a namespace + // relative name, otherwise a module relative name. + let typeName: string; + if (this.isInNamespace(innerType)) { + [, , typeName] = this.boundRe.exec(innerType) as string[]; } else { - throw new Error("Invalid type reference: " + JSON.stringify(typeRef)); + [, , typeName] = this.moduleRe.exec(innerType) as string[]; } - // If our type is Optional, then we'll wrap our underlying type with typing.Optional - // However, if we're not respecting optionals, then we'll just skip over this. - // We explicitly don't emit this when our type is typing.Any, because typing.Any - // already implied that None is an accepted type. - // See: https://github.com/aws/jsii/issues/284 - if (opts.optional && pythonType !== "typing.Any") { - pythonType = `typing.Optional[${pythonType}]`; - } + // This re will look for the entire type, boxed by either the start/end of + // a string, a comma, a space, a quote, or open/closing brackets. This will + // ensure that we only match whole type names, and not partial ones. + const re = new RegExp(`((?:^|[[,\\s])"?)${innerType}("?(?:$|[\\],\\s]))`); - return pythonType; - } - - private toPythonPrimitive(primitive: spec.PrimitiveType): string { - switch (primitive) { - case spec.PrimitiveType.Boolean: return "bool"; - case spec.PrimitiveType.Date: return "datetime.datetime"; - case spec.PrimitiveType.Json: return "typing.Mapping[typing.Any, typing.Any]"; - case spec.PrimitiveType.Number: return "jsii.Number"; - case spec.PrimitiveType.String: return "str"; - case spec.PrimitiveType.Any: return "typing.Any"; - default: - throw new Error("Unknown primitive type: " + primitive); + // We need to handle forward references, our caller knows if we're able to + // use them in the current context or not, so if not, we'll wrap our forward + // reference in quotes. + // We have special logic here for checking if our thing is actually *in* + // our module, behond what we've already done, because our other logic will + // work for submodules, but this can't. + if (!forwardReferences && this.isInModule(innerType)) { + pythonType = pythonType.replace(re, `$1"${innerType}"$2`); } - } - private toPythonCollection(ref: spec.CollectionTypeReference): string { - const elementPythonType = this.toPythonType(ref.collection.elementtype, { optional: false }); - switch (ref.collection.kind) { - case spec.CollectionKind.Array: return `typing.List[${elementPythonType}]`; - case spec.CollectionKind.Map: return `typing.Mapping[str,${elementPythonType}]`; - default: - throw new Error(`Unsupported collection kind: ${ref.collection.kind}`); - } + // Now that we've gotten forward references out of the way, we will want + // to replace the entire type string, with just the type portion. + pythonType = pythonType.replace(re, `$1${typeName}$2`); + } } - private toPythonFQN(fqn: string): string { - const [assemblyName, ...qualifiedIdentifiers] = fqn.split("."); - const fqnParts: string[] = [this.findModule(assemblyName).targets!.python!.module]; - - for (const part of qualifiedIdentifiers) { - fqnParts.push(toPythonIdentifier(part)); - } + return pythonType; + } - return fqnParts.join("."); - } -} - -class PythonGenerator extends Generator { - private package: Package; - private types: Map; - - constructor(options: GeneratorOptions = {}) { - super(options); - - this.code.openBlockFormatter = s => `${s}:`; - this.code.closeBlockFormatter = _s => ""; - - this.types = new Map(); - } - - public getPythonType(fqn: string): PythonType { - const type = this.types.get(fqn); - - if (type === undefined) { - throw new Error(`Could not locate type: "${fqn}"`); - } + private toPythonType(typeRef: spec.TypeReference, opts: { optional: boolean }): string { + let pythonType: string; - return type; - } - - protected getAssemblyOutputDir(assm: spec.Assembly) { - return path.join("src", pythonModuleNameToFilename(this.getAssemblyModuleName(assm))); - } - - protected onBeginAssembly(assm: spec.Assembly, _fingerprint: boolean) { - this.package = new Package( - assm.targets!.python!.distName, - assm.version, - assm, - ); - - const assemblyModule = new Module( - this.getAssemblyModuleName(assm), - null, - { assembly: assm, - assemblyFilename: this.getAssemblyFileName(), - loadAssembly: false }, - ); - - this.package.addModule(assemblyModule); - this.package.addData(assemblyModule, this.getAssemblyFileName(), null); - } - - protected onEndAssembly(_assm: spec.Assembly, _fingerprint: boolean) { - const resolver = new TypeResolver( - this.types, - (fqn: string) => this.findModule(fqn), - (fqn: string) => this.findType(fqn), - ); - this.package.write(this.code, resolver); + // Get the underlying python type. + if (spec.isPrimitiveTypeReference(typeRef)) { + pythonType = this.toPythonPrimitive(typeRef.primitive); + } else if (spec.isCollectionTypeReference(typeRef)) { + pythonType = this.toPythonCollection(typeRef); + } else if (spec.isNamedTypeReference(typeRef)) { + pythonType = this.toPythonFQN(typeRef.fqn); + } else if (typeRef.union) { + const types = new Array(); + for (const subtype of typeRef.union.types) { + types.push(this.toPythonType(subtype, opts)); + } + pythonType = `typing.Union[${types.join(', ')}]`; + } else { + throw new Error(`Invalid type reference: ${JSON.stringify(typeRef)}`); } - protected onBeginNamespace(ns: string) { - // If we're generating the Namespace that matches our assembly, then we'll - // actually be generating a module, otherwise we'll generate a class within - // that module. - if (ns === this.assembly.name) { - const module = new Module( - this.assembly.targets!.python!.module, - ns, - { assembly: this.assembly, - assemblyFilename: this.getAssemblyFileName(), - loadAssembly: ns === this.assembly.name }, - ); - - this.package.addModule(module); - // Add our py.typed marker to ensure that gradual typing works for this - // package. - this.package.addData(module, "py.typed", ""); - - this.types.set(ns, module); - } else { - // This should be temporary code, which can be removed and turned into an - // error case once https://github.com/aws/jsii/issues/270 and - // https://github.com/aws/jsii/issues/283 are solved. - this.addPythonType( - new Namespace( - this, - toPythonIdentifier(ns.replace(/^.+\.([^\.]+)$/, "$1")), - ns, - {}, - undefined, - ), - ); - } + // If our type is Optional, then we'll wrap our underlying type with typing.Optional + // However, if we're not respecting optionals, then we'll just skip over this. + // We explicitly don't emit this when our type is typing.Any, because typing.Any + // already implied that None is an accepted type. + // See: https://github.com/aws/jsii/issues/284 + if (opts.optional && pythonType !== 'typing.Any') { + pythonType = `typing.Optional[${pythonType}]`; } - protected onBeginClass(cls: spec.ClassType, abstract: boolean | undefined) { - const klass = new Class( - this, - toPythonIdentifier(cls.name), - cls.fqn, - { - abstract, - bases: (cls.base && [this.findType(cls.base)]) || [], - interfaces: cls.interfaces && cls.interfaces.map(base => this.findType(base)), - abstractBases: abstract ? this.getAbstractBases(cls) : [], - }, - cls.docs, - ); - - if (cls.initializer !== undefined) { - const { parameters = [] } = cls.initializer; - - klass.addMember( - new Initializer( - this, - "__init__", - undefined, - parameters, - undefined, - cls.initializer.docs, - { liftedProp: this.getliftedProp(cls.initializer), parent: cls }, - ) - ); - } - - this.addPythonType(klass); - } - - protected onStaticMethod(cls: spec.ClassType, method: spec.Method) { - const { parameters = [] } = method; - - this.getPythonType(cls.fqn).addMember( - new StaticMethod( - this, - toPythonMethodName(method.name!), - method.name, - parameters, - method.returns, - method.docs, - { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, - ) - ); - } - - protected onStaticProperty(cls: spec.ClassType, prop: spec.Property) { - this.getPythonType(cls.fqn).addMember( - new StaticProperty( - toPythonPropertyName(prop.name, prop.const), - prop.name, - prop, - prop.docs, - { abstract: prop.abstract, immutable: prop.immutable }, - ) - ); - } - - protected onMethod(cls: spec.ClassType, method: spec.Method) { - const { parameters = [] } = method; - - if (method.async) { - this.getPythonType(cls.fqn).addMember( - new AsyncMethod( - this, - toPythonMethodName(method.name!, method.protected), - method.name, - parameters, - method.returns, - method.docs, - { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, - ) - ); - } else { - this.getPythonType(cls.fqn).addMember( - new Method( - this, - toPythonMethodName(method.name!, method.protected), - method.name, - parameters, - method.returns, - method.docs, - { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, - ) - ); - } - } + return pythonType; + } - protected onProperty(cls: spec.ClassType, prop: spec.Property) { - this.getPythonType(cls.fqn).addMember( - new Property( - toPythonPropertyName(prop.name, prop.const, prop.protected), - prop.name, - prop, - prop.docs, - { abstract: prop.abstract, immutable: prop.immutable }, - ) - ); + private toPythonPrimitive(primitive: spec.PrimitiveType): string { + switch (primitive) { + case spec.PrimitiveType.Boolean: return 'bool'; + case spec.PrimitiveType.Date: return 'datetime.datetime'; + case spec.PrimitiveType.Json: return 'typing.Mapping[typing.Any, typing.Any]'; + case spec.PrimitiveType.Number: return 'jsii.Number'; + case spec.PrimitiveType.String: return 'str'; + case spec.PrimitiveType.Any: return 'typing.Any'; + default: + throw new Error(`Unknown primitive type: ${primitive}`); } + } - protected onUnionProperty(cls: spec.ClassType, prop: spec.Property, _union: spec.UnionTypeReference) { - this.onProperty(cls, prop); + private toPythonCollection(ref: spec.CollectionTypeReference): string { + const elementPythonType = this.toPythonType(ref.collection.elementtype, { optional: false }); + switch (ref.collection.kind) { + case spec.CollectionKind.Array: return `typing.List[${elementPythonType}]`; + case spec.CollectionKind.Map: return `typing.Mapping[str,${elementPythonType}]`; + default: + throw new Error(`Unsupported collection kind: ${ref.collection.kind}`); } + } - protected onBeginInterface(ifc: spec.InterfaceType) { - let iface: Interface | Struct; - - if (ifc.datatype) { - iface = new Struct( - this, - toPythonIdentifier(ifc.name), - ifc.fqn, - { bases: ifc.interfaces && ifc.interfaces.map(base => this.findType(base)) }, - ifc.docs, - ); - } else { - iface = new Interface( - this, - toPythonIdentifier(ifc.name), - ifc.fqn, - { bases: ifc.interfaces && ifc.interfaces.map(base => this.findType(base)) }, - ifc.docs, - ); - } + private toPythonFQN(fqn: string): string { + const [assemblyName, ...qualifiedIdentifiers] = fqn.split('.'); + const fqnParts: string[] = [this.findModule(assemblyName).targets!.python!.module]; - this.addPythonType(iface); + for (const part of qualifiedIdentifiers) { + fqnParts.push(toPythonIdentifier(part)); } - protected onEndInterface(_ifc: spec.InterfaceType) { return; } - - protected onInterfaceMethod(ifc: spec.InterfaceType, method: spec.Method) { - const { parameters = [] } = method; + return fqnParts.join('.'); + } +} - this.getPythonType(ifc.fqn).addMember( - new InterfaceMethod( - this, - toPythonMethodName(method.name!, method.protected), - method.name, - parameters, - method.returns, - method.docs, - { liftedProp: this.getliftedProp(method) }, - ) - ); +class PythonGenerator extends Generator { + private package: Package; + private readonly types: Map; + + public constructor(options: GeneratorOptions = {}) { + super(options); + + this.code.openBlockFormatter = s => `${s}:`; + this.code.closeBlockFormatter = _s => ''; + + this.types = new Map(); + } + + public getPythonType(fqn: string): PythonType { + const type = this.types.get(fqn); + + if (type === undefined) { + throw new Error(`Could not locate type: "${fqn}"`); + } + + return type; + } + + protected getAssemblyOutputDir(assm: spec.Assembly) { + return path.join('src', pythonModuleNameToFilename(this.getAssemblyModuleName(assm))); + } + + protected onBeginAssembly(assm: spec.Assembly, _fingerprint: boolean) { + this.package = new Package( + assm.targets!.python!.distName, + assm.version, + assm, + ); + + const assemblyModule = new Module( + this.getAssemblyModuleName(assm), + null, + { assembly: assm, + assemblyFilename: this.getAssemblyFileName(), + loadAssembly: false }, + ); + + this.package.addModule(assemblyModule); + this.package.addData(assemblyModule, this.getAssemblyFileName(), null); + } + + protected onEndAssembly(_assm: spec.Assembly, _fingerprint: boolean) { + const resolver = new TypeResolver( + this.types, + (fqn: string) => this.findModule(fqn), + (fqn: string) => this.findType(fqn), + ); + this.package.write(this.code, resolver); + } + + protected onBeginNamespace(ns: string) { + // If we're generating the Namespace that matches our assembly, then we'll + // actually be generating a module, otherwise we'll generate a class within + // that module. + if (ns === this.assembly.name) { + const module = new Module( + this.assembly.targets!.python!.module, + ns, + { assembly: this.assembly, + assemblyFilename: this.getAssemblyFileName(), + loadAssembly: ns === this.assembly.name }, + ); + + this.package.addModule(module); + // Add our py.typed marker to ensure that gradual typing works for this + // package. + this.package.addData(module, 'py.typed', ''); + + this.types.set(ns, module); + } else { + // This should be temporary code, which can be removed and turned into an + // error case once https://github.com/aws/jsii/issues/270 and + // https://github.com/aws/jsii/issues/283 are solved. + this.addPythonType( + new Namespace( + this, + toPythonIdentifier(ns.replace(/^.+\.([^.]+)$/, '$1')), + ns, + {}, + undefined, + ), + ); + } + } + + protected onBeginClass(cls: spec.ClassType, abstract: boolean | undefined) { + const klass = new Class( + this, + toPythonIdentifier(cls.name), + cls.fqn, + { + abstract, + bases: (cls.base && [this.findType(cls.base)]) || [], + interfaces: cls.interfaces && cls.interfaces.map(base => this.findType(base)), + abstractBases: abstract ? this.getAbstractBases(cls) : [], + }, + cls.docs, + ); + + if (cls.initializer !== undefined) { + const { parameters = [] } = cls.initializer; + + klass.addMember( + new Initializer( + this, + '__init__', + undefined, + parameters, + undefined, + cls.initializer.docs, + { liftedProp: this.getliftedProp(cls.initializer), parent: cls }, + ) + ); + } + + this.addPythonType(klass); + } + + protected onStaticMethod(cls: spec.ClassType, method: spec.Method) { + const { parameters = [] } = method; + + this.getPythonType(cls.fqn).addMember( + new StaticMethod( + this, + toPythonMethodName(method.name), + method.name, + parameters, + method.returns, + method.docs, + { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, + ) + ); + } + + protected onStaticProperty(cls: spec.ClassType, prop: spec.Property) { + this.getPythonType(cls.fqn).addMember( + new StaticProperty( + toPythonPropertyName(prop.name, prop.const), + prop.name, + prop, + prop.docs, + { abstract: prop.abstract, immutable: prop.immutable }, + ) + ); + } + + protected onMethod(cls: spec.ClassType, method: spec.Method) { + const { parameters = [] } = method; + + if (method.async) { + this.getPythonType(cls.fqn).addMember( + new AsyncMethod( + this, + toPythonMethodName(method.name, method.protected), + method.name, + parameters, + method.returns, + method.docs, + { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, + ) + ); + } else { + this.getPythonType(cls.fqn).addMember( + new Method( + this, + toPythonMethodName(method.name, method.protected), + method.name, + parameters, + method.returns, + method.docs, + { abstract: method.abstract, liftedProp: this.getliftedProp(method) }, + ) + ); + } + } + + protected onProperty(cls: spec.ClassType, prop: spec.Property) { + this.getPythonType(cls.fqn).addMember( + new Property( + toPythonPropertyName(prop.name, prop.const, prop.protected), + prop.name, + prop, + prop.docs, + { abstract: prop.abstract, immutable: prop.immutable }, + ) + ); + } + + protected onUnionProperty(cls: spec.ClassType, prop: spec.Property, _union: spec.UnionTypeReference) { + this.onProperty(cls, prop); + } + + protected onBeginInterface(ifc: spec.InterfaceType) { + let iface: Interface | Struct; + + if (ifc.datatype) { + iface = new Struct( + this, + toPythonIdentifier(ifc.name), + ifc.fqn, + { bases: ifc.interfaces && ifc.interfaces.map(base => this.findType(base)) }, + ifc.docs, + ); + } else { + iface = new Interface( + this, + toPythonIdentifier(ifc.name), + ifc.fqn, + { bases: ifc.interfaces && ifc.interfaces.map(base => this.findType(base)) }, + ifc.docs, + ); + } + + this.addPythonType(iface); + } + + protected onEndInterface(_ifc: spec.InterfaceType) { return; } + + protected onInterfaceMethod(ifc: spec.InterfaceType, method: spec.Method) { + const { parameters = [] } = method; + + this.getPythonType(ifc.fqn).addMember( + new InterfaceMethod( + this, + toPythonMethodName(method.name, method.protected), + method.name, + parameters, + method.returns, + method.docs, + { liftedProp: this.getliftedProp(method) }, + ) + ); + } + + protected onInterfaceProperty(ifc: spec.InterfaceType, prop: spec.Property) { + let ifaceProperty: InterfaceProperty | StructField; + + if (ifc.datatype) { + ifaceProperty = new StructField(prop); + } else { + ifaceProperty = new InterfaceProperty( + toPythonPropertyName(prop.name, prop.const, prop.protected), + prop.name, + prop, + prop.docs, + { immutable: prop.immutable }, + ); } - protected onInterfaceProperty(ifc: spec.InterfaceType, prop: spec.Property) { - let ifaceProperty: InterfaceProperty | StructField; + this.getPythonType(ifc.fqn).addMember(ifaceProperty); + } - if (ifc.datatype) { - ifaceProperty = new StructField(prop); - } else { - ifaceProperty = new InterfaceProperty( - toPythonPropertyName(prop.name, prop.const, prop.protected), - prop.name, - prop, - prop.docs, - { immutable: prop.immutable }, - ); - } + protected onBeginEnum(enm: spec.EnumType) { + this.addPythonType(new Enum(this, toPythonIdentifier(enm.name), enm.fqn, {}, enm.docs)); + } - this.getPythonType(ifc.fqn).addMember(ifaceProperty); - } + protected onEnumMember(enm: spec.EnumType, member: spec.EnumMember) { + this.getPythonType(enm.fqn).addMember( + new EnumMember( + toPythonIdentifier(member.name), + member.name, + member.docs, + ) + ); + } - protected onBeginEnum(enm: spec.EnumType) { - this.addPythonType(new Enum(this, toPythonIdentifier(enm.name), enm.fqn, {}, enm.docs)); - } + protected onInterfaceMethodOverload(_ifc: spec.InterfaceType, _overload: spec.Method, _originalMethod: spec.Method) { + throw new Error('Unhandled Type: InterfaceMethodOverload'); + } - protected onEnumMember(enm: spec.EnumType, member: spec.EnumMember) { - this.getPythonType(enm.fqn).addMember( - new EnumMember( - toPythonIdentifier(member.name), - member.name, - member.docs, - ) - ); - } + protected onMethodOverload(_cls: spec.ClassType, _overload: spec.Method, _originalMethod: spec.Method) { + throw new Error('Unhandled Type: MethodOverload'); + } - protected onInterfaceMethodOverload(_ifc: spec.InterfaceType, _overload: spec.Method, _originalMethod: spec.Method) { - throw new Error("Unhandled Type: InterfaceMethodOverload"); - } + protected onStaticMethodOverload(_cls: spec.ClassType, _overload: spec.Method, _originalMethod: spec.Method) { + throw new Error('Unhandled Type: StaticMethodOverload'); + } - protected onMethodOverload(_cls: spec.ClassType, _overload: spec.Method, _originalMethod: spec.Method) { - throw new Error("Unhandled Type: MethodOverload"); - } + private getAssemblyModuleName(assm: spec.Assembly): string { + return `${assm.targets!.python!.module}._jsii`; + } - protected onStaticMethodOverload(_cls: spec.ClassType, _overload: spec.Method, _originalMethod: spec.Method) { - throw new Error("Unhandled Type: StaticMethodOverload"); - } + private getParentFQN(fqn: string): string { + const m = /^(.+)\.[^.]+$/.exec(fqn); - private getAssemblyModuleName(assm: spec.Assembly): string { - return `${assm.targets!.python!.module}._jsii`; + if (m === null) { + throw new Error(`Could not determine parent FQN of: ${fqn}`); } - private getParentFQN(fqn: string): string { - const m = fqn.match(/^(.+)\.[^\.]+$/); + return m[1]; + } - if (m === null) { - throw new Error(`Could not determine parent FQN of: ${fqn}`); - } - - return m[1]; - } + private getParent(fqn: string): PythonType { + return this.getPythonType(this.getParentFQN(fqn)); + } - private getParent(fqn: string): PythonType { - return this.getPythonType(this.getParentFQN(fqn)); + private addPythonType(type: PythonType) { + if (type.fqn === null) { + throw new Error('Cannot add a Python type without a FQN.'); } - private addPythonType(type: PythonType) { - if (type.fqn === null) { - throw new Error("Cannot add a Python type without a FQN."); - } + this.getParent(type.fqn).addMember(type); + this.types.set(type.fqn, type); + } - this.getParent(type.fqn).addMember(type); - this.types.set(type.fqn, type); - } - - private getliftedProp(method: spec.Method | spec.Initializer): spec.InterfaceType | undefined { - // If there are parameters to this method, and if the last parameter's type is - // a datatype interface, then we want to lift the members of that last paramter - // as keyword arguments to this function. - if (method.parameters !== undefined && method.parameters.length >= 1) { - const lastParameter = method.parameters.slice(-1)[0]; - if (!lastParameter.variadic && spec.isNamedTypeReference(lastParameter.type)) { - const lastParameterType = this.findType(lastParameter.type.fqn); - if (spec.isInterfaceType(lastParameterType) && lastParameterType.datatype) { - return lastParameterType; - } - } + private getliftedProp(method: spec.Method | spec.Initializer): spec.InterfaceType | undefined { + // If there are parameters to this method, and if the last parameter's type is + // a datatype interface, then we want to lift the members of that last paramter + // as keyword arguments to this function. + if (method.parameters !== undefined && method.parameters.length >= 1) { + const lastParameter = method.parameters.slice(-1)[0]; + if (!lastParameter.variadic && spec.isNamedTypeReference(lastParameter.type)) { + const lastParameterType = this.findType(lastParameter.type.fqn); + if (spec.isInterfaceType(lastParameterType) && lastParameterType.datatype) { + return lastParameterType; } - - return undefined; + } } - private getAbstractBases(cls: spec.ClassType): spec.ClassType[] { - const abstractBases: spec.ClassType[] = []; + return undefined; + } - if (cls.base !== undefined) { - const base = this.findType(cls.base); + private getAbstractBases(cls: spec.ClassType): spec.ClassType[] { + const abstractBases: spec.ClassType[] = []; - if (!spec.isClassType(base)) { - throw new Error("Class inheritence that isn't a class?"); - } + if (cls.base !== undefined) { + const base = this.findType(cls.base); - if (base.abstract) { - abstractBases.push(base); - } - } + if (!spec.isClassType(base)) { + throw new Error("Class inheritence that isn't a class?"); + } - return abstractBases; + if (base.abstract) { + abstractBases.push(base); + } } + + return abstractBases; + } } /** * Positional argument or keyword parameter */ interface DocumentableArgument { - name: string; - docs?: spec.Docs; + name: string; + docs?: spec.Docs; } function emitDocString(code: CodeMaker, docs: spec.Docs | undefined, options: { - arguments?: DocumentableArgument[], - documentableItem?: string - } = {}) { - if ((!docs || Object.keys(docs).length === 0) && !options.arguments) { return; } - if (!docs) { docs = {}; } - - const lines = new Array(); - - if (docs.summary) { - lines.push(md2rst(docs.summary)); - brk(); + arguments?: DocumentableArgument[]; + documentableItem?: string; +} = {}) { + if ((!docs || Object.keys(docs).length === 0) && !options.arguments) { return; } + if (!docs) { docs = {}; } + + const lines = new Array(); + + if (docs.summary) { + lines.push(md2rst(docs.summary)); + brk(); + } else { + lines.push(''); + } + + function brk() { + if (lines.length > 0 && lines[lines.length - 1].trim() !== '') { lines.push(''); } + } + + function block(heading: string, content: string, doBrk = true) { + if (doBrk) { brk(); } + lines.push(heading); + const contentLines = md2rst(content).split('\n'); + if (contentLines.length <= 1) { + lines.push(`:${heading}: ${contentLines.join('')}`); } else { - lines.push(''); - } - - function brk() { - if (lines.length > 0 && lines[lines.length - 1].trim() !== '') { lines.push(''); } - } - - function block(heading: string, content: string, doBrk = true) { - if (doBrk) { brk(); } - lines.push(heading); - const contentLines = md2rst(content).split('\n'); - if (contentLines.length <= 1) { - lines.push(`:${heading}: ${contentLines.join('')}`); - } else { - lines.push(`:${heading}:`); - brk(); - for (const line of contentLines) { - lines.push(`${line}`); - } - } - if (doBrk) { brk(); } - } - - if (docs.remarks) { - brk(); - lines.push(...md2rst(convertSnippetsInMarkdown(docs.remarks || '', options.documentableItem || 'docstring')).split('\n')); - brk(); - } - - if (options.arguments && options.arguments.length > 0) { - brk(); - for (const param of options.arguments) { - // Add a line for every argument. Even if there is no description, we need - // the docstring so that the Sphinx extension can add the type annotations. - lines.push(`:param ${toPythonParameterName(param.name)}: ${onelineDescription(param.docs)}`); - } - brk(); - } - - if (docs.default) { block('default', docs.default); } - if (docs.returns) { block('return', docs.returns); } - if (docs.deprecated) { block('deprecated', docs.deprecated); } - if (docs.see) { block('see', docs.see, false); } - if (docs.stability && shouldMentionStability(docs.stability)) { block('stability', docs.stability, false); } - if (docs.subclassable) { block('subclassable', 'Yes'); } - - for (const [k, v] of Object.entries(docs.custom || {})) { - block(k + ':', v, false); - } - - if (docs.example) { - brk(); - lines.push('Example::'); - const exampleText = convertExample(docs.example, options.documentableItem || 'example'); - - for (const line of exampleText.split('\n')) { - lines.push(` ${line}`); - } - brk(); - } - - while (lines.length > 0 && lines[lines.length - 1] === '') { lines.pop(); } - - if (lines.length === 0) { return; } - - if (lines.length === 1) { - code.line(`"""${lines[0]}"""`); - return; - } - - code.line(`"""${lines[0]}`); - lines.splice(0, 1); - - for (const line of lines) { - code.line(line); - } - - code.line(`"""`); + lines.push(`:${heading}:`); + brk(); + for (const line of contentLines) { + lines.push(`${line}`); + } + } + if (doBrk) { brk(); } + } + + if (docs.remarks) { + brk(); + lines.push(...md2rst(convertSnippetsInMarkdown(docs.remarks || '', options.documentableItem || 'docstring')).split('\n')); + brk(); + } + + if (options.arguments && options.arguments.length > 0) { + brk(); + for (const param of options.arguments) { + // Add a line for every argument. Even if there is no description, we need + // the docstring so that the Sphinx extension can add the type annotations. + lines.push(`:param ${toPythonParameterName(param.name)}: ${onelineDescription(param.docs)}`); + } + brk(); + } + + if (docs.default) { block('default', docs.default); } + if (docs.returns) { block('return', docs.returns); } + if (docs.deprecated) { block('deprecated', docs.deprecated); } + if (docs.see) { block('see', docs.see, false); } + if (docs.stability && shouldMentionStability(docs.stability)) { block('stability', docs.stability, false); } + if (docs.subclassable) { block('subclassable', 'Yes'); } + + for (const [k, v] of Object.entries(docs.custom || {})) { + block(`${k}:`, v, false); + } + + if (docs.example) { + brk(); + lines.push('Example::'); + const exampleText = convertExample(docs.example, options.documentableItem || 'example'); + + for (const line of exampleText.split('\n')) { + lines.push(` ${line}`); + } + brk(); + } + + while (lines.length > 0 && lines[lines.length - 1] === '') { lines.pop(); } + + if (lines.length === 0) { return; } + + if (lines.length === 1) { + code.line(`"""${lines[0]}"""`); + return; + } + + code.line(`"""${lines[0]}`); + lines.splice(0, 1); + + for (const line of lines) { + code.line(line); + } + + code.line('"""'); } /** * Render a one-line description of the given docs, used for method arguments and inlined properties */ function onelineDescription(docs: spec.Docs | undefined) { - // Only consider a subset of fields here, we don't have a lot of formatting space - if (!docs) { return '-'; } - - const parts = []; - if (docs.summary) { parts.push(md2rst(docs.summary)); } - if (docs.remarks) { parts.push(md2rst(docs.remarks)); } - if (docs.default) { parts.push(`Default: ${md2rst(docs.default)}`); } - return parts.join(' ').replace(/\s+/g, ' '); + // Only consider a subset of fields here, we don't have a lot of formatting space + if (!docs) { return '-'; } + + const parts = []; + if (docs.summary) { parts.push(md2rst(docs.summary)); } + if (docs.remarks) { parts.push(md2rst(docs.remarks)); } + if (docs.default) { parts.push(`Default: ${md2rst(docs.default)}`); } + return parts.join(' ').replace(/\s+/g, ' '); } function shouldMentionStability(s: Stability) { - return s === Stability.Deprecated || s === Stability.Experimental; + return s === Stability.Deprecated || s === Stability.Experimental; } function isStruct(typeSystem: reflect.TypeSystem, ref: spec.TypeReference): boolean { - if (!spec.isNamedTypeReference(ref)) { return false; } - const type = typeSystem.tryFindFqn(ref.fqn); - return type !== undefined && type.isInterfaceType() && type.isDataType(); + if (!spec.isNamedTypeReference(ref)) { return false; } + const type = typeSystem.tryFindFqn(ref.fqn); + return type !== undefined && type.isInterfaceType() && type.isDataType(); } const pythonTranslator = new sampiler.PythonVisitor({ - disclaimer: 'Example may have issues. See https://github.com/aws/jsii/issues/826' + disclaimer: 'Example may have issues. See https://github.com/aws/jsii/issues/826' }); function convertExample(example: string, filename: string): string { - const source = new sampiler.LiteralSource(example, filename); - const result = sampiler.translateTypeScript(source, pythonTranslator); - sampiler.printDiagnostics(result.diagnostics, process.stderr); - return sampiler.renderTree(result.tree); + const source = new sampiler.LiteralSource(example, filename); + const result = sampiler.translateTypeScript(source, pythonTranslator); + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); } function convertSnippetsInMarkdown(markdown: string, filename: string): string { - const source = new sampiler.LiteralSource(markdown, filename); - const result = sampiler.translateMarkdown(source, pythonTranslator, { - languageIdentifier: 'python' - }); - // FIXME: This should translate into an exit code somehow - sampiler.printDiagnostics(result.diagnostics, process.stderr); - return sampiler.renderTree(result.tree); + const source = new sampiler.LiteralSource(markdown, filename); + const result = sampiler.translateMarkdown(source, pythonTranslator, { + languageIdentifier: 'python' + }); + // FIXME: This should translate into an exit code somehow + sampiler.printDiagnostics(result.diagnostics, process.stderr); + return sampiler.renderTree(result.tree); } \ No newline at end of file