From 1a37faceb1aa6de533e94b2ce303beb452fecc32 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Wed, 19 Sep 2018 18:52:15 +0200 Subject: [PATCH 01/11] Add new dependencies to vscode-dotty --- vscode-dotty/package-lock.json | 957 +++++++++++++++++++-------------- vscode-dotty/package.json | 10 +- 2 files changed, 548 insertions(+), 419 deletions(-) diff --git a/vscode-dotty/package-lock.json b/vscode-dotty/package-lock.json index 3c0d58df9fb6..5965899e6c22 100644 --- a/vscode-dotty/package-lock.json +++ b/vscode-dotty/package-lock.json @@ -4,12 +4,59 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/archiver": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-2.1.2.tgz", + "integrity": "sha512-UGcGgeMoGpFh97pQkzR+cgSrJDjVmO+CZ2N+WDI7i0QCOJE+PocpfHEEtePhlttULdbfOrzNi0yexg66E52Prw==", + "dev": true, + "requires": { + "@types/glob": "*" + } + }, + "@types/caseless": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", + "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==", + "dev": true + }, "@types/compare-versions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/compare-versions/-/compare-versions-3.0.0.tgz", "integrity": "sha512-HNXtUQQuW3ThO9DVfTNbdvClVr+8AZlNNa2pxk5qtEvObnT27qh0DdQXTN4h5PuTTGinxwXkRKXsllJxuAzGPw==", "dev": true }, + "@types/events": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/mocha": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", @@ -17,16 +64,43 @@ "dev": true }, "@types/node": { - "version": "8.10.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.32.tgz", - "integrity": "sha512-8OfXpkB3E0jhpcpyVlqJDV5mkXlrsJrDZR7q0uss8SBdW8IxNdx/J2o5m7cM2qbFzyd/o+aV5Z4OJcIukI6UlA==", + "version": "8.10.36", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.36.tgz", + "integrity": "sha512-SL6KhfM7PTqiFmbCW3eVNwVBZ+88Mrzbuvn9olPsfv43mbiWaFY+nRcz/TGGku0/lc2FepdMbImdMY1JrQ+zbw==", "dev": true }, + "@types/request": { + "version": "2.48.0", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.0.tgz", + "integrity": "sha512-KnfoOtqXKllSqfXSEvGTd8KDkNlpHs+PWr6I6XiEIWk/jckH3pNmWDXNFZyPkB9wApb8vzDq2wMByM/0GFSmXg==", + "dev": true, + "requires": { + "@types/caseless": "*", + "@types/form-data": "*", + "@types/node": "*", + "@types/tough-cookie": "*" + } + }, + "@types/tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ==", + "dev": true + }, + "@types/ws": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.1.tgz", + "integrity": "sha512-EzH8k1gyZ4xih/MaZTXwT2xOkPiIMSrhQ9b8wrlX88L0T02eYsddatQlwVFlEPyEqV0ChpdpNnE51QPH6NVT4Q==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/node": "*" + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", @@ -58,6 +132,39 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "archiver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.0.0.tgz", + "integrity": "sha512-5QeR6Xc5hSA9X1rbQfcuQ6VZuUXOaEdB65Dhmk9duuRJHYif/ZyJfuyJqsQrj34PFjU5emv5/MmfgA8un06onw==", + "requires": { + "archiver-utils": "^2.0.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^2.0.1" + } + }, + "archiver-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.0.0.tgz", + "integrity": "sha512-JRBgcVvDX4Mwu2RBF8bBaHcQCSxab7afsxAPYDQ5W+19quIPP5CfKE7Ql+UHs9wYvwsaNR8oDuhtf5iqrKmzww==", + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash.assign": "^4.2.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.toarray": "^4.4.0", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, "arr-diff": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", @@ -123,7 +230,6 @@ "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" } @@ -131,37 +237,63 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "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=" }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "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, - "optional": true, "requires": { "tweetnacl": "^0.14.3" } }, + "bl": { + "version": "1.2.2", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -175,7 +307,6 @@ "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" @@ -198,11 +329,38 @@ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffer-from": { "version": "1.1.1", @@ -210,6 +368,11 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "clone": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", @@ -242,14 +405,12 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { "delayed-stream": "~1.0.0" } @@ -265,39 +426,69 @@ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==" }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, "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 + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "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" + } }, "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 + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } }, "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" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "debug": { @@ -321,8 +512,7 @@ "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 + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "diff": { "version": "3.3.1", @@ -332,14 +522,14 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -352,8 +542,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "optional": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -363,7 +551,6 @@ "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" } @@ -375,18 +562,19 @@ "dev": true }, "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz", + "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==", "dev": true, "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" + "duplexer": "^0.1.1", + "flatmap-stream": "^0.1.0", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" } }, "expand-brackets": { @@ -410,8 +598,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "1.1.4", @@ -442,20 +629,17 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "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 + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fd-slicer": { "version": "1.1.0", @@ -491,6 +675,12 @@ "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", "dev": true }, + "flatmap-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz", + "integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -509,8 +699,17 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "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==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } }, "from": { "version": "0.1.7", @@ -518,11 +717,15 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { "version": "1.0.11", @@ -540,24 +743,14 @@ "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" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -650,7 +843,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -681,8 +874,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "growl": { "version": "1.10.3", @@ -730,7 +922,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -849,6 +1041,44 @@ "vinyl-fs": "^2.4.3" } }, + "gulp-untar": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz", + "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==", + "dev": true, + "requires": { + "event-stream": "~3.3.4", + "streamifier": "~0.1.1", + "tar": "^2.2.1", + "through2": "~2.0.3", + "vinyl": "^1.2.0" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, "gulp-vinyl-zip": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", @@ -904,8 +1134,16 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } }, "has-flag": { "version": "2.0.0", @@ -919,11 +1157,25 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, "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" @@ -932,8 +1184,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "is": { "version": "3.2.1", @@ -1005,7 +1256,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -1030,8 +1281,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", @@ -1048,8 +1298,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isobject": { "version": "2.1.0", @@ -1063,27 +1312,22 @@ "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 + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stable-stringify": { "version": "1.0.1", @@ -1097,8 +1341,7 @@ "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 + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsonify": { "version": "0.0.0", @@ -1110,7 +1353,6 @@ "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", @@ -1120,7 +1362,7 @@ }, "kind-of": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, @@ -1128,21 +1370,60 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, "requires": { "readable-stream": "^2.0.5" } }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, "math-random": { @@ -1213,42 +1494,48 @@ "requires": { "is-buffer": "^1.1.5" } + }, + "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" + } } } }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", - "dev": true + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", - "dev": true, + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "requires": { - "mime-db": "~1.36.0" + "mime-db": "~1.37.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": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -1317,13 +1604,14 @@ } }, "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" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -1345,7 +1633,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -1398,12 +1685,11 @@ "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 + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -1419,8 +1705,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "plugin-error": { "version": "0.1.2", @@ -1444,8 +1729,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "promisify-child-process": { "version": "2.1.2", @@ -1456,22 +1740,31 @@ }, "dependencies": { "@types/node": { - "version": "10.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.6.tgz", - "integrity": "sha512-fnA7yvqg3oKQDb3skBif9w5RRKVKAaeKeNuLzZL37XcSiWL4IoSXQnnbchR3UnBu2EMLHBip7ZVEkqoIVBP8QQ==" + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", + "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==" } } }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", "dev": true }, "queue": { @@ -1484,9 +1777,9 @@ } }, "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { "is-number": "^4.0.0", @@ -1510,9 +1803,8 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1535,8 +1827,7 @@ "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 + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.3", @@ -1557,171 +1848,30 @@ "dev": true }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", - "dev": true, + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", + "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.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "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 - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - } - } - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, - "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" - } - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "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" - } - } + "uuid": "^3.3.2" } }, "requires-port": { @@ -1742,19 +1892,17 @@ "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 + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "source-map": { "version": "0.6.1", @@ -1773,19 +1921,18 @@ } }, "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { "through": "2" } }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -1796,14 +1943,6 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "stat-mode": { @@ -1813,12 +1952,13 @@ "dev": true }, "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "version": "0.2.2", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", "dev": true, "requires": { - "duplexer": "~0.1.1" + "duplexer": "~0.1.1", + "through": "~2.3.4" } }, "stream-shift": { @@ -1846,17 +1986,10 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -1896,9 +2029,23 @@ "inherits": "2" } }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -1942,12 +2089,32 @@ } } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "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==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "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, - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "typescript": { "version": "2.9.2", @@ -1978,14 +2145,12 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "vali-date": { "version": "1.0.0", @@ -1997,19 +2162,10 @@ "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" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "vinyl": { @@ -2102,44 +2258,6 @@ "source-map-support": "^0.5.0", "url-parse": "^1.4.3", "vinyl-source-stream": "^1.1.0" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "gulp-untar": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz", - "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==", - "dev": true, - "requires": { - "event-stream": "~3.3.4", - "streamifier": "~0.1.1", - "tar": "^2.2.1", - "through2": "~2.0.3", - "vinyl": "^1.2.0" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } } }, "vscode-jsonrpc": { @@ -2148,9 +2266,9 @@ "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==" }, "vscode-languageclient": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.1.0.tgz", - "integrity": "sha512-Z95Kps8UqD4o17HE3uCkZuvenOsxHVH46dKmaGVpGixEFZigPaVuVxLM/JWeIY9aRenoC0ZD9CK1O7L4jpffKg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.1.1.tgz", + "integrity": "sha512-jMxshi+BPRQFNG8GB00dJv7ldqMda0be26laYYll/udtJuHbog6RqK10GSxHWDN0PgY0b0m5fePyTk3bq8a0TA==", "requires": { "semver": "^5.5.0", "vscode-languageserver-protocol": "3.13.0" @@ -2163,17 +2281,6 @@ "requires": { "vscode-languageserver-protocol": "3.13.0", "vscode-uri": "^1.0.6" - }, - "dependencies": { - "vscode-languageserver-protocol": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.13.0.tgz", - "integrity": "sha512-2ZGKwI+P2ovQll2PGAp+2UfJH+FK9eait86VBUdkPd9HRlm8e58aYT9pV/NYanHOcp3pL6x2yTLVCFMcTer0mg==", - "requires": { - "vscode-jsonrpc": "^4.0.0", - "vscode-languageserver-types": "3.13.0" - } - } } }, "vscode-languageserver-protocol": { @@ -2198,14 +2305,20 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz", + "integrity": "sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg==", + "requires": { + "async-limiter": "~1.0.0" + } }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "yauzl": { "version": "2.10.0", @@ -2225,6 +2338,16 @@ "requires": { "buffer-crc32": "~0.2.3" } + }, + "zip-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.0.1.tgz", + "integrity": "sha512-c+eUhhkDpaK87G/py74wvWLtz2kzMPNCCkUApkun50ssE0oQliIQzWpTnwjB+MTKVIf2tGzIgHyqW/Y+W77ecQ==", + "requires": { + "archiver-utils": "^2.0.0", + "compress-commons": "^1.2.0", + "readable-stream": "^2.0.0" + } } } } diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index 3d76a617f466..07f806c23d9e 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -11,7 +11,7 @@ }, "icon": "images/dotty-logo.png", "engines": { - "vscode": "^1.27.0" + "vscode": "^1.27.1" }, "categories": [ "Languages" @@ -88,12 +88,18 @@ "compare-versions": "^3.4.0", "vscode-languageclient": "^5.1.0", "vscode-languageserver": "^5.1.0", - "vscode-jsonrpc": "4.0.0" + "vscode-jsonrpc": "4.0.0", + "ws": "^6.0.0", + "archiver": "^3.0.0", + "request": "^2.88.0" }, "devDependencies": { "@types/compare-versions": "^3.0.0", "@types/mocha": "^5.2.5", "@types/node": "^8.10.32", + "@types/ws": "^6.0.0", + "@types/archiver": "^2.1.2", + "@types/request": "^2.47.1", "typescript": "^2.9.2", "vscode": "^1.1.21" } From f48a19c05c27c7119e775c74faf4dc000c730784 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Wed, 19 Sep 2018 18:52:35 +0200 Subject: [PATCH 02/11] Implement LSP tracing for vscode-dotty --- vscode-dotty/package.json | 8 + vscode-dotty/src/extension.ts | 19 +- vscode-dotty/src/tracer.ts | 281 ++++++++++++++++++++++++++++ vscode-dotty/src/tracing-consent.ts | 27 +++ 4 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 vscode-dotty/src/tracer.ts create mode 100644 vscode-dotty/src/tracing-consent.ts diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index 07f806c23d9e..b61925a5535a 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -48,6 +48,14 @@ "type": "boolean", "default": true, "description": "If true, saving a worksheet will also run it." + }, + "dotty.tracing.machineId": { + "type": [ + "string", + "null" + ], + "default": null, + "description": "ID of your machine used when Dotty Language Server tracing is turned on." } } }, diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index 4c42966243cc..3fcac9cd356a 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -19,9 +19,14 @@ export let client: LanguageClient import * as rpc from 'vscode-jsonrpc' import * as sbtserver from './sbt-server' +import { Tracer } from './tracer'; + +const extensionName = 'dotty'; +const extensionConfig = vscode.workspace.getConfiguration(extensionName); let extensionContext: ExtensionContext let outputChannel: vscode.OutputChannel +let tracer: Tracer; /** The sbt process that may have been started by this extension */ let sbtProcess: ChildProcess | undefined @@ -46,6 +51,11 @@ function isConfiguredProject() { export function activate(context: ExtensionContext) { extensionContext = context outputChannel = vscode.window.createOutputChannel("Dotty"); + tracer = new Tracer({ + extensionContext, + extensionConfig, + extensionOut: outputChannel, + }) const coursierPath = path.join(extensionContext.extensionPath, "out", "coursier"); const dottyPluginSbtFileSource = path.join(extensionContext.extensionPath, "out", "dotty-plugin.sbt") @@ -297,6 +307,10 @@ function bootstrapSbtProject(buildSbtFileSource: string, } function run(serverOptions: ServerOptions, isOldServer: boolean) { + + tracer.initializeAsyncWorkspaceDump(); + const tracingOutputChannel = tracer.createLspOutputChannel(); + const clientOptions: LanguageClientOptions = { documentSelector: [ { scheme: 'file', pattern: '**/*.sc' }, @@ -307,11 +321,11 @@ function run(serverOptions: ServerOptions, isOldServer: boolean) { synchronize: { configurationSection: 'dotty' }, - outputChannel: outputChannel, + outputChannel: tracingOutputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never } - client = new LanguageClient("dotty", "Dotty", serverOptions, clientOptions) + client = new LanguageClient(extensionName, "Dotty", serverOptions, clientOptions) client.registerFeature(new features.WorksheetRunFeature(client)) if (isOldServer) @@ -320,4 +334,5 @@ function run(serverOptions: ServerOptions, isOldServer: boolean) { // Push the disposable to the context's subscriptions so that the // client can be deactivated on extension deactivation extensionContext.subscriptions.push(client.start()) + if (tracingOutputChannel) extensionContext.subscriptions.push(tracingOutputChannel); } diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts new file mode 100644 index 000000000000..f8d1c7a2a3ac --- /dev/null +++ b/vscode-dotty/src/tracer.ts @@ -0,0 +1,281 @@ +import * as vscode from 'vscode'; + +import * as fs from 'fs'; +import * as path from 'path'; + +import * as archiver from 'archiver'; +import * as WebSocket from 'ws'; +import * as request from 'request'; + +import { TracingConsentCache } from './tracing-consent'; + +export interface Ctx { + readonly extensionContext: vscode.ExtensionContext, + readonly extensionConfig: vscode.WorkspaceConfiguration, + readonly extensionOut: vscode.OutputChannel +} + +export class Tracer { + private readonly ctx: Ctx + + private projectId: string + private machineId: string + private sessionId: string + + private tracingConsent: TracingConsentCache + + private remoteTracingUrl?: string + + constructor(ctx: Ctx) { + this.ctx = ctx; + + this.tracingConsent = new TracingConsentCache(ctx.extensionContext.workspaceState); + + this.machineId = (() => { + const machineIdKey = 'tracing.machineId'; + function persisted(value: string): string { + ctx.extensionConfig.update(machineIdKey, value, vscode.ConfigurationTarget.Global) + return value + } + + const machineId = ctx.extensionConfig.get(machineIdKey) + if (machineId != null) return machineId; + + // vscode.env.machineId is a dummy value if telemetry is off - cannot be used + const vscodeMachineId = vscode.workspace.getConfiguration().get('telemetry.machineId') + if (vscodeMachineId !== undefined) return persisted(vscodeMachineId) + + function uuidv4() { + // https://stackoverflow.com/a/2117523 + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + + return persisted(uuidv4()) + })(); + + this.projectId = vscode.workspace.name !== undefined ? vscode.workspace.name : 'no-project'; + this.sessionId = new Date().toISOString(); + } + + initializeAsyncWorkspaceDump() { + const remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl'); + if (remoteWorkspaceDumpUrl === undefined) return; + + try { + this.asyncUploadWorkspaceDump(remoteWorkspaceDumpUrl); + } catch (err) { + this.logError('error during workspace dump', safeError(err)); + } + } + + createLspOutputChannel(): vscode.OutputChannel | undefined { + const remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl'); + if (!remoteTracingUrl) return undefined; + + if (this.tracingConsent.get() === 'no-answer') { + vscode.window.showInformationMessage( + 'Do you want to help EPFL develop this plugin by uploading your usage data? ' + + 'PLEASE BE AWARE that this will upload all of your keystrokes and all of your code, ' + + 'among other things.', + 'yes', 'no' + ).then((value: string | undefined) => { + if (value === 'yes' || value === 'no') this.tracingConsent.set(value); + }); + } + + const localLspOutputChannel = vscode.window.createOutputChannel('Dotty LSP Communication') + try { + return this.createRemoteLspOutputChannel(remoteTracingUrl, localLspOutputChannel); + } catch (err) { + this.logError('error during remote output channel creation', safeError(err)); + return localLspOutputChannel; + } + } + + private asyncUploadWorkspaceDump(url: string) { + const storagePath = this.ctx.extensionContext.storagePath; + const rootPath = vscode.workspace.rootPath; + if (storagePath === undefined || rootPath === undefined) { + this.logError('Cannot start workspace dump b/c of workspace state:', { storagePath, rootPath }); + return; + } + + if (!fs.existsSync(storagePath)) fs.mkdirSync(storagePath); + const outputPath = path.join(storagePath, 'workspace-dump.zip'); + if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath); + let output = fs.createWriteStream(outputPath); + output.on('end', () => { + this.ctx.extensionOut.appendLine('zip - data has been drained'); + }); + + const zip = archiver('zip'); + zip.on('error', (err) => this.logError('zip error', safeError(err))); + zip.on('warning', (err) => this.logError('zip warning', safeError(err))); + zip.on('entry', (entry) => { + this.ctx.extensionOut.appendLine(`zip - entry: ${entry.name}`); + }); + zip.on('finish', () => { + this.ctx.extensionOut.appendLine('zip - finished'); + fs.createReadStream(outputPath).pipe( + request.put(url, { + qs: { + client: this.machineId, + project: this.projectId, + session: this.sessionId + } + }) + .on('error', (err) => this.logError('zip upload connection error', url, safeError(err))) + .on('complete', (resp) => { + if (!(resp.statusCode >= 200 && resp.statusCode < 300)) { + this.logError('zip upload http error', url, resp.statusCode, resp.body); + } else { + this.ctx.extensionOut.appendLine('zip - http upload finished'); + } + }) + ); + }); + zip.pipe(output); + zip.glob('./**/*.{scala,sbt}', { cwd: rootPath }); + zip.finalize(); + } + + private createRemoteLspOutputChannel( + remoteTracingUrl: string, + localOutputChannel: vscode.OutputChannel + ): vscode.OutputChannel { + const socketHeaders = { + 'X-DLS-Project-ID': this.projectId, + 'X-DLS-Client-ID': this.machineId, + 'X-DLS-Session-ID': this.sessionId, + }; + + const socket = new WebSocket(remoteTracingUrl, { headers: socketHeaders }); + + const timer = setInterval( + () => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(''); + } else if (socket.readyState === WebSocket.CLOSED) { + clearInterval(timer); + } + }, + 10 * 1000 /*ms*/, + ) + + socket.onerror = (event) => { + this.logErrorWithoutNotifying( + 'socket error', + remoteTracingUrl, + new SafeJsonifier(event, (event) => ({ + error: safeError(event.error), + message: event.message, + type: event.type + })) + ); + vscode.window.showWarningMessage('An error occured in Dotty LSP remote tracing connection.'); + } + + socket.onclose = (event) => { + this.logErrorWithoutNotifying( + 'socket closed', + remoteTracingUrl, + new SafeJsonifier(event, (event) => ({ + wasClean: event.wasClean, + code: event.code, + reason: event.reason + })) + ); + vscode.window.showWarningMessage('Dotty LSP remote tracing connection was dropped.'); + } + + let log: string = ''; + return { + name: 'websocket', + + append: (value: string) => { + localOutputChannel.append(value); + if (this.tracingConsent.get() === 'no') return; + log += value; + }, + + appendLine: (value: string) => { + localOutputChannel.appendLine(value) + if (this.tracingConsent.get() === 'no') { + log = ''; + return; + } + + log += value; + log += '\n'; + if (this.tracingConsent.get() === 'yes' && socket.readyState === WebSocket.OPEN) { + socket.send(log, (err) => { + if (err) { + this.logError('socket send error', err) + } + }); + log = ''; + } + }, + + clear() { }, + show() { }, + hide() { }, + dispose() { + socket.close(); + localOutputChannel.dispose(); + } + }; + } + + private silenceErrors: boolean = false; + private logErrorWithoutNotifying(message: string, ...rest: any[]) { + const msg = `[Dotty LSP Tracer] ${message}`; + // unwrap SafeJsonifier, for some reason Electron logs the result + // of .toJSON, unlike browsers + console.error(msg, ...rest.map((a) => a instanceof SafeJsonifier ? a.value : a)); + function cautiousStringify(a: any): string { + try { + return JSON.stringify(a, undefined, 4); + } catch (err) { + console.error('cannot stringify', err, a); + return a.toString(); + } + } + this.ctx.extensionOut.appendLine([msg].concat(rest.map(cautiousStringify)).join(' ')); + } + private logError(message: string, ...rest: any[]) { + this.logErrorWithoutNotifying(message, ...rest); + if (!this.silenceErrors) { + vscode.window.showErrorMessage( + 'An error occured which prevents sending usage data to EPFL. ' + + 'Please copy the text from "Dotty Language Client" output (View > Output) and send it to your TA.', + 'Silence further errors' + ).then((result) => { + if (result !== undefined) { + this.silenceErrors = true; + } + }) + } + } +} + +function safeError(e: Error): SafeJsonifier { + return new SafeJsonifier(e, (e) => e.toString()); +} + +class SafeJsonifier { + value: T + valueToObject: (t: T) => {} + + constructor(value: T, valueToObject: (t: T) => {}) { + this.value = value; + this.valueToObject = valueToObject; + } + + toJSON() { + return this.valueToObject(this.value); + } +} diff --git a/vscode-dotty/src/tracing-consent.ts b/vscode-dotty/src/tracing-consent.ts new file mode 100644 index 000000000000..d4ba4008292f --- /dev/null +++ b/vscode-dotty/src/tracing-consent.ts @@ -0,0 +1,27 @@ +import { Memento } from 'vscode'; + +export type TracingConsent = 'yes' | 'no' | 'no-answer'; + +export class TracingConsentCache { + private readonly workspaceState: Memento + + private cache?: TracingConsent + + constructor(workspaceState: Memento) { + this.workspaceState = workspaceState; + } + + get(): TracingConsent { + if (this.cache !== undefined) return this.cache; + const setting = this.workspaceState.get('remote-tracing-consent'); + this.cache = setting === undefined ? 'no-answer' + : setting ? 'yes' + : 'no'; + return this.cache; + } + + set(value: 'yes' | 'no'): void { + this.workspaceState.update('remote-tracing-consent', value === 'yes'); + this.cache = value; + } +} From 120a45d5e3010a06dbd92874a7885607311feefe Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Fri, 12 Oct 2018 15:48:31 +0200 Subject: [PATCH 03/11] VsCode plugin: review adjustments An item in status bar now shows tracing status and can be clicked to adjust consent. Tracing and workspace dump now take into account that consent can be given/revoked - workspace dump is only initialized after consent is given, tracing socket is only created lazily as necessary. --- vscode-dotty/src/extension.ts | 8 +- vscode-dotty/src/tracer.ts | 228 +++++++++++++++++++--------- vscode-dotty/src/tracing-consent.ts | 7 + 3 files changed, 166 insertions(+), 77 deletions(-) diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index 3fcac9cd356a..3c9f82ed8501 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -21,7 +21,7 @@ import * as rpc from 'vscode-jsonrpc' import * as sbtserver from './sbt-server' import { Tracer } from './tracer'; -const extensionName = 'dotty'; +export const extensionName = 'dotty'; const extensionConfig = vscode.workspace.getConfiguration(extensionName); let extensionContext: ExtensionContext @@ -308,8 +308,7 @@ function bootstrapSbtProject(buildSbtFileSource: string, function run(serverOptions: ServerOptions, isOldServer: boolean) { - tracer.initializeAsyncWorkspaceDump(); - const tracingOutputChannel = tracer.createLspOutputChannel(); + const { lspOutputChannel } = tracer.run(); const clientOptions: LanguageClientOptions = { documentSelector: [ @@ -321,7 +320,7 @@ function run(serverOptions: ServerOptions, isOldServer: boolean) { synchronize: { configurationSection: 'dotty' }, - outputChannel: tracingOutputChannel, + outputChannel: lspOutputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never } @@ -334,5 +333,4 @@ function run(serverOptions: ServerOptions, isOldServer: boolean) { // Push the disposable to the context's subscriptions so that the // client can be deactivated on extension deactivation extensionContext.subscriptions.push(client.start()) - if (tracingOutputChannel) extensionContext.subscriptions.push(tracingOutputChannel); } diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index f8d1c7a2a3ac..264244e6aaca 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -7,8 +7,11 @@ import * as archiver from 'archiver'; import * as WebSocket from 'ws'; import * as request from 'request'; +import { extensionName } from './extension'; import { TracingConsentCache } from './tracing-consent'; +const consentCommandName = `${extensionName}.adjust-consent`; + export interface Ctx { readonly extensionContext: vscode.ExtensionContext, readonly extensionConfig: vscode.WorkspaceConfiguration, @@ -24,13 +27,20 @@ export class Tracer { private tracingConsent: TracingConsentCache - private remoteTracingUrl?: string + private readonly remoteTracingUrl: string | undefined + private readonly remoteWorkspaceDumpUrl: string | undefined + private get isTracingEnabled(): boolean { + return Boolean(this.remoteWorkspaceDumpUrl || this.remoteTracingUrl); + } constructor(ctx: Ctx) { this.ctx = ctx; this.tracingConsent = new TracingConsentCache(ctx.extensionContext.workspaceState); + this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl'); + this.remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl'); + this.machineId = (() => { const machineIdKey = 'tracing.machineId'; function persisted(value: string): string { @@ -60,35 +70,82 @@ export class Tracer { this.sessionId = new Date().toISOString(); } - initializeAsyncWorkspaceDump() { - const remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl'); - if (remoteWorkspaceDumpUrl === undefined) return; + run(): { lspOutputChannel?: vscode.OutputChannel } { + const consentCommandDisposable = vscode.commands.registerCommand(consentCommandName, () => this.askForTracingConsent()); + if (this.isTracingEnabled && this.tracingConsent.get() === 'no-answer') this.askForTracingConsent(); + this.initializeAsyncWorkspaceDump(); + const lspOutputChannel = this.createLspOutputChannel(); + const statusBarItem = this.createStatusBarItem(); + for (const disposable of [consentCommandDisposable, lspOutputChannel, statusBarItem]) { + if (disposable) this.ctx.extensionContext.subscriptions.push(disposable); + } + return { lspOutputChannel }; + } + + private askForTracingConsent(): void { + vscode.window.showInformationMessage( + 'Do you want to help EPFL develop Dotty LSP plugin by uploading your LSP communication? ' + + 'PLEASE BE AWARE that the data sent contains your entire codebase and ALL the IDE actions, ' + + 'including every single keystroke.', + 'yes', 'no' + ).then((value: string | undefined) => { + if (value === 'yes' || value === 'no') this.tracingConsent.set(value); + }); + } - try { - this.asyncUploadWorkspaceDump(remoteWorkspaceDumpUrl); - } catch (err) { - this.logError('error during workspace dump', safeError(err)); + private initializeAsyncWorkspaceDump() { + if (this.remoteWorkspaceDumpUrl === undefined) return; + // convince TS that this is a string + const definedUrl: string = this.remoteWorkspaceDumpUrl; + + const doInitialize = () => { + try { + this.asyncUploadWorkspaceDump(definedUrl); + } catch (err) { + this.logError('error during workspace dump', safeError(err)); + } + }; + + if (this.tracingConsent.get() === 'yes') { + doInitialize() + } else { + let didInitialize = false; + this.tracingConsent.subscribe(() => { + if (didInitialize) return; + didInitialize = true; + doInitialize(); + }) } } - createLspOutputChannel(): vscode.OutputChannel | undefined { - const remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl'); - if (!remoteTracingUrl) return undefined; - - if (this.tracingConsent.get() === 'no-answer') { - vscode.window.showInformationMessage( - 'Do you want to help EPFL develop this plugin by uploading your usage data? ' + - 'PLEASE BE AWARE that this will upload all of your keystrokes and all of your code, ' + - 'among other things.', - 'yes', 'no' - ).then((value: string | undefined) => { - if (value === 'yes' || value === 'no') this.tracingConsent.set(value); - }); + private createStatusBarItem(): vscode.StatusBarItem | undefined { + if (!this.isTracingEnabled) return undefined; + const item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0) + item.command = consentCommandName; + const renderStatusBarItem = () => { + item.text = (() => { + const desc = this.tracingConsent.get() === 'yes' ? 'ON' : 'OFF'; + return `$(radio-tower) Dotty trace: ${desc}`; + })(); + + item.tooltip = (() => { + const desc = this.tracingConsent.get() === 'yes' ? 'consented' : 'not consented'; + return `This workspace is configured for remote tracing of Dotty LSP and you have ${desc} to it. ` + + 'Click to adjust your consent.'; + })(); } + renderStatusBarItem(); + this.tracingConsent.subscribe(renderStatusBarItem); + item.show(); + return item; + } + + private createLspOutputChannel(): vscode.OutputChannel | undefined { + if (!this.remoteTracingUrl) return undefined; const localLspOutputChannel = vscode.window.createOutputChannel('Dotty LSP Communication') try { - return this.createRemoteLspOutputChannel(remoteTracingUrl, localLspOutputChannel); + return this.createRemoteLspOutputChannel(this.remoteTracingUrl, localLspOutputChannel); } catch (err) { this.logError('error during remote output channel creation', safeError(err)); return localLspOutputChannel; @@ -97,6 +154,7 @@ export class Tracer { private asyncUploadWorkspaceDump(url: string) { const storagePath = this.ctx.extensionContext.storagePath; + // TODO: handle multi-root workspaces const rootPath = vscode.workspace.rootPath; if (storagePath === undefined || rootPath === undefined) { this.logError('Cannot start workspace dump b/c of workspace state:', { storagePath, rootPath }); @@ -106,7 +164,7 @@ export class Tracer { if (!fs.existsSync(storagePath)) fs.mkdirSync(storagePath); const outputPath = path.join(storagePath, 'workspace-dump.zip'); if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath); - let output = fs.createWriteStream(outputPath); + const output = fs.createWriteStream(outputPath); output.on('end', () => { this.ctx.extensionOut.appendLine('zip - data has been drained'); }); @@ -138,7 +196,8 @@ export class Tracer { ); }); zip.pipe(output); - zip.glob('./**/*.{scala,sbt}', { cwd: rootPath }); + zip.glob('./**/*.{scala,sc,sbt,java}', { cwd: rootPath }); + zip.glob('./**/.dotty-ide{.json,-artifact}', { cwd: rootPath }); zip.finalize(); } @@ -146,49 +205,72 @@ export class Tracer { remoteTracingUrl: string, localOutputChannel: vscode.OutputChannel ): vscode.OutputChannel { - const socketHeaders = { - 'X-DLS-Project-ID': this.projectId, - 'X-DLS-Client-ID': this.machineId, - 'X-DLS-Session-ID': this.sessionId, - }; + const createSocket = () => { + const socket = new WebSocket(remoteTracingUrl, { + headers: { + 'X-DLS-Project-ID': this.projectId, + 'X-DLS-Client-ID': this.machineId, + 'X-DLS-Session-ID': this.sessionId, + }, + }); + + const timer = setInterval( + () => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(''); + } else if (socket.readyState === WebSocket.CLOSED) { + clearInterval(timer); + } + }, + 10 * 1000 /*ms*/, + ) + + socket.onerror = (event) => { + this.logErrorWithoutNotifying( + 'socket error', + remoteTracingUrl, + new SafeJsonifier(event, (event) => ({ + error: safeError(event.error), + message: event.message, + type: event.type + })) + ); + vscode.window.showWarningMessage('An error occured in Dotty LSP remote tracing connection.'); + } - const socket = new WebSocket(remoteTracingUrl, { headers: socketHeaders }); + socket.onclose = (event) => { + this.logErrorWithoutNotifying( + 'socket closed', + remoteTracingUrl, + new SafeJsonifier(event, (event) => ({ + wasClean: event.wasClean, + code: event.code, + reason: event.reason + })) + ); + vscode.window.showWarningMessage('Dotty LSP remote tracing connection was dropped.'); + } - const timer = setInterval( - () => { - if (socket.readyState === WebSocket.OPEN) { - socket.send(''); - } else if (socket.readyState === WebSocket.CLOSED) { - clearInterval(timer); + return socket; + }; + + let alreadyCreated = false; + let socket: WebSocket; + // note: creating socket lazily is important for correctness + // if the user did not initially give his consent on IDE start, but gives it afterwards + // we only want to start a connection and upload data *after* being given consent + const withSocket: (thunk: (socket: WebSocket) => any) => void = (thunk) => { + // only try to create the socket _once_ to avoid endlessly looping + if (!alreadyCreated) { + alreadyCreated = true; + try { + socket = createSocket(); + } catch (err) { + this.logError('socket create error', safeError(err)); } - }, - 10 * 1000 /*ms*/, - ) - - socket.onerror = (event) => { - this.logErrorWithoutNotifying( - 'socket error', - remoteTracingUrl, - new SafeJsonifier(event, (event) => ({ - error: safeError(event.error), - message: event.message, - type: event.type - })) - ); - vscode.window.showWarningMessage('An error occured in Dotty LSP remote tracing connection.'); - } + } - socket.onclose = (event) => { - this.logErrorWithoutNotifying( - 'socket closed', - remoteTracingUrl, - new SafeJsonifier(event, (event) => ({ - wasClean: event.wasClean, - code: event.code, - reason: event.reason - })) - ); - vscode.window.showWarningMessage('Dotty LSP remote tracing connection was dropped.'); + if (socket) thunk(socket); } let log: string = ''; @@ -210,21 +292,23 @@ export class Tracer { log += value; log += '\n'; - if (this.tracingConsent.get() === 'yes' && socket.readyState === WebSocket.OPEN) { - socket.send(log, (err) => { - if (err) { - this.logError('socket send error', err) - } - }); - log = ''; - } + if (this.tracingConsent.get() === 'yes') withSocket((socket) => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(log, (err) => { + if (err) { + this.logError('socket send error', err) + } + }); + log = ''; + } + }); }, clear() { }, show() { }, hide() { }, dispose() { - socket.close(); + if (socket) socket.close(); localOutputChannel.dispose(); } }; diff --git a/vscode-dotty/src/tracing-consent.ts b/vscode-dotty/src/tracing-consent.ts index d4ba4008292f..94443a57f30a 100644 --- a/vscode-dotty/src/tracing-consent.ts +++ b/vscode-dotty/src/tracing-consent.ts @@ -5,7 +5,9 @@ export type TracingConsent = 'yes' | 'no' | 'no-answer'; export class TracingConsentCache { private readonly workspaceState: Memento + // since updating Memento is async, caching prevents nonsense edge-cases private cache?: TracingConsent + private subscribers: Array<() => void> = []; constructor(workspaceState: Memento) { this.workspaceState = workspaceState; @@ -23,5 +25,10 @@ export class TracingConsentCache { set(value: 'yes' | 'no'): void { this.workspaceState.update('remote-tracing-consent', value === 'yes'); this.cache = value; + this.subscribers.forEach(f => f()); + } + + subscribe(callback: () => void): void { + this.subscribers.push(callback); } } From 623a0a08595de111db49047063557afd16959815 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Fri, 12 Oct 2018 15:59:38 +0200 Subject: [PATCH 04/11] VsCode plugin: make workspace dump more informative Remote useless info, say when starting to zip. --- vscode-dotty/src/tracer.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index 264244e6aaca..7513a30543fa 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -165,16 +165,10 @@ export class Tracer { const outputPath = path.join(storagePath, 'workspace-dump.zip'); if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath); const output = fs.createWriteStream(outputPath); - output.on('end', () => { - this.ctx.extensionOut.appendLine('zip - data has been drained'); - }); const zip = archiver('zip'); zip.on('error', (err) => this.logError('zip error', safeError(err))); zip.on('warning', (err) => this.logError('zip warning', safeError(err))); - zip.on('entry', (entry) => { - this.ctx.extensionOut.appendLine(`zip - entry: ${entry.name}`); - }); zip.on('finish', () => { this.ctx.extensionOut.appendLine('zip - finished'); fs.createReadStream(outputPath).pipe( @@ -195,6 +189,8 @@ export class Tracer { }) ); }); + + this.ctx.extensionOut.appendLine('zip - starting'); zip.pipe(output); zip.glob('./**/*.{scala,sc,sbt,java}', { cwd: rootPath }); zip.glob('./**/.dotty-ide{.json,-artifact}', { cwd: rootPath }); From 9f8e730e4f923fca72c776dd63f455441a8888a0 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Mon, 29 Oct 2018 13:26:04 +0100 Subject: [PATCH 05/11] VsCode: add max message size setting Note that server doesn't care if the messages are proper JSON or not. --- vscode-dotty/package.json | 5 +++++ vscode-dotty/src/tracer.ts | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index b61925a5535a..f956e61b0946 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -56,6 +56,11 @@ ], "default": null, "description": "ID of your machine used when Dotty Language Server tracing is turned on." + }, + "dotty.tracing.maximumMessageSize": { + "type": "number", + "default": 512, + "description": "Maximum size for the messages sent to remote server. Larger ones will be split." } } }, diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index 7513a30543fa..afbc2ec800fa 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -29,6 +29,7 @@ export class Tracer { private readonly remoteTracingUrl: string | undefined private readonly remoteWorkspaceDumpUrl: string | undefined + private readonly maximumMessageSize: number private get isTracingEnabled(): boolean { return Boolean(this.remoteWorkspaceDumpUrl || this.remoteTracingUrl); } @@ -40,6 +41,8 @@ export class Tracer { this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl'); this.remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl'); + const maximumMessageSize = this.ctx.extensionConfig.get('tracing.maximumMessageSize'); + this.maximumMessageSize = maximumMessageSize === undefined || maximumMessageSize < 0 ? 0 : maximumMessageSize | 0; this.machineId = (() => { const machineIdKey = 'tracing.machineId'; @@ -290,11 +293,17 @@ export class Tracer { log += '\n'; if (this.tracingConsent.get() === 'yes') withSocket((socket) => { if (socket.readyState === WebSocket.OPEN) { - socket.send(log, (err) => { + const send = (msg: string) => socket.send(msg, (err) => { if (err) { this.logError('socket send error', err) } }); + + let start = 0; + while (start < log.length) { + send(log.substring(start, start + this.maximumMessageSize)); + start += this.maximumMessageSize; + } log = ''; } }); From e4a1e648b979ebab0dfce3c6f4fb40f4691e2e1a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 30 Oct 2018 13:58:47 +0100 Subject: [PATCH 06/11] vscode-dotty: don't use semi-colons --- vscode-dotty/src/compat.ts | 6 +- vscode-dotty/src/extension.ts | 32 ++-- vscode-dotty/src/features.ts | 4 +- vscode-dotty/src/passthrough-server.ts | 6 +- vscode-dotty/src/sbt-server.ts | 24 +-- vscode-dotty/src/tracer.ts | 250 ++++++++++++------------- vscode-dotty/src/tracing-consent.ts | 24 +-- 7 files changed, 171 insertions(+), 175 deletions(-) diff --git a/vscode-dotty/src/compat.ts b/vscode-dotty/src/compat.ts index 1d11e4236f24..ae170b9090db 100644 --- a/vscode-dotty/src/compat.ts +++ b/vscode-dotty/src/compat.ts @@ -1,8 +1,8 @@ -import * as vscode from 'vscode'; +import * as vscode from 'vscode' -import { HoverRequest } from 'vscode-languageclient'; +import { HoverRequest } from 'vscode-languageclient' import { MarkedString, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, - ServerOptions } from 'vscode-languageclient'; + ServerOptions } from 'vscode-languageclient' // Fix hover functionality when using this version of vscode-dotty with Dotty // Language Server 0.9 or earlier. diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index 3c9f82ed8501..83d5fef8eceb 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -1,17 +1,15 @@ -'use strict'; +import * as fs from 'fs' +import * as path from 'path' -import * as fs from 'fs'; -import * as path from 'path'; +import * as pcp from 'promisify-child-process' +import * as compareVersions from 'compare-versions' -import * as pcp from 'promisify-child-process'; -import * as compareVersions from 'compare-versions'; +import { ChildProcess } from "child_process" -import { ChildProcess } from "child_process"; - -import { ExtensionContext } from 'vscode'; -import * as vscode from 'vscode'; +import { ExtensionContext } from 'vscode' +import * as vscode from 'vscode' import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn, - ServerOptions } from 'vscode-languageclient'; + ServerOptions } from 'vscode-languageclient' import { enableOldServerWorkaround } from './compat' import * as features from './features' @@ -19,14 +17,14 @@ export let client: LanguageClient import * as rpc from 'vscode-jsonrpc' import * as sbtserver from './sbt-server' -import { Tracer } from './tracer'; +import { Tracer } from './tracer' -export const extensionName = 'dotty'; -const extensionConfig = vscode.workspace.getConfiguration(extensionName); +export const extensionName = 'dotty' +const extensionConfig = vscode.workspace.getConfiguration(extensionName) let extensionContext: ExtensionContext let outputChannel: vscode.OutputChannel -let tracer: Tracer; +let tracer: Tracer /** The sbt process that may have been started by this extension */ let sbtProcess: ChildProcess | undefined @@ -50,14 +48,14 @@ function isConfiguredProject() { export function activate(context: ExtensionContext) { extensionContext = context - outputChannel = vscode.window.createOutputChannel("Dotty"); + outputChannel = vscode.window.createOutputChannel("Dotty") tracer = new Tracer({ extensionContext, extensionConfig, extensionOut: outputChannel, }) - const coursierPath = path.join(extensionContext.extensionPath, "out", "coursier"); + const coursierPath = path.join(extensionContext.extensionPath, "out", "coursier") const dottyPluginSbtFileSource = path.join(extensionContext.extensionPath, "out", "dotty-plugin.sbt") const buildSbtFileSource = path.join(extensionContext.extensionPath, "out", "build.sbt") @@ -308,7 +306,7 @@ function bootstrapSbtProject(buildSbtFileSource: string, function run(serverOptions: ServerOptions, isOldServer: boolean) { - const { lspOutputChannel } = tracer.run(); + const { lspOutputChannel } = tracer.run() const clientOptions: LanguageClientOptions = { documentSelector: [ diff --git a/vscode-dotty/src/features.ts b/vscode-dotty/src/features.ts index 8416048aa86e..24d02c169978 100644 --- a/vscode-dotty/src/features.ts +++ b/vscode-dotty/src/features.ts @@ -14,9 +14,9 @@ import { WorksheetProvider } from './worksheet' // https://github.com/Microsoft/vscode-languageserver-node/issues/423 is fixed. function ensure(target: T, key: K): T[K] { if (target[key] === void 0) { - target[key] = {} as any; + target[key] = {} as any } - return target[key]; + return target[key] } export interface WorksheetClientCapabilities { diff --git a/vscode-dotty/src/passthrough-server.ts b/vscode-dotty/src/passthrough-server.ts index 6ac50f05fe92..7d3005fe71fe 100644 --- a/vscode-dotty/src/passthrough-server.ts +++ b/vscode-dotty/src/passthrough-server.ts @@ -1,6 +1,4 @@ -'use strict'; - -import * as net from 'net'; +import * as net from 'net' let argv: string[] = process.argv.slice(2) const firstArg: string | undefined = argv.shift() @@ -22,7 +20,7 @@ client.on('data', (data) => { process.stdout.write(data.toString()) }) process.stdin.on('readable', () => { - let chunk = process.stdin.read(); + let chunk = process.stdin.read() if (chunk !== null) { if (isConnected) { client.write(chunk) diff --git a/vscode-dotty/src/sbt-server.ts b/vscode-dotty/src/sbt-server.ts index 087e6a88d8b1..279d70f8af6e 100644 --- a/vscode-dotty/src/sbt-server.ts +++ b/vscode-dotty/src/sbt-server.ts @@ -79,25 +79,25 @@ function connectSocket(socket: net.Socket): net.Socket { if (u.protocol == 'tcp:' && u.port) { socket.connect(+u.port, '127.0.0.1'); } else if (u.protocol == 'local:' && u.hostname && os.platform() == 'win32') { - let pipePath = '\\\\.\\pipe\\' + u.hostname; - socket.connect(pipePath); + let pipePath = '\\\\.\\pipe\\' + u.hostname + socket.connect(pipePath) } else if (u.protocol == 'local:' && u.path) { - socket.connect(u.path); + socket.connect(u.path) } else { - throw 'Unknown protocol ' + u.protocol; + throw 'Unknown protocol ' + u.protocol } - return socket; + return socket } // the port file is hardcoded to a particular location relative to the build. function discoverUrl(): url.Url { - let pf = path.join(workspaceRoot, 'project', 'target', 'active.json'); - let portfile = JSON.parse(fs.readFileSync(pf).toString()); - return url.parse(portfile.uri); + let pf = path.join(workspaceRoot, 'project', 'target', 'active.json') + let portfile = JSON.parse(fs.readFileSync(pf).toString()) + return url.parse(portfile.uri) } function delay(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => setTimeout(resolve, ms)) } async function waitForServer(): Promise { @@ -106,12 +106,12 @@ async function waitForServer(): Promise { location: vscode.ProgressLocation.Window, title: "Connecting to sbt server..." }, async _ => { - let retries = 60; + let retries = 60 while (!socket && retries > 0) { try { socket = connectSocket(new net.Socket()) } catch (e) { - retries--; - await delay(1000); + retries-- + await delay(1000) } } if (socket) return Promise.resolve(socket) diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index afbc2ec800fa..23647dccdb14 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -1,16 +1,16 @@ -import * as vscode from 'vscode'; +import * as vscode from 'vscode' -import * as fs from 'fs'; -import * as path from 'path'; +import * as fs from 'fs' +import * as path from 'path' -import * as archiver from 'archiver'; -import * as WebSocket from 'ws'; -import * as request from 'request'; +import * as archiver from 'archiver' +import * as WebSocket from 'ws' +import * as request from 'request' -import { extensionName } from './extension'; -import { TracingConsentCache } from './tracing-consent'; +import { extensionName } from './extension' +import { TracingConsentCache } from './tracing-consent' -const consentCommandName = `${extensionName}.adjust-consent`; +const consentCommandName = `${extensionName}.adjust-consent` export interface Ctx { readonly extensionContext: vscode.ExtensionContext, @@ -31,28 +31,28 @@ export class Tracer { private readonly remoteWorkspaceDumpUrl: string | undefined private readonly maximumMessageSize: number private get isTracingEnabled(): boolean { - return Boolean(this.remoteWorkspaceDumpUrl || this.remoteTracingUrl); + return Boolean(this.remoteWorkspaceDumpUrl || this.remoteTracingUrl) } constructor(ctx: Ctx) { - this.ctx = ctx; + this.ctx = ctx - this.tracingConsent = new TracingConsentCache(ctx.extensionContext.workspaceState); + this.tracingConsent = new TracingConsentCache(ctx.extensionContext.workspaceState) - this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl'); - this.remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl'); - const maximumMessageSize = this.ctx.extensionConfig.get('tracing.maximumMessageSize'); - this.maximumMessageSize = maximumMessageSize === undefined || maximumMessageSize < 0 ? 0 : maximumMessageSize | 0; + this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl') + this.remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl') + const maximumMessageSize = this.ctx.extensionConfig.get('tracing.maximumMessageSize') + this.maximumMessageSize = maximumMessageSize === undefined || maximumMessageSize < 0 ? 0 : maximumMessageSize | 0 this.machineId = (() => { - const machineIdKey = 'tracing.machineId'; + const machineIdKey = 'tracing.machineId' function persisted(value: string): string { ctx.extensionConfig.update(machineIdKey, value, vscode.ConfigurationTarget.Global) return value } const machineId = ctx.extensionConfig.get(machineIdKey) - if (machineId != null) return machineId; + if (machineId != null) return machineId // vscode.env.machineId is a dummy value if telemetry is off - cannot be used const vscodeMachineId = vscode.workspace.getConfiguration().get('telemetry.machineId') @@ -61,28 +61,28 @@ export class Tracer { function uuidv4() { // https://stackoverflow.com/a/2117523 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8) + return v.toString(16) + }) } return persisted(uuidv4()) - })(); + })() - this.projectId = vscode.workspace.name !== undefined ? vscode.workspace.name : 'no-project'; - this.sessionId = new Date().toISOString(); + this.projectId = vscode.workspace.name !== undefined ? vscode.workspace.name : 'no-project' + this.sessionId = new Date().toISOString() } run(): { lspOutputChannel?: vscode.OutputChannel } { - const consentCommandDisposable = vscode.commands.registerCommand(consentCommandName, () => this.askForTracingConsent()); - if (this.isTracingEnabled && this.tracingConsent.get() === 'no-answer') this.askForTracingConsent(); - this.initializeAsyncWorkspaceDump(); - const lspOutputChannel = this.createLspOutputChannel(); - const statusBarItem = this.createStatusBarItem(); + const consentCommandDisposable = vscode.commands.registerCommand(consentCommandName, () => this.askForTracingConsent()) + if (this.isTracingEnabled && this.tracingConsent.get() === 'no-answer') this.askForTracingConsent() + this.initializeAsyncWorkspaceDump() + const lspOutputChannel = this.createLspOutputChannel() + const statusBarItem = this.createStatusBarItem() for (const disposable of [consentCommandDisposable, lspOutputChannel, statusBarItem]) { - if (disposable) this.ctx.extensionContext.subscriptions.push(disposable); + if (disposable) this.ctx.extensionContext.subscriptions.push(disposable) } - return { lspOutputChannel }; + return { lspOutputChannel } } private askForTracingConsent(): void { @@ -92,88 +92,88 @@ export class Tracer { 'including every single keystroke.', 'yes', 'no' ).then((value: string | undefined) => { - if (value === 'yes' || value === 'no') this.tracingConsent.set(value); - }); + if (value === 'yes' || value === 'no') this.tracingConsent.set(value) + }) } private initializeAsyncWorkspaceDump() { - if (this.remoteWorkspaceDumpUrl === undefined) return; + if (this.remoteWorkspaceDumpUrl === undefined) return // convince TS that this is a string - const definedUrl: string = this.remoteWorkspaceDumpUrl; + const definedUrl: string = this.remoteWorkspaceDumpUrl const doInitialize = () => { try { - this.asyncUploadWorkspaceDump(definedUrl); + this.asyncUploadWorkspaceDump(definedUrl) } catch (err) { - this.logError('error during workspace dump', safeError(err)); + this.logError('error during workspace dump', safeError(err)) } - }; + } if (this.tracingConsent.get() === 'yes') { doInitialize() } else { - let didInitialize = false; + let didInitialize = false this.tracingConsent.subscribe(() => { - if (didInitialize) return; - didInitialize = true; - doInitialize(); + if (didInitialize) return + didInitialize = true + doInitialize() }) } } private createStatusBarItem(): vscode.StatusBarItem | undefined { - if (!this.isTracingEnabled) return undefined; + if (!this.isTracingEnabled) return undefined const item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0) - item.command = consentCommandName; + item.command = consentCommandName const renderStatusBarItem = () => { item.text = (() => { - const desc = this.tracingConsent.get() === 'yes' ? 'ON' : 'OFF'; - return `$(radio-tower) Dotty trace: ${desc}`; - })(); + const desc = this.tracingConsent.get() === 'yes' ? 'ON' : 'OFF' + return `$(radio-tower) Dotty trace: ${desc}` + })() item.tooltip = (() => { - const desc = this.tracingConsent.get() === 'yes' ? 'consented' : 'not consented'; + const desc = this.tracingConsent.get() === 'yes' ? 'consented' : 'not consented' return `This workspace is configured for remote tracing of Dotty LSP and you have ${desc} to it. ` + - 'Click to adjust your consent.'; - })(); + 'Click to adjust your consent.' + })() } - renderStatusBarItem(); - this.tracingConsent.subscribe(renderStatusBarItem); - item.show(); - return item; + renderStatusBarItem() + this.tracingConsent.subscribe(renderStatusBarItem) + item.show() + return item } private createLspOutputChannel(): vscode.OutputChannel | undefined { - if (!this.remoteTracingUrl) return undefined; + if (!this.remoteTracingUrl) return undefined const localLspOutputChannel = vscode.window.createOutputChannel('Dotty LSP Communication') try { - return this.createRemoteLspOutputChannel(this.remoteTracingUrl, localLspOutputChannel); + return this.createRemoteLspOutputChannel(this.remoteTracingUrl, localLspOutputChannel) } catch (err) { - this.logError('error during remote output channel creation', safeError(err)); - return localLspOutputChannel; + this.logError('error during remote output channel creation', safeError(err)) + return localLspOutputChannel } } private asyncUploadWorkspaceDump(url: string) { - const storagePath = this.ctx.extensionContext.storagePath; + const storagePath = this.ctx.extensionContext.storagePath // TODO: handle multi-root workspaces - const rootPath = vscode.workspace.rootPath; + const rootPath = vscode.workspace.rootPath if (storagePath === undefined || rootPath === undefined) { - this.logError('Cannot start workspace dump b/c of workspace state:', { storagePath, rootPath }); - return; + this.logError('Cannot start workspace dump b/c of workspace state:', { storagePath, rootPath }) + return } - if (!fs.existsSync(storagePath)) fs.mkdirSync(storagePath); - const outputPath = path.join(storagePath, 'workspace-dump.zip'); - if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath); - const output = fs.createWriteStream(outputPath); + if (!fs.existsSync(storagePath)) fs.mkdirSync(storagePath) + const outputPath = path.join(storagePath, 'workspace-dump.zip') + if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath) + const output = fs.createWriteStream(outputPath) - const zip = archiver('zip'); - zip.on('error', (err) => this.logError('zip error', safeError(err))); - zip.on('warning', (err) => this.logError('zip warning', safeError(err))); + const zip = archiver('zip') + zip.on('error', (err) => this.logError('zip error', safeError(err))) + zip.on('warning', (err) => this.logError('zip warning', safeError(err))) zip.on('finish', () => { - this.ctx.extensionOut.appendLine('zip - finished'); + this.ctx.extensionOut.appendLine('zip - finished') fs.createReadStream(outputPath).pipe( request.put(url, { qs: { @@ -185,19 +185,19 @@ export class Tracer { .on('error', (err) => this.logError('zip upload connection error', url, safeError(err))) .on('complete', (resp) => { if (!(resp.statusCode >= 200 && resp.statusCode < 300)) { - this.logError('zip upload http error', url, resp.statusCode, resp.body); + this.logError('zip upload http error', url, resp.statusCode, resp.body) } else { - this.ctx.extensionOut.appendLine('zip - http upload finished'); + this.ctx.extensionOut.appendLine('zip - http upload finished') } }) - ); - }); - - this.ctx.extensionOut.appendLine('zip - starting'); - zip.pipe(output); - zip.glob('./**/*.{scala,sc,sbt,java}', { cwd: rootPath }); - zip.glob('./**/.dotty-ide{.json,-artifact}', { cwd: rootPath }); - zip.finalize(); + ) + }) + + this.ctx.extensionOut.appendLine('zip - starting') + zip.pipe(output) + zip.glob('./**/*.{scala,sc,sbt,java}', { cwd: rootPath }) + zip.glob('./**/.dotty-ide{.json,-artifact}', { cwd: rootPath }) + zip.finalize() } private createRemoteLspOutputChannel( @@ -211,14 +211,14 @@ export class Tracer { 'X-DLS-Client-ID': this.machineId, 'X-DLS-Session-ID': this.sessionId, }, - }); + }) const timer = setInterval( () => { if (socket.readyState === WebSocket.OPEN) { - socket.send(''); + socket.send('') } else if (socket.readyState === WebSocket.CLOSED) { - clearInterval(timer); + clearInterval(timer) } }, 10 * 1000 /*ms*/, @@ -233,8 +233,8 @@ export class Tracer { message: event.message, type: event.type })) - ); - vscode.window.showWarningMessage('An error occured in Dotty LSP remote tracing connection.'); + ) + vscode.window.showWarningMessage('An error occured in Dotty LSP remote tracing connection.') } socket.onclose = (event) => { @@ -246,97 +246,97 @@ export class Tracer { code: event.code, reason: event.reason })) - ); - vscode.window.showWarningMessage('Dotty LSP remote tracing connection was dropped.'); + ) + vscode.window.showWarningMessage('Dotty LSP remote tracing connection was dropped.') } - return socket; - }; + return socket + } - let alreadyCreated = false; - let socket: WebSocket; + let alreadyCreated = false + let socket: WebSocket // note: creating socket lazily is important for correctness // if the user did not initially give his consent on IDE start, but gives it afterwards // we only want to start a connection and upload data *after* being given consent const withSocket: (thunk: (socket: WebSocket) => any) => void = (thunk) => { // only try to create the socket _once_ to avoid endlessly looping if (!alreadyCreated) { - alreadyCreated = true; + alreadyCreated = true try { - socket = createSocket(); + socket = createSocket() } catch (err) { - this.logError('socket create error', safeError(err)); + this.logError('socket create error', safeError(err)) } } - if (socket) thunk(socket); + if (socket) thunk(socket) } - let log: string = ''; + let log: string = '' return { name: 'websocket', append: (value: string) => { - localOutputChannel.append(value); - if (this.tracingConsent.get() === 'no') return; - log += value; + localOutputChannel.append(value) + if (this.tracingConsent.get() === 'no') return + log += value }, appendLine: (value: string) => { localOutputChannel.appendLine(value) if (this.tracingConsent.get() === 'no') { - log = ''; - return; + log = '' + return } - log += value; - log += '\n'; + log += value + log += '\n' if (this.tracingConsent.get() === 'yes') withSocket((socket) => { if (socket.readyState === WebSocket.OPEN) { const send = (msg: string) => socket.send(msg, (err) => { if (err) { this.logError('socket send error', err) } - }); + }) - let start = 0; + let start = 0 while (start < log.length) { - send(log.substring(start, start + this.maximumMessageSize)); - start += this.maximumMessageSize; + send(log.substring(start, start + this.maximumMessageSize)) + start += this.maximumMessageSize } - log = ''; + log = '' } - }); + }) }, clear() { }, show() { }, hide() { }, dispose() { - if (socket) socket.close(); - localOutputChannel.dispose(); + if (socket) socket.close() + localOutputChannel.dispose() } - }; + } } - private silenceErrors: boolean = false; + private silenceErrors: boolean = false private logErrorWithoutNotifying(message: string, ...rest: any[]) { - const msg = `[Dotty LSP Tracer] ${message}`; + const msg = `[Dotty LSP Tracer] ${message}` // unwrap SafeJsonifier, for some reason Electron logs the result // of .toJSON, unlike browsers - console.error(msg, ...rest.map((a) => a instanceof SafeJsonifier ? a.value : a)); + console.error(msg, ...rest.map((a) => a instanceof SafeJsonifier ? a.value : a)) function cautiousStringify(a: any): string { try { - return JSON.stringify(a, undefined, 4); + return JSON.stringify(a, undefined, 4) } catch (err) { - console.error('cannot stringify', err, a); - return a.toString(); + console.error('cannot stringify', err, a) + return a.toString() } } - this.ctx.extensionOut.appendLine([msg].concat(rest.map(cautiousStringify)).join(' ')); + this.ctx.extensionOut.appendLine([msg].concat(rest.map(cautiousStringify)).join(' ')) } private logError(message: string, ...rest: any[]) { - this.logErrorWithoutNotifying(message, ...rest); + this.logErrorWithoutNotifying(message, ...rest) if (!this.silenceErrors) { vscode.window.showErrorMessage( 'An error occured which prevents sending usage data to EPFL. ' + @@ -344,7 +344,7 @@ export class Tracer { 'Silence further errors' ).then((result) => { if (result !== undefined) { - this.silenceErrors = true; + this.silenceErrors = true } }) } @@ -352,7 +352,7 @@ export class Tracer { } function safeError(e: Error): SafeJsonifier { - return new SafeJsonifier(e, (e) => e.toString()); + return new SafeJsonifier(e, (e) => e.toString()) } class SafeJsonifier { @@ -360,11 +360,11 @@ class SafeJsonifier { valueToObject: (t: T) => {} constructor(value: T, valueToObject: (t: T) => {}) { - this.value = value; - this.valueToObject = valueToObject; + this.value = value + this.valueToObject = valueToObject } toJSON() { - return this.valueToObject(this.value); + return this.valueToObject(this.value) } } diff --git a/vscode-dotty/src/tracing-consent.ts b/vscode-dotty/src/tracing-consent.ts index 94443a57f30a..6c41c93c5acf 100644 --- a/vscode-dotty/src/tracing-consent.ts +++ b/vscode-dotty/src/tracing-consent.ts @@ -1,34 +1,34 @@ -import { Memento } from 'vscode'; +import { Memento } from 'vscode' -export type TracingConsent = 'yes' | 'no' | 'no-answer'; +export type TracingConsent = 'yes' | 'no' | 'no-answer' export class TracingConsentCache { private readonly workspaceState: Memento // since updating Memento is async, caching prevents nonsense edge-cases private cache?: TracingConsent - private subscribers: Array<() => void> = []; + private subscribers: Array<() => void> = [] constructor(workspaceState: Memento) { - this.workspaceState = workspaceState; + this.workspaceState = workspaceState } get(): TracingConsent { - if (this.cache !== undefined) return this.cache; - const setting = this.workspaceState.get('remote-tracing-consent'); + if (this.cache !== undefined) return this.cache + const setting = this.workspaceState.get('remote-tracing-consent') this.cache = setting === undefined ? 'no-answer' : setting ? 'yes' - : 'no'; - return this.cache; + : 'no' + return this.cache } set(value: 'yes' | 'no'): void { - this.workspaceState.update('remote-tracing-consent', value === 'yes'); - this.cache = value; - this.subscribers.forEach(f => f()); + this.workspaceState.update('remote-tracing-consent', value === 'yes') + this.cache = value + this.subscribers.forEach(f => f()) } subscribe(callback: () => void): void { - this.subscribers.push(callback); + this.subscribers.push(callback) } } From 732033948268a829867283b943e3a21d734060d6 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 30 Oct 2018 14:00:45 +0100 Subject: [PATCH 07/11] vscode-dotty: update package-lock.json --- vscode-dotty/package-lock.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/vscode-dotty/package-lock.json b/vscode-dotty/package-lock.json index 5965899e6c22..e54e2b39028a 100644 --- a/vscode-dotty/package-lock.json +++ b/vscode-dotty/package-lock.json @@ -522,7 +522,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, @@ -633,7 +633,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { @@ -843,7 +843,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -922,7 +922,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -1256,7 +1256,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -1362,7 +1362,7 @@ }, "kind-of": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, @@ -1529,13 +1529,13 @@ }, "minimist": { "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -1689,7 +1689,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -1803,7 +1803,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -2045,7 +2045,7 @@ }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, From 803843c49d79ffd6329b95c45c4f8aa4720ddffd Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Wed, 31 Oct 2018 16:13:46 +0100 Subject: [PATCH 08/11] Adjust after review --- vscode-dotty/package.json | 14 ++++++- vscode-dotty/src/extension.ts | 3 +- vscode-dotty/src/tracer.ts | 75 ++++++++++++++++------------------- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/vscode-dotty/package.json b/vscode-dotty/package.json index f956e61b0946..fe5532031eb5 100644 --- a/vscode-dotty/package.json +++ b/vscode-dotty/package.json @@ -49,7 +49,17 @@ "default": true, "description": "If true, saving a worksheet will also run it." }, - "dotty.tracing.machineId": { + "dotty.trace.remoteWorkspaceDumpUrl": { + "type": "string", + "default": "", + "description": "Url to send local workspace dump to." + }, + "dotty.trace.remoteTracingUrl": { + "type": "string", + "default": "", + "description": "Url to send local LSP communication to." + }, + "dotty.trace.machineId": { "type": [ "string", "null" @@ -57,7 +67,7 @@ "default": null, "description": "ID of your machine used when Dotty Language Server tracing is turned on." }, - "dotty.tracing.maximumMessageSize": { + "dotty.trace.maximumMessageSize": { "type": "number", "default": 512, "description": "Maximum size for the messages sent to remote server. Larger ones will be split." diff --git a/vscode-dotty/src/extension.ts b/vscode-dotty/src/extension.ts index 83d5fef8eceb..282cbe4e39fa 100644 --- a/vscode-dotty/src/extension.ts +++ b/vscode-dotty/src/extension.ts @@ -305,8 +305,7 @@ function bootstrapSbtProject(buildSbtFileSource: string, } function run(serverOptions: ServerOptions, isOldServer: boolean) { - - const { lspOutputChannel } = tracer.run() + const lspOutputChannel = tracer.run() const clientOptions: LanguageClientOptions = { documentSelector: [ diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index 23647dccdb14..948e589d329d 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -39,9 +39,9 @@ export class Tracer { this.tracingConsent = new TracingConsentCache(ctx.extensionContext.workspaceState) - this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('remoteWorkspaceDumpUrl') - this.remoteTracingUrl = this.ctx.extensionConfig.get('remoteTracingUrl') - const maximumMessageSize = this.ctx.extensionConfig.get('tracing.maximumMessageSize') + this.remoteWorkspaceDumpUrl = this.ctx.extensionConfig.get('trace.remoteWorkspaceDumpUrl') + this.remoteTracingUrl = this.ctx.extensionConfig.get('trace.remoteTracingUrl') + const maximumMessageSize = this.ctx.extensionConfig.get('trace.maximumMessageSize') this.maximumMessageSize = maximumMessageSize === undefined || maximumMessageSize < 0 ? 0 : maximumMessageSize | 0 this.machineId = (() => { @@ -73,16 +73,17 @@ export class Tracer { this.sessionId = new Date().toISOString() } - run(): { lspOutputChannel?: vscode.OutputChannel } { + run(): vscode.OutputChannel | undefined { const consentCommandDisposable = vscode.commands.registerCommand(consentCommandName, () => this.askForTracingConsent()) if (this.isTracingEnabled && this.tracingConsent.get() === 'no-answer') this.askForTracingConsent() this.initializeAsyncWorkspaceDump() + const lspOutputChannel = this.createLspOutputChannel() const statusBarItem = this.createStatusBarItem() for (const disposable of [consentCommandDisposable, lspOutputChannel, statusBarItem]) { if (disposable) this.ctx.extensionContext.subscriptions.push(disposable) } - return { lspOutputChannel } + return lspOutputChannel } private askForTracingConsent(): void { @@ -97,13 +98,12 @@ export class Tracer { } private initializeAsyncWorkspaceDump() { - if (this.remoteWorkspaceDumpUrl === undefined) return - // convince TS that this is a string - const definedUrl: string = this.remoteWorkspaceDumpUrl + const url = this.remoteWorkspaceDumpUrl + if (url === undefined) return const doInitialize = () => { try { - this.asyncUploadWorkspaceDump(definedUrl) + this.asyncUploadWorkspaceDump(url) } catch (err) { this.logError('error during workspace dump', safeError(err)) } @@ -144,14 +144,20 @@ export class Tracer { } private createLspOutputChannel(): vscode.OutputChannel | undefined { - if (!this.remoteTracingUrl) return undefined + if (this.ctx.extensionConfig.get('trace.server') === undefined) { + if (this.remoteTracingUrl) this.ctx.extensionOut.appendLine( + 'error: tracing URL is set, but trace.server not - no remote tracing possible.' + ) + return undefined + } - const localLspOutputChannel = vscode.window.createOutputChannel('Dotty LSP Communication') + const lspOutputChannel = vscode.window.createOutputChannel('Dotty LSP Communication') + if (!this.remoteTracingUrl) return lspOutputChannel try { - return this.createRemoteLspOutputChannel(this.remoteTracingUrl, localLspOutputChannel) + return this.createRemoteLspOutputChannel(this.remoteTracingUrl, lspOutputChannel) } catch (err) { this.logError('error during remote output channel creation', safeError(err)) - return localLspOutputChannel + return lspOutputChannel } } @@ -225,7 +231,7 @@ export class Tracer { ) socket.onerror = (event) => { - this.logErrorWithoutNotifying( + this.logError( 'socket error', remoteTracingUrl, new SafeJsonifier(event, (event) => ({ @@ -238,7 +244,7 @@ export class Tracer { } socket.onclose = (event) => { - this.logErrorWithoutNotifying( + this.logError( 'socket closed', remoteTracingUrl, new SafeJsonifier(event, (event) => ({ @@ -319,11 +325,12 @@ export class Tracer { } } - private silenceErrors: boolean = false - private logErrorWithoutNotifying(message: string, ...rest: any[]) { + private logError(message: string, ...rest: any[]) { const msg = `[Dotty LSP Tracer] ${message}` - // unwrap SafeJsonifier, for some reason Electron logs the result - // of .toJSON, unlike browsers + // in a browser, we'd be able to log a SafeJsonifier directly + // and get an inspectable object in the console + // unfortunately, Electron apparently uses .toJson if available, + // so we need to manually unwrap SafeJsonifiers console.error(msg, ...rest.map((a) => a instanceof SafeJsonifier ? a.value : a)) function cautiousStringify(a: any): string { try { @@ -335,34 +342,22 @@ export class Tracer { } this.ctx.extensionOut.appendLine([msg].concat(rest.map(cautiousStringify)).join(' ')) } - private logError(message: string, ...rest: any[]) { - this.logErrorWithoutNotifying(message, ...rest) - if (!this.silenceErrors) { - vscode.window.showErrorMessage( - 'An error occured which prevents sending usage data to EPFL. ' + - 'Please copy the text from "Dotty Language Client" output (View > Output) and send it to your TA.', - 'Silence further errors' - ).then((result) => { - if (result !== undefined) { - this.silenceErrors = true - } - }) - } - } } function safeError(e: Error): SafeJsonifier { return new SafeJsonifier(e, (e) => e.toString()) } +/** + * Wraps a value of type T so it's possible to safely pass it to JSON.stringify. + * + * Values with circular references (errors, for example) cause JSON.stringify to throw an exception + */ class SafeJsonifier { - value: T - valueToObject: (t: T) => {} - - constructor(value: T, valueToObject: (t: T) => {}) { - this.value = value - this.valueToObject = valueToObject - } + constructor( + readonly value: T, + readonly valueToObject: (t: T) => {} + ) {} toJSON() { return this.valueToObject(this.value) From 1912f86afc8e3572cd7023e16156985dbdea176e Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 31 Oct 2018 17:04:01 +0100 Subject: [PATCH 09/11] Update the message asking for tracing consent --- vscode-dotty/src/tracer.ts | 30 +++++++++++++++-------------- vscode-dotty/src/tracing-consent.ts | 10 +++++----- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index 948e589d329d..1f177a8472e4 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -88,12 +88,13 @@ export class Tracer { private askForTracingConsent(): void { vscode.window.showInformationMessage( - 'Do you want to help EPFL develop Dotty LSP plugin by uploading your LSP communication? ' + - 'PLEASE BE AWARE that the data sent contains your entire codebase and ALL the IDE actions, ' + - 'including every single keystroke.', - 'yes', 'no' + 'To help us improve the Scala IDE support, we would like to collect ' + + 'the content of every Scala file in your project and ' + + 'every interaction with Scala files in the IDE, including keystrokes. ' + + 'This data will be stored anonymously (we won\'t know your name) on servers at EPFL in Switzerland.', + 'Allow', 'Deny', ).then((value: string | undefined) => { - if (value === 'yes' || value === 'no') this.tracingConsent.set(value) + if (value === 'Allow' || value === 'Deny') this.tracingConsent.set(value) }) } @@ -109,7 +110,7 @@ export class Tracer { } } - if (this.tracingConsent.get() === 'yes') { + if (this.tracingConsent.get() === 'Allow') { doInitialize() } else { let didInitialize = false @@ -127,14 +128,15 @@ export class Tracer { item.command = consentCommandName const renderStatusBarItem = () => { item.text = (() => { - const desc = this.tracingConsent.get() === 'yes' ? 'ON' : 'OFF' - return `$(radio-tower) Dotty trace: ${desc}` + const desc = this.tracingConsent.get() === 'Allow' ? 'On' : 'Off' + return `$(radio-tower) Scala telemetry: ${desc}` })() item.tooltip = (() => { - const desc = this.tracingConsent.get() === 'yes' ? 'consented' : 'not consented' - return `This workspace is configured for remote tracing of Dotty LSP and you have ${desc} to it. ` + - 'Click to adjust your consent.' + const desc = this.tracingConsent.get() === 'Allow' ? 'enabled' : 'disabled' + const toggle = this.tracingConsent.get() === 'Allow' ? 'disable' : 'enable' + return `Data collection for Scala is ${desc}. ` + + `Click to ${toggle} it.` })() } renderStatusBarItem() @@ -284,20 +286,20 @@ export class Tracer { append: (value: string) => { localOutputChannel.append(value) - if (this.tracingConsent.get() === 'no') return + if (this.tracingConsent.get() === 'Deny') return log += value }, appendLine: (value: string) => { localOutputChannel.appendLine(value) - if (this.tracingConsent.get() === 'no') { + if (this.tracingConsent.get() === 'Deny') { log = '' return } log += value log += '\n' - if (this.tracingConsent.get() === 'yes') withSocket((socket) => { + if (this.tracingConsent.get() === 'Allow') withSocket((socket) => { if (socket.readyState === WebSocket.OPEN) { const send = (msg: string) => socket.send(msg, (err) => { if (err) { diff --git a/vscode-dotty/src/tracing-consent.ts b/vscode-dotty/src/tracing-consent.ts index 6c41c93c5acf..306fb1190b53 100644 --- a/vscode-dotty/src/tracing-consent.ts +++ b/vscode-dotty/src/tracing-consent.ts @@ -1,6 +1,6 @@ import { Memento } from 'vscode' -export type TracingConsent = 'yes' | 'no' | 'no-answer' +export type TracingConsent = 'Allow' | 'Deny' | 'no-answer' export class TracingConsentCache { private readonly workspaceState: Memento @@ -17,13 +17,13 @@ export class TracingConsentCache { if (this.cache !== undefined) return this.cache const setting = this.workspaceState.get('remote-tracing-consent') this.cache = setting === undefined ? 'no-answer' - : setting ? 'yes' - : 'no' + : setting ? 'Allow' + : 'Deny' return this.cache } - set(value: 'yes' | 'no'): void { - this.workspaceState.update('remote-tracing-consent', value === 'yes') + set(value: 'Allow' | 'Deny'): void { + this.workspaceState.update('remote-tracing-consent', value === 'Allow') this.cache = value this.subscribers.forEach(f => f()) } From b68c35a49986b61e2c6c4679bed1987d9314652a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 31 Oct 2018 17:07:17 +0100 Subject: [PATCH 10/11] Fix indentation for object literal --- vscode-dotty/src/tracer.ts | 80 +++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index 1f177a8472e4..e46ac879b8f2 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -282,48 +282,48 @@ export class Tracer { let log: string = '' return { - name: 'websocket', - - append: (value: string) => { - localOutputChannel.append(value) - if (this.tracingConsent.get() === 'Deny') return - log += value - }, - - appendLine: (value: string) => { - localOutputChannel.appendLine(value) - if (this.tracingConsent.get() === 'Deny') { - log = '' - return - } + name: 'websocket', + + append: (value: string) => { + localOutputChannel.append(value) + if (this.tracingConsent.get() === 'Deny') return + log += value + }, + + appendLine: (value: string) => { + localOutputChannel.appendLine(value) + if (this.tracingConsent.get() === 'Deny') { + log = '' + return + } - log += value - log += '\n' - if (this.tracingConsent.get() === 'Allow') withSocket((socket) => { - if (socket.readyState === WebSocket.OPEN) { - const send = (msg: string) => socket.send(msg, (err) => { - if (err) { - this.logError('socket send error', err) - } - }) - - let start = 0 - while (start < log.length) { - send(log.substring(start, start + this.maximumMessageSize)) - start += this.maximumMessageSize - } - log = '' - } + log += value + log += '\n' + if (this.tracingConsent.get() === 'Allow') withSocket((socket) => { + if (socket.readyState === WebSocket.OPEN) { + const send = (msg: string) => socket.send(msg, (err) => { + if (err) { + this.logError('socket send error', err) + } }) - }, - - clear() { }, - show() { }, - hide() { }, - dispose() { - if (socket) socket.close() - localOutputChannel.dispose() - } + + let start = 0 + while (start < log.length) { + send(log.substring(start, start + this.maximumMessageSize)) + start += this.maximumMessageSize + } + log = '' + } + }) + }, + + clear() { }, + show() { }, + hide() { }, + dispose() { + if (socket) socket.close() + localOutputChannel.dispose() + } } } From d3f45e9dc430f47170d62fb793a6eb902717e5cf Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 31 Oct 2018 17:14:47 +0100 Subject: [PATCH 11/11] Add a maximum size to the local lsp log buffer --- vscode-dotty/src/tracer.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vscode-dotty/src/tracer.ts b/vscode-dotty/src/tracer.ts index e46ac879b8f2..1a4841001d27 100644 --- a/vscode-dotty/src/tracer.ts +++ b/vscode-dotty/src/tracer.ts @@ -281,16 +281,31 @@ export class Tracer { } let log: string = '' + let messageCounter: number = 0 + // Avoid filling the user memory with log messages + let maxLocalMessages: number = 1000 return { name: 'websocket', append: (value: string) => { + messageCounter++ + if (messageCounter > maxLocalMessages) { + messageCounter = 0 + localOutputChannel.clear() + } + localOutputChannel.append(value) if (this.tracingConsent.get() === 'Deny') return log += value }, appendLine: (value: string) => { + messageCounter++ + if (messageCounter > maxLocalMessages) { + messageCounter = 0 + localOutputChannel.clear() + } + localOutputChannel.appendLine(value) if (this.tracingConsent.get() === 'Deny') { log = ''