From 3e4279195f3eabdf1a473e0acaa942175ad81d7c Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Fri, 4 May 2018 12:15:58 +0200 Subject: [PATCH 01/64] Resolve promise inside async generator --- src/compiler/transformers/esnext.ts | 9 ++- .../reference/asyncImportNestedYield.js | 9 ++- ...ter.asyncGenerators.classMethods.es2015.js | 81 ++++++++++++++++--- ...mitter.asyncGenerators.classMethods.es5.js | 81 ++++++++++++++++--- ...cGenerators.functionDeclarations.es2015.js | 63 +++++++++++++-- ...syncGenerators.functionDeclarations.es5.js | 63 +++++++++++++-- ...ncGenerators.functionExpressions.es2015.js | 63 +++++++++++++-- ...asyncGenerators.functionExpressions.es5.js | 63 +++++++++++++-- ...cGenerators.objectLiteralMethods.es2015.js | 63 +++++++++++++-- ...syncGenerators.objectLiteralMethods.es5.js | 63 +++++++++++++-- .../reference/emitter.forAwait.es2015.js | 27 ++++++- .../reference/emitter.forAwait.es2017.js | 27 ++++++- .../reference/emitter.forAwait.es5.js | 27 ++++++- 13 files changed, 568 insertions(+), 71 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 68861a5bb43..e60a39eecd2 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -906,7 +906,14 @@ namespace ts { return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/asyncImportNestedYield.js b/tests/baselines/reference/asyncImportNestedYield.js index 0dd76a13ace..4c83c6caf17 100644 --- a/tests/baselines/reference/asyncImportNestedYield.js +++ b/tests/baselines/reference/asyncImportNestedYield.js @@ -38,7 +38,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 2de9f939ba1..639e56f7b7e 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -68,7 +68,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -87,7 +94,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -107,7 +121,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -137,7 +158,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -157,7 +185,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -187,7 +222,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -207,7 +249,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -227,7 +276,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -249,7 +305,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index a91120c4079..359c86683dd 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -95,7 +95,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -147,7 +154,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -205,7 +219,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -273,7 +294,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -342,7 +370,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -428,7 +463,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -486,7 +528,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -538,7 +587,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -603,7 +659,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index d0bf1c902c0..f8d5b9b158e 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -37,7 +37,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -54,7 +61,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -72,7 +86,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -100,7 +121,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -118,7 +146,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -146,7 +181,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -164,7 +206,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index 70cfee32542..9ca02ccdfaa 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -64,7 +64,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -111,7 +118,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -164,7 +178,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -227,7 +248,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -291,7 +319,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -372,7 +407,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -425,7 +467,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index 909196952f0..a25653a10fd 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -37,7 +37,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -54,7 +61,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -72,7 +86,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -100,7 +121,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -118,7 +146,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -146,7 +181,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -164,7 +206,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index c9dff58c7ce..22a934c6f67 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -64,7 +64,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -111,7 +118,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -164,7 +178,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -227,7 +248,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -291,7 +319,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -372,7 +407,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -425,7 +467,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 99caa9d3ad3..9cce459c9da 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -51,7 +51,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -70,7 +77,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -90,7 +104,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -120,7 +141,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -140,7 +168,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -170,7 +205,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -190,7 +232,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 76d74351923..6b50d4c0834 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -78,7 +78,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -127,7 +134,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -182,7 +196,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -247,7 +268,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -313,7 +341,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -396,7 +431,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -451,7 +493,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es2015.js b/tests/baselines/reference/emitter.forAwait.es2015.js index 6b6bdd739fd..ade1964638f 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.js +++ b/tests/baselines/reference/emitter.forAwait.es2015.js @@ -118,7 +118,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -154,7 +161,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -224,7 +238,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es2017.js b/tests/baselines/reference/emitter.forAwait.es2017.js index 8eb21442558..df401094158 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.js +++ b/tests/baselines/reference/emitter.forAwait.es2017.js @@ -98,7 +98,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -134,7 +141,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -194,7 +208,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es5.js b/tests/baselines/reference/emitter.forAwait.es5.js index b4ea4ddcf54..d847c216bb2 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.js +++ b/tests/baselines/reference/emitter.forAwait.es5.js @@ -241,7 +241,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -325,7 +332,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -490,7 +504,14 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function step(r) { + if (r.value instanceof __await) { + Promise.resolve(r.value.v).then(fulfill, reject); + } else if (r.value instanceof Promise) { + r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); + } else { settle(q[0][2], r); } + } + function resolve(r, rv) { return { value: rv, done: r.done }; } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } From f1713c92d34435d59ce089c5e383c91479bd9ee1 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 4 May 2018 10:39:47 -0700 Subject: [PATCH 02/64] Add outlining spans for import declarations --- src/harness/fourslash.ts | 4 +- src/services/outliningElementsCollector.ts | 43 ++++++++++++++++--- src/services/types.ts | 3 +- .../fourslash/getOutliningSpansForImports.ts | 20 +++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/getOutliningSpansForImports.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 8b9929161e2..2c2d921eebf 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2467,7 +2467,7 @@ Actual: ${stringify(fullActual)}`); Harness.IO.log(stringify(spans)); } - public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code") { + public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "import") { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { @@ -4299,7 +4299,7 @@ namespace FourSlashInterface { this.state.verifyCurrentNameOrDottedNameSpanText(text); } - public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code") { + public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "import") { this.state.verifyOutliningSpans(spans, kind); } diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 10684c268be..cca5f843938 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -9,7 +9,35 @@ namespace ts.OutliningElementsCollector { function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { let depthRemaining = 40; - sourceFile.forEachChild(function walk(n) { + let current = 0; + const statements = sourceFile.statements; + const n = statements.length; + while (current < n) { + while (current < n && !isAnyImportSyntax(statements[current])) { + visitNonImportNode(statements[current]); + current++; + } + if (current === n) break; + const firstImport = statements[current]; + while (current < n && isAnyImportSyntax(statements[current])) { + visitImportNode(statements[current] as AnyImportSyntax, sourceFile, cancellationToken, out); + current++; + } + const lastImport = current < n ? statements[current - 1] : statements[n - 1]; + if (lastImport !== firstImport) { + out.push(createOutliningSpanFromBounds(findChildOfKind(firstImport, SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), lastImport.getEnd(), OutliningSpanKind.Import)); + } + } + + function visitImportNode(node: AnyImportSyntax, sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push) { + // Add outlining spans for comments if they exist + addOutliningForLeadingCommentsForNode(node, sourceFile, cancellationToken, out); + // Add outlining spans for the import statement itself if applicable + const span = getOutliningSpanForNode(node, sourceFile); + if (span) out.push(span); + } + + function visitNonImportNode(n: Node) { if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); @@ -23,17 +51,17 @@ namespace ts.OutliningElementsCollector { depthRemaining--; if (isIfStatement(n) && n.elseStatement && isIfStatement(n.elseStatement)) { // Consider an 'else if' to be on the same depth as the 'if'. - walk(n.expression); - walk(n.thenStatement); + visitNonImportNode(n.expression); + visitNonImportNode(n.thenStatement); depthRemaining++; - walk(n.elseStatement); + visitNonImportNode(n.elseStatement); depthRemaining--; } else { - n.forEachChild(walk); + n.forEachChild(visitNonImportNode); } depthRemaining++; - }); + } } function addRegionOutliningSpans(sourceFile: SourceFile, out: Push): void { @@ -149,6 +177,9 @@ namespace ts.OutliningElementsCollector { return spanForObjectOrArrayLiteral(n); case SyntaxKind.ArrayLiteralExpression: return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken); + case SyntaxKind.ImportDeclaration: + const importClause = (n as ImportDeclaration).importClause; + return importClause && importClause.namedBindings && importClause.namedBindings.kind !== SyntaxKind.NamespaceImport ? spanForNode(importClause.namedBindings) : undefined; } function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { diff --git a/src/services/types.ts b/src/services/types.ts index 31baf7df399..48eb25f8a3e 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -826,7 +826,8 @@ namespace ts { export const enum OutliningSpanKind { Comment = "comment", Region = "region", - Code = "code" + Code = "code", + Import = "import" } export const enum OutputFileType { diff --git a/tests/cases/fourslash/getOutliningSpansForImports.ts b/tests/cases/fourslash/getOutliningSpansForImports.ts new file mode 100644 index 00000000000..23b625059c5 --- /dev/null +++ b/tests/cases/fourslash/getOutliningSpansForImports.ts @@ -0,0 +1,20 @@ +/// + + +////[|import * as ns from "mod"; +//// +////import d from "mod"; +////import { a, b, c } from "mod"; +//// +////import r = require("mod");|] +//// +////// statement +////var x = 0; +//// +////// another set of imports +////[|import * as ns from "mod"; +////import d from "mod"; +////import { a, b, c } from "mod"; +////import r = require("mod");|] + +verify.outliningSpansInCurrentFile(test.ranges(), "import"); From 2d725feb51a317905daea8b5abc7b36edd260211 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 4 May 2018 11:26:03 -0700 Subject: [PATCH 03/64] Add outlining span for named bindings in import declarations --- src/services/outliningElementsCollector.ts | 17 +++++++++++------ .../fourslash/getOutliningSpansForImports.ts | 4 ++-- ...OutliningSpansForImportsWithNamedBindings.ts | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index cca5f843938..c58e122356a 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -33,8 +33,16 @@ namespace ts.OutliningElementsCollector { // Add outlining spans for comments if they exist addOutliningForLeadingCommentsForNode(node, sourceFile, cancellationToken, out); // Add outlining spans for the import statement itself if applicable - const span = getOutliningSpanForNode(node, sourceFile); - if (span) out.push(span); + if (isImportDeclaration(node) && node.importClause && node.importClause.namedBindings && + node.importClause.namedBindings.kind !== SyntaxKind.NamespaceImport && node.importClause.namedBindings.elements.length) { + const openToken = findChildOfKind(node.importClause.namedBindings, SyntaxKind.OpenBraceToken, sourceFile); + const closeToken = findChildOfKind(node.importClause.namedBindings, SyntaxKind.CloseBraceToken, sourceFile); + if (openToken && closeToken) { + out.push(createOutliningSpan( + createTextSpanFromBounds(openToken.getStart(sourceFile), closeToken.getEnd()), + OutliningSpanKind.Import, createTextSpanFromNode(node, sourceFile))); + } + } } function visitNonImportNode(n: Node) { @@ -177,10 +185,7 @@ namespace ts.OutliningElementsCollector { return spanForObjectOrArrayLiteral(n); case SyntaxKind.ArrayLiteralExpression: return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken); - case SyntaxKind.ImportDeclaration: - const importClause = (n as ImportDeclaration).importClause; - return importClause && importClause.namedBindings && importClause.namedBindings.kind !== SyntaxKind.NamespaceImport ? spanForNode(importClause.namedBindings) : undefined; - } + } function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { // If the block has no leading keywords and is inside an array literal, diff --git a/tests/cases/fourslash/getOutliningSpansForImports.ts b/tests/cases/fourslash/getOutliningSpansForImports.ts index 23b625059c5..198adc9c551 100644 --- a/tests/cases/fourslash/getOutliningSpansForImports.ts +++ b/tests/cases/fourslash/getOutliningSpansForImports.ts @@ -4,7 +4,7 @@ ////[|import * as ns from "mod"; //// ////import d from "mod"; -////import { a, b, c } from "mod"; +////import [|{ a, b, c }|] from "mod"; //// ////import r = require("mod");|] //// @@ -14,7 +14,7 @@ ////// another set of imports ////[|import * as ns from "mod"; ////import d from "mod"; -////import { a, b, c } from "mod"; +////import [|{ a, b, c }|] from "mod"; ////import r = require("mod");|] verify.outliningSpansInCurrentFile(test.ranges(), "import"); diff --git a/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts b/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts new file mode 100644 index 00000000000..4e5336ba3b0 --- /dev/null +++ b/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts @@ -0,0 +1,17 @@ +/// + + +////[|import [|{ +//// a, +//// b as B, +//// c +////}|] from "mod"; +//// +//// +////import { } from "mod"; +////import * as ns from "mod"; +////import d from "mod";|] + +verify.outliningSpansInCurrentFile(test.ranges(), "import"); + + From dae112668045b01771673812b9cde544f5229437 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 4 May 2018 11:27:10 -0700 Subject: [PATCH 04/64] Accept baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 3 ++- tests/baselines/reference/api/typescript.d.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c52960b574b..5e99f782526 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4880,7 +4880,8 @@ declare namespace ts { enum OutliningSpanKind { Comment = "comment", Region = "region", - Code = "code" + Code = "code", + Import = "import" } enum OutputFileType { JavaScript = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 9c2639305df..59dcc58e187 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4880,7 +4880,8 @@ declare namespace ts { enum OutliningSpanKind { Comment = "comment", Region = "region", - Code = "code" + Code = "code", + Import = "import" } enum OutputFileType { JavaScript = 0, From a59ac8fd33f62a9519fa5dfb50e341995145f7ca Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 4 May 2018 11:29:54 -0700 Subject: [PATCH 05/64] Update test --- tests/cases/fourslash/incrementalParsingWithJsDoc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/fourslash/incrementalParsingWithJsDoc.ts b/tests/cases/fourslash/incrementalParsingWithJsDoc.ts index cd709530f9c..324cc0608ab 100644 --- a/tests/cases/fourslash/incrementalParsingWithJsDoc.ts +++ b/tests/cases/fourslash/incrementalParsingWithJsDoc.ts @@ -1,8 +1,8 @@ /// -////import a from 'a/aaaaaaa/aaaaaaa/aaaaaa/aaaaaaa'; +////[|import a from 'a/aaaaaaa/aaaaaaa/aaaaaa/aaaaaaa'; /////**/import b from 'b'; -////import c from 'c'; +////import c from 'c';|] //// ////[|/** @internal */|] ////export class LanguageIdentifier[| { }|] From 5ecfa782fcc012d0a86b186604e7cc2811036110 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 3 May 2018 10:52:24 -0700 Subject: [PATCH 06/64] Few renames to distinguish between fs File and File in the test case to load in the VFS with watch --- src/harness/unittests/compileOnSave.ts | 38 +- src/harness/unittests/organizeImports.ts | 8 +- .../unittests/reuseProgramStructure.ts | 38 +- src/harness/unittests/telemetry.ts | 2 +- src/harness/unittests/tscWatchMode.ts | 155 +++---- .../unittests/tsserverProjectSystem.ts | 402 +++++++++--------- src/harness/unittests/typingsInstaller.ts | 22 +- src/harness/virtualFileSystemWithWatch.ts | 171 ++++---- 8 files changed, 428 insertions(+), 408 deletions(-) diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 0efd8662cf1..df73c575b15 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -11,7 +11,7 @@ namespace ts.projectSystem { } describe("CompileOnSave affected list", () => { - function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { + function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: File[] }[]) { const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; const actualResult = response.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); expectedFileList = expectedFileList.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); @@ -47,12 +47,12 @@ namespace ts.projectSystem { } describe("for configured projects", () => { - let moduleFile1: FileOrFolder; - let file1Consumer1: FileOrFolder; - let file1Consumer2: FileOrFolder; - let moduleFile2: FileOrFolder; - let globalFile3: FileOrFolder; - let configFile: FileOrFolder; + let moduleFile1: File; + let file1Consumer1: File; + let file1Consumer2: File; + let moduleFile2: File; + let globalFile3: File; + let configFile: File; let changeModuleFile1ShapeRequest1: server.protocol.Request; let changeModuleFile1InternalRequest1: server.protocol.Request; // A compile on save affected file request using file1 @@ -225,7 +225,7 @@ namespace ts.projectSystem { openFilesForSession([moduleFile1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); - const file1Consumer3: FileOrFolder = { + const file1Consumer3: File = { path: "/a/b/file1Consumer3.ts", content: `import {Foo} from "./moduleFile1"; let y = Foo();` }; @@ -330,7 +330,7 @@ namespace ts.projectSystem { }` }; - const configFile2: FileOrFolder = { + const configFile2: File = { path: "/a/tsconfig.json", content: `{ "compileOnSave": true @@ -403,7 +403,7 @@ namespace ts.projectSystem { }); it("should return cascaded affected file list", () => { - const file1Consumer1Consumer1: FileOrFolder = { + const file1Consumer1Consumer1: File = { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";` }; @@ -428,13 +428,13 @@ namespace ts.projectSystem { }); it("should work fine for files with circular references", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: ` /// export var t1 = 10;` }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/file2.ts", content: ` /// @@ -450,11 +450,11 @@ namespace ts.projectSystem { }); it("should return results for all projects if not specifying projectFileName", () => { - const file1: FileOrFolder = { path: "/a/b/file1.ts", content: "export var t = 10;" }; - const file2: FileOrFolder = { path: "/a/b/file2.ts", content: `import {t} from "./file1"; var t2 = 11;` }; - const file3: FileOrFolder = { path: "/a/c/file2.ts", content: `import {t} from "../b/file1"; var t3 = 11;` }; - const configFile1: FileOrFolder = { path: "/a/b/tsconfig.json", content: `{ "compileOnSave": true }` }; - const configFile2: FileOrFolder = { path: "/a/c/tsconfig.json", content: `{ "compileOnSave": true }` }; + const file1: File = { path: "/a/b/file1.ts", content: "export var t = 10;" }; + const file2: File = { path: "/a/b/file2.ts", content: `import {t} from "./file1"; var t2 = 11;` }; + const file3: File = { path: "/a/c/file2.ts", content: `import {t} from "../b/file1"; var t3 = 11;` }; + const configFile1: File = { path: "/a/b/tsconfig.json", content: `{ "compileOnSave": true }` }; + const configFile2: File = { path: "/a/c/tsconfig.json", content: `{ "compileOnSave": true }` }; const host = createServerHost([file1, file2, file3, configFile1, configFile2]); const session = createSession(host); @@ -469,7 +469,7 @@ namespace ts.projectSystem { }); it("should detect removed code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -490,7 +490,7 @@ namespace ts.projectSystem { }); it("should detect non-existing code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// diff --git a/src/harness/unittests/organizeImports.ts b/src/harness/unittests/organizeImports.ts index 4471600b1c1..ebd5a7925a2 100644 --- a/src/harness/unittests/organizeImports.ts +++ b/src/harness/unittests/organizeImports.ts @@ -446,11 +446,11 @@ import { React, Other } from "react"; }, reactLibFile); - function testOrganizeImports(testName: string, testFile: TestFSWithWatch.FileOrFolder, ...otherFiles: TestFSWithWatch.FileOrFolder[]) { + function testOrganizeImports(testName: string, testFile: TestFSWithWatch.File, ...otherFiles: TestFSWithWatch.File[]) { it(testName, () => runBaseline(`organizeImports/${testName}.ts`, testFile, ...otherFiles)); } - function runBaseline(baselinePath: string, testFile: TestFSWithWatch.FileOrFolder, ...otherFiles: TestFSWithWatch.FileOrFolder[]) { + function runBaseline(baselinePath: string, testFile: TestFSWithWatch.File, ...otherFiles: TestFSWithWatch.File[]) { const { path: testPath, content: testContent } = testFile; const languageService = makeLanguageService(testFile, ...otherFiles); const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatOptions, defaultPreferences); @@ -468,7 +468,7 @@ import { React, Other } from "react"; }); } - function makeLanguageService(...files: TestFSWithWatch.FileOrFolder[]) { + function makeLanguageService(...files: TestFSWithWatch.File[]) { const host = projectSystem.createServerHost(files); const projectService = projectSystem.createProjectService(host, { useSingleInferredProject: true }); projectService.setCompilerOptionsForInferredProjects({ jsx: files.some(f => f.path.endsWith("x")) ? JsxEmit.React : JsxEmit.None }); @@ -555,4 +555,4 @@ import { React, Other } from "react"; } } }); -} \ No newline at end of file +} diff --git a/src/harness/unittests/reuseProgramStructure.ts b/src/harness/unittests/reuseProgramStructure.ts index 0ba9e6f6351..74037d79418 100644 --- a/src/harness/unittests/reuseProgramStructure.ts +++ b/src/harness/unittests/reuseProgramStructure.ts @@ -884,7 +884,7 @@ namespace ts { }); }); - type FileOrFolder = TestFSWithWatch.FileOrFolder; + type File = TestFSWithWatch.File; import createTestSystem = TestFSWithWatch.createWatchedSystem; import libFile = TestFSWithWatch.libFile; @@ -920,22 +920,22 @@ namespace ts { verifyProgramIsUptoDate(program, fileNames, options); } - function verifyProgram(files: FileOrFolder[], rootFiles: string[], options: CompilerOptions, configFile: string) { + function verifyProgram(files: File[], rootFiles: string[], options: CompilerOptions, configFile: string) { const system = createTestSystem(files); verifyProgramWithoutConfigFile(system, rootFiles, options); verifyProgramWithConfigFile(system, configFile); } it("has empty options", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: "let x = 1" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/file2.ts", content: "let y = 1" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "{}" }; @@ -944,19 +944,19 @@ namespace ts { it("has lib specified in the options", () => { const compilerOptions: CompilerOptions = { lib: ["es5", "es2015.promise"] }; - const app: FileOrFolder = { + const app: File = { path: "/src/app.ts", content: "var x: Promise;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/src/tsconfig.json", content: JSON.stringify({ compilerOptions }) }; - const es5Lib: FileOrFolder = { + const es5Lib: File = { path: "/compiler/lib.es5.d.ts", content: "declare const eval: any" }; - const es2015Promise: FileOrFolder = { + const es2015Promise: File = { path: "/compiler/lib.es2015.promise.d.ts", content: "declare class Promise {}" }; @@ -975,26 +975,26 @@ namespace ts { ] } }; - const app: FileOrFolder = { + const app: File = { path: "/src/packages/framework/app.ts", content: 'import classc from "module1/lib/file1";\ import classD from "module3/file3";\ let x = new classc();\ let y = new classD();' }; - const module1: FileOrFolder = { + const module1: File = { path: "/src/packages/mail/data/module1/lib/file1.ts", content: 'import classc from "module2/file2";export default classc;', }; - const module2: FileOrFolder = { + const module2: File = { path: "/src/packages/mail/data/module1/lib/module2/file2.ts", content: 'class classc { method2() { return "hello"; } }\nexport default classc', }; - const module3: FileOrFolder = { + const module3: File = { path: "/src/packages/styles/module3/file3.ts", content: "class classD { method() { return 10; } }\nexport default classD;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/src/tsconfig.json", content: JSON.stringify({ compilerOptions }) }; @@ -1013,26 +1013,26 @@ namespace ts { ] } }; - const app: FileOrFolder = { + const app: File = { path: "/src/packages/framework/app.ts", content: 'import classc from "module1/lib/file1";\ import classD from "module3/file3";\ let x = new classc();\ let y = new classD();' }; - const module1: FileOrFolder = { + const module1: File = { path: "/src/packages/mail/data/module1/lib/file1.ts", content: 'import classc from "module2/file2";export default classc;', }; - const module2: FileOrFolder = { + const module2: File = { path: "/src/packages/mail/data/module1/lib/module2/file2.ts", content: 'class classc { method2() { return "hello"; } }\nexport default classc', }; - const module3: FileOrFolder = { + const module3: File = { path: "/src/packages/styles/module3/file3.ts", content: "class classD { method() { return 10; } }\nexport default classD;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/src/tsconfig.json", content: JSON.stringify({ compilerOptions, include: ["packages/**/*.ts"] }) }; diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index 27512ba1e8c..2e3e299ac3b 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -236,7 +236,7 @@ namespace ts.projectSystem { }); }); - function makeFile(path: string, content: {} = ""): FileOrFolder { + function makeFile(path: string, content: {} = ""): File { return { path, content: isString(content) ? "" : JSON.stringify(content) }; } } diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index b64b02e301a..f3194d68dcd 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -4,7 +4,8 @@ namespace ts.tscWatch { import WatchedSystem = TestFSWithWatch.TestServerHost; - type FileOrFolder = TestFSWithWatch.FileOrFolder; + type File = TestFSWithWatch.File; + type SymLink = TestFSWithWatch.SymLink; import createWatchedSystem = TestFSWithWatch.createWatchedSystem; import checkArray = TestFSWithWatch.checkArray; import libFile = TestFSWithWatch.libFile; @@ -33,7 +34,7 @@ namespace ts.tscWatch { return () => watch.getCurrentProgram().getProgram(); } - function getEmittedLineForMultiFileOutput(file: FileOrFolder, host: WatchedSystem) { + function getEmittedLineForMultiFileOutput(file: File, host: WatchedSystem) { return `TSFILE: ${file.path.replace(".ts", ".js")}${host.newLine}`; } @@ -41,11 +42,11 @@ namespace ts.tscWatch { return `TSFILE: ${filename}${host.newLine}`; } - interface FileOrFolderEmit extends FileOrFolder { + interface FileOrFolderEmit extends File { output?: string; } - function getFileOrFolderEmit(file: FileOrFolder, getOutput?: (file: FileOrFolder) => string): FileOrFolderEmit { + function getFileOrFolderEmit(file: File, getOutput?: (file: File) => string): FileOrFolderEmit { const result = file as FileOrFolderEmit; if (getOutput) { result.output = getOutput(file); @@ -202,7 +203,7 @@ namespace ts.tscWatch { return getDiagnosticOfFileFrom(file, text, start, length, message); } - function getUnknownCompilerOption(program: Program, configFile: FileOrFolder, option: string) { + function getUnknownCompilerOption(program: Program, configFile: File, option: string) { const quotedOption = `"${option}"`; return getDiagnosticOfFile(program.getCompilerOptions().configFile, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option); } @@ -218,23 +219,23 @@ namespace ts.tscWatch { text, start, length, message); } - function getDiagnosticModuleNotFoundOfFile(program: Program, file: FileOrFolder, moduleName: string) { + function getDiagnosticModuleNotFoundOfFile(program: Program, file: File, moduleName: string) { const quotedModuleName = `"${moduleName}"`; return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0, moduleName); } describe("tsc-watch program updates", () => { - const commonFile1: FileOrFolder = { + const commonFile1: File = { path: "/a/b/commonFile1.ts", content: "let x = 1" }; - const commonFile2: FileOrFolder = { + const commonFile2: File = { path: "/a/b/commonFile2.ts", content: "let y = 1" }; it("create watch without config file", () => { - const appFile: FileOrFolder = { + const appFile: File = { path: "/a/b/c/app.ts", content: ` import {f} from "./module" @@ -242,7 +243,7 @@ namespace ts.tscWatch { ` }; - const moduleFile: FileOrFolder = { + const moduleFile: File = { path: "/a/b/c/module.d.ts", content: `export let x: number` }; @@ -277,7 +278,7 @@ namespace ts.tscWatch { }); it("create configured project without file list", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: ` { @@ -287,15 +288,15 @@ namespace ts.tscWatch { ] }` }; - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/c/f1.ts", content: "let x = 1" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/d/f2.ts", content: "let y = 1" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/e/f3.ts", content: "let z = 1" }; @@ -315,7 +316,7 @@ namespace ts.tscWatch { // }); it("add new files to a configured program without file list", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; @@ -333,7 +334,7 @@ namespace ts.tscWatch { }); it("should ignore non-existing files specified in the config file", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -352,7 +353,7 @@ namespace ts.tscWatch { }); it("handle recreated files correctly", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; @@ -373,7 +374,7 @@ namespace ts.tscWatch { it("handles the missing files - that were added to program because they were added with /// { const commonFile2Name = "commonFile2.ts"; - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/commonFile1.ts", content: `/// let x = y` @@ -396,7 +397,7 @@ namespace ts.tscWatch { }); it("should reflect change in config file", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -419,7 +420,7 @@ namespace ts.tscWatch { }); it("works correctly when config file is changed but its content havent", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -441,14 +442,14 @@ namespace ts.tscWatch { }); it("files explicitly excluded in config file", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, "exclude": ["/a/c"] }` }; - const excludedFile1: FileOrFolder = { + const excludedFile1: File = { path: "/a/c/excluedFile1.ts", content: `let t = 1;` }; @@ -459,19 +460,19 @@ namespace ts.tscWatch { }); it("should properly handle module resolution changes in config file", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: `import { T } from "module1";` }; - const nodeModuleFile: FileOrFolder = { + const nodeModuleFile: File = { path: "/a/b/node_modules/module1.ts", content: `export interface T {}` }; - const classicModuleFile: FileOrFolder = { + const classicModuleFile: File = { path: "/a/module1.ts", content: `export interface T {}` }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -499,7 +500,7 @@ namespace ts.tscWatch { }); it("should tolerate config file errors and still try to build a project", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1117,15 +1118,15 @@ namespace ts.tscWatch { it("should not trigger recompilation because of program emit", () => { const proj = "/user/username/projects/myproject"; - const file1: FileOrFolder = { + const file1: File = { path: `${proj}/file1.ts`, content: "export const c = 30;" }; - const file2: FileOrFolder = { + const file2: File = { path: `${proj}/src/file2.ts`, content: `import {c} from "file1"; export const d = 30;` }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${proj}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -1153,7 +1154,7 @@ namespace ts.tscWatch { one(); } }`; - const file: FileOrFolder = { + const file: File = { path: "/a/b/file.ts", content: getFileContent(/*asModule*/ false) }; @@ -1174,11 +1175,11 @@ namespace ts.tscWatch { it("watched files when file is deleted and new file is added as part of change", () => { const projectLocation = "/home/username/project"; - const file: FileOrFolder = { + const file: File = { path: `${projectLocation}/src/file1.ts`, content: "var a = 10;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectLocation}/tsconfig.json`, content: "{}" }; @@ -1211,7 +1212,7 @@ namespace ts.tscWatch { }) }; - let getOutput: (file: FileOrFolder) => string; + let getOutput: (file: File) => string; if (out) { config.content = JSON.stringify({ compilerOptions: { listEmittedFiles: true, out } @@ -1266,23 +1267,23 @@ namespace ts.tscWatch { }); function verifyFilesEmittedOnce(useOutFile: boolean) { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/output/AnotherDependency/file1.d.ts", content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/dependencies/file2.d.ts", content: "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/project/src/main.ts", content: "namespace Main { export function fooBar() {} }" }; - const file4: FileOrFolder = { + const file4: File = { path: "/a/b/project/src/main2.ts", content: "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: useOutFile ? @@ -1334,16 +1335,16 @@ namespace ts.tscWatch { /** list of the files that will be emitted for first compilation */ firstCompilationEmitFiles?: string[]; /** get the emit file for file - default is multi file emit line */ - getEmitLine?(file: FileOrFolder, host: WatchedSystem): string; + getEmitLine?(file: File, host: WatchedSystem): string; /** Additional files and folders to add */ - getAdditionalFileOrFolder?(): FileOrFolder[]; + getAdditionalFileOrFolder?(): File[]; /** initial list of files to emit if not the default list */ firstReloadFileList?: string[]; } function getInitialState({ configObj = {}, firstCompilationEmitFiles, getEmitLine, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}) { const host = createWatchedSystem([]); - const getOutputName = getEmitLine ? (file: FileOrFolder) => getEmitLine(file, host) : - (file: FileOrFolder) => getEmittedLineForMultiFileOutput(file, host); + const getOutputName = getEmitLine ? (file: File) => getEmitLine(file, host) : + (file: File) => getEmittedLineForMultiFileOutput(file, host); const moduleFile1 = getFileOrFolderEmit({ path: moduleFile1Path, @@ -1555,7 +1556,7 @@ namespace ts.tscWatch { }); it("should return cascaded affected file list", () => { - const file1Consumer1Consumer1: FileOrFolder = { + const file1Consumer1Consumer1: File = { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";` }; @@ -1582,13 +1583,13 @@ namespace ts.tscWatch { it("should work fine for files with circular references", () => { // TODO: do not exit on such errors? Just continue to watch the files for update in watch mode - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: ` /// export var t1 = 10;` }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/file2.ts", content: ` /// @@ -1611,7 +1612,7 @@ namespace ts.tscWatch { }); it("should detect removed code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -1632,7 +1633,7 @@ namespace ts.tscWatch { }); it("should detect non-existing code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -1659,7 +1660,7 @@ namespace ts.tscWatch { }); describe("tsc-watch emit file content", () => { - interface EmittedFile extends FileOrFolder { + interface EmittedFile extends File { shouldBeWritten: boolean; } function getEmittedFiles(files: FileOrFolderEmit[], contents: string[]): EmittedFile[] { @@ -1684,8 +1685,8 @@ namespace ts.tscWatch { } } - function verifyEmittedFileContents(newLine: string, inputFiles: FileOrFolder[], initialEmittedFileContents: string[], - modifyFiles: (files: FileOrFolderEmit[], emitedFiles: EmittedFile[]) => FileOrFolderEmit[], configFile?: FileOrFolder) { + function verifyEmittedFileContents(newLine: string, inputFiles: File[], initialEmittedFileContents: string[], + modifyFiles: (files: FileOrFolderEmit[], emitedFiles: EmittedFile[]) => FileOrFolderEmit[], configFile?: File) { const host = createWatchedSystem([], { newLine }); const files = concatenate( map(inputFiles, file => getFileOrFolderEmit(file, fileToConvert => getEmittedLineForMultiFileOutput(fileToConvert, host))), @@ -1778,15 +1779,15 @@ namespace ts.tscWatch { it("Elides const enums correctly in incremental compilation", () => { const currentDirectory = "/user/someone/projects/myproject"; - const file1: FileOrFolder = { + const file1: File = { path: `${currentDirectory}/file1.ts`, content: "export const enum E1 { V = 1 }" }; - const file2: FileOrFolder = { + const file2: File = { path: `${currentDirectory}/file2.ts`, content: `import { E1 } from "./file1"; export const enum E2 { V = E1.V }` }; - const file3: FileOrFolder = { + const file3: File = { path: `${currentDirectory}/file3.ts`, content: `import { E2 } from "./file2"; const v: E2 = E2.V;` }; @@ -1808,12 +1809,12 @@ namespace ts.tscWatch { it("file is deleted and created as part of change", () => { const projectLocation = "/home/username/project"; - const file: FileOrFolder = { + const file: File = { path: `${projectLocation}/app/file.ts`, content: "var a = 10;" }; const fileJs = `${projectLocation}/app/file.js`; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectLocation}/tsconfig.json`, content: JSON.stringify({ include: [ @@ -2101,19 +2102,19 @@ declare module "fs" { it("works when reusing program with files from external library", () => { interface ExpectedFile { path: string; isExpectedToEmit?: boolean; content?: string; } const configDir = "/a/b/projects/myProject/src/"; - const file1: FileOrFolder = { + const file1: File = { path: configDir + "file1.ts", content: 'import module1 = require("module1");\nmodule1("hello");' }; - const file2: FileOrFolder = { + const file2: File = { path: configDir + "file2.ts", content: 'import module11 = require("module1");\nmodule11("hello");' }; - const module1: FileOrFolder = { + const module1: File = { path: "/a/b/projects/myProject/node_modules/module1/index.js", content: "module.exports = options => { return options.toString(); }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: configDir + "tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -2169,7 +2170,7 @@ declare module "fs" { }; } - function createExpectedEmittedFile(file: FileOrFolder): ExpectedFile { + function createExpectedEmittedFile(file: File): ExpectedFile { return { path: removeFileExtension(file.path.replace(configDir, outDirFolder)) + Extension.Js, isExpectedToEmit: true, @@ -2180,11 +2181,11 @@ declare module "fs" { it("works when renaming node_modules folder that already contains @types folder", () => { const currentDirectory = "/user/username/projects/myproject"; - const file: FileOrFolder = { + const file: File = { path: `${currentDirectory}/a.ts`, content: `import * as q from "qqq";` }; - const module: FileOrFolder = { + const module: File = { path: `${currentDirectory}/node_modules2/@types/qqq/index.d.ts`, content: "export {}" }; @@ -2203,7 +2204,7 @@ declare module "fs" { describe("tsc-watch with when module emit is specified as node", () => { it("when instead of filechanged recursive directory watcher is invoked", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/rootFolder/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -2217,11 +2218,11 @@ declare module "fs" { }) }; const outputFolder = "/a/rootFolder/project/Static/scripts/"; - const file1: FileOrFolder = { + const file1: File = { path: "/a/rootFolder/project/Scripts/TypeScript.ts", content: "var z = 10;" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/rootFolder/project/Scripts/Javascript.js", content: "var zz = 10;" }; @@ -2299,7 +2300,7 @@ declare module "fs" { describe("tsc-watch with different polling/non polling options", () => { it("watchFile using dynamic priority polling", () => { const projectFolder = "/a/username/project"; - const file1: FileOrFolder = { + const file1: File = { path: `${projectFolder}/typescript.ts`, content: "var z = 10;" }; @@ -2362,11 +2363,11 @@ declare module "fs" { function verifyRenamingFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) { const projectFolder = "/a/username/project"; const projectSrcFolder = `${projectFolder}/src`; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: "{}" }; - const file: FileOrFolder = { + const file: File = { path: `${projectSrcFolder}/file1.ts`, content: "" }; @@ -2428,35 +2429,35 @@ declare module "fs" { it("when there are symlinks to folders in recursive folders", () => { const cwd = "/home/user/projects/myproject"; - const file1: FileOrFolder = { + const file1: File = { path: `${cwd}/src/file.ts`, content: `import * as a from "a"` }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${cwd}/tsconfig.json`, content: `{ "compilerOptions": { "extendedDiagnostics": true, "traceResolution": true }}` }; - const realA: FileOrFolder = { + const realA: File = { path: `${cwd}/node_modules/reala/index.d.ts`, content: `export {}` }; - const realB: FileOrFolder = { + const realB: File = { path: `${cwd}/node_modules/realb/index.d.ts`, content: `export {}` }; - const symLinkA: FileOrFolder = { + const symLinkA: SymLink = { path: `${cwd}/node_modules/a`, symLink: `${cwd}/node_modules/reala` }; - const symLinkB: FileOrFolder = { + const symLinkB: SymLink = { path: `${cwd}/node_modules/b`, symLink: `${cwd}/node_modules/realb` }; - const symLinkBInA: FileOrFolder = { + const symLinkBInA: SymLink = { path: `${cwd}/node_modules/reala/node_modules/b`, symLink: `${cwd}/node_modules/b` }; - const symLinkAInB: FileOrFolder = { + const symLinkAInB: SymLink = { path: `${cwd}/node_modules/realb/node_modules/a`, symLink: `${cwd}/node_modules/a` }; diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5f04b643a35..bed1940ee88 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -8,7 +8,9 @@ namespace ts.projectSystem { import CommandNames = server.CommandNames; export import TestServerHost = TestFSWithWatch.TestServerHost; - export type FileOrFolder = TestFSWithWatch.FileOrFolder; + export type File = TestFSWithWatch.File; + export type SymLink = TestFSWithWatch.SymLink; + export type Folder = TestFSWithWatch.Folder; export import createServerHost = TestFSWithWatch.createServerHost; export import checkArray = TestFSWithWatch.checkArray; export import libFile = TestFSWithWatch.libFile; @@ -170,7 +172,7 @@ namespace ts.projectSystem { readonly session: TestSession; readonly service: server.ProjectService; readonly host: TestServerHost; - constructor(files: FileOrFolder[], suppressDiagnosticEvents?: boolean) { + constructor(files: File[], suppressDiagnosticEvents?: boolean) { this.host = createServerHost(files); this.session = createSession(this.host, { canUseEvents: true, @@ -394,7 +396,7 @@ namespace ts.projectSystem { return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } - function checkOpenFiles(projectService: server.ProjectService, expectedFiles: FileOrFolder[]) { + function checkOpenFiles(projectService: server.ProjectService, expectedFiles: File[]) { checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path)); } @@ -451,7 +453,7 @@ namespace ts.projectSystem { return newRequest; } - export function openFilesForSession(files: FileOrFolder[], session: server.Session) { + export function openFilesForSession(files: File[], session: server.Session) { for (const file of files) { const request = makeSessionRequest(CommandNames.Open, { file: file.path }); session.executeCommand(request); @@ -512,17 +514,17 @@ namespace ts.projectSystem { } describe("tsserverProjectSystem general functionality", () => { - const commonFile1: FileOrFolder = { + const commonFile1: File = { path: "/a/b/commonFile1.ts", content: "let x = 1" }; - const commonFile2: FileOrFolder = { + const commonFile2: File = { path: "/a/b/commonFile2.ts", content: "let y = 1" }; it("create inferred project", () => { - const appFile: FileOrFolder = { + const appFile: File = { path: "/a/b/c/app.ts", content: ` import {f} from "./module" @@ -530,7 +532,7 @@ namespace ts.projectSystem { ` }; - const moduleFile: FileOrFolder = { + const moduleFile: File = { path: "/a/b/c/module.d.ts", content: `export let x: number` }; @@ -583,7 +585,7 @@ namespace ts.projectSystem { }); it("create configured project without file list", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: ` { @@ -593,15 +595,15 @@ namespace ts.projectSystem { ] }` }; - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/c/f1.ts", content: "let x = 1" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/d/f2.ts", content: "let y = 1" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/e/f3.ts", content: "let z = 1" }; @@ -625,7 +627,7 @@ namespace ts.projectSystem { }); it("create configured project with the file list", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: ` { @@ -633,15 +635,15 @@ namespace ts.projectSystem { "include": ["*.ts"] }` }; - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/f1.ts", content: "let x = 1" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/f2.ts", content: "let y = 1" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/c/f3.ts", content: "let z = 1" }; @@ -664,7 +666,7 @@ namespace ts.projectSystem { }); it("add and then remove a config file in a folder with loose files", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "files": ["commonFile1.ts"] @@ -713,7 +715,7 @@ namespace ts.projectSystem { }); it("add new files to a configured project without file list", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; @@ -735,7 +737,7 @@ namespace ts.projectSystem { }); it("should ignore non-existing files specified in the config file", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -769,7 +771,7 @@ namespace ts.projectSystem { path: "/c/app.ts", content: "let x = 1" }; - const makeProject = (f: FileOrFolder) => ({ projectFileName: f.path + ".csproj", rootFiles: [toExternalFile(f.path)], options: {} }); + const makeProject = (f: File) => ({ projectFileName: f.path + ".csproj", rootFiles: [toExternalFile(f.path)], options: {} }); const p1 = makeProject(f1); const p2 = makeProject(f2); const p3 = makeProject(f3); @@ -817,7 +819,7 @@ namespace ts.projectSystem { }); it("handle recreated files correctly", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; @@ -841,7 +843,7 @@ namespace ts.projectSystem { }); it("handles the missing files - that were added to program because they were added with /// { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/commonFile1.ts", content: `/// let x = y` @@ -878,7 +880,7 @@ namespace ts.projectSystem { }); it("should create new inferred projects for files excluded from a configured project", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -909,14 +911,14 @@ namespace ts.projectSystem { }); it("files explicitly excluded in config file", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, "exclude": ["/a/c"] }` }; - const excludedFile1: FileOrFolder = { + const excludedFile1: File = { path: "/a/c/excluedFile1.ts", content: `let t = 1;` }; @@ -933,23 +935,23 @@ namespace ts.projectSystem { }); it("should properly handle module resolution changes in config file", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: `import { T } from "module1";` }; - const nodeModuleFile: FileOrFolder = { + const nodeModuleFile: File = { path: "/a/b/node_modules/module1.ts", content: `export interface T {}` }; - const classicModuleFile: FileOrFolder = { + const classicModuleFile: File = { path: "/a/module1.ts", content: `export interface T {}` }; - const randomFile: FileOrFolder = { + const randomFile: File = { path: "/a/file1.ts", content: `export interface T {}` }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -998,15 +1000,15 @@ namespace ts.projectSystem { }); it("should keep the configured project when the opened file is referenced by the project but not its root", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/main.ts", content: "import { objA } from './obj-a';" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/obj-a.ts", content: `export const objA = Object.assign({foo: "bar"}, {bar: "baz"});` }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1025,15 +1027,15 @@ namespace ts.projectSystem { }); it("should keep the configured project when the opened file is referenced by the project but not its root", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/main.ts", content: "import { objA } from './obj-a';" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/obj-a.ts", content: `export const objA = Object.assign({foo: "bar"}, {bar: "baz"});` }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1051,7 +1053,7 @@ namespace ts.projectSystem { checkNumberOfInferredProjects(projectService, 0); }); it("should tolerate config file errors and still try to build a project", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1108,7 +1110,7 @@ namespace ts.projectSystem { path: "/a/b/main.ts", content: "let x =1;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1154,7 +1156,7 @@ namespace ts.projectSystem { path: "/a/b/main2.ts", content: "let y =1;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -1188,7 +1190,7 @@ namespace ts.projectSystem { path: "/a/b/main.ts", content: "let x =1;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -2449,19 +2451,19 @@ namespace ts.projectSystem { }); it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4: FileOrFolder = { + const file4: File = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -2527,7 +2529,7 @@ namespace ts.projectSystem { checkProjectActualFiles(inferredProject4, [file4.path]); assert.strictEqual(inferredProject5, inferredProject4); - const file5: FileOrFolder = { + const file5: File = { path: "/file5.ts", content: "let zz = 1;" }; @@ -2545,7 +2547,7 @@ namespace ts.projectSystem { infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); } - function verifyScriptInfosAreUndefined(files: FileOrFolder[]) { + function verifyScriptInfosAreUndefined(files: File[]) { for (const file of files) { assert.isUndefined(projectService.getScriptInfoForPath(file.path as Path)); } @@ -2561,19 +2563,19 @@ namespace ts.projectSystem { }); it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3: FileOrFolder = { + const file3: File = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4: FileOrFolder = { + const file4: File = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -2943,19 +2945,19 @@ namespace ts.projectSystem { }); it("Changed module resolution reflected when specifying files list", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: 'import classc from "file2"' }; - const file2a: FileOrFolder = { + const file2a: File = { path: "/a/file2.ts", content: "export classc { method2a() { return 10; } }" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/file2.ts", content: "export classc { method2() { return 10; } }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ files: [file1.path], compilerOptions: { module: "amd" } }) }; @@ -2997,24 +2999,24 @@ namespace ts.projectSystem { it("Failed lookup locations uses parent most node_modules directory", () => { const root = "/user/username/rootfolder"; - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/src/file1.ts", content: 'import { classc } from "module1"' }; - const module1: FileOrFolder = { + const module1: File = { path: "/a/b/node_modules/module1/index.d.ts", content: `import { class2 } from "module2"; export classc { method2a(): class2; }` }; - const module2: FileOrFolder = { + const module2: File = { path: "/a/b/node_modules/module2/index.d.ts", content: "export class2 { method2() { return 10; } }" }; - const module3: FileOrFolder = { + const module3: File = { path: "/a/b/node_modules/module/node_modules/module3/index.d.ts", content: "export class3 { method2() { return 10; } }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/src/tsconfig.json", content: JSON.stringify({ files: ["file1.ts"] }) }; @@ -3036,7 +3038,7 @@ namespace ts.projectSystem { }); it("Properly handle Windows-style outDir", () => { - const configFile: FileOrFolder = { + const configFile: File = { path: "C:\\a\\tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -3045,7 +3047,7 @@ namespace ts.projectSystem { include: ["*.ts"] }) }; - const file1: FileOrFolder = { + const file1: File = { path: "C:\\a\\f1.ts", content: "let x = 1;" }; @@ -3062,7 +3064,7 @@ namespace ts.projectSystem { }); it("dynamic file without external project", () => { - const file: FileOrFolder = { + const file: File = { path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js", content: "var x = 10;" }; @@ -3101,19 +3103,19 @@ namespace ts.projectSystem { }); it("files opened, closed affecting multiple projects", () => { - const file: FileOrFolder = { + const file: File = { path: "/a/b/projects/config/file.ts", content: `import {a} from "../files/file1"; export let b = a;` }; - const config: FileOrFolder = { + const config: File = { path: "/a/b/projects/config/tsconfig.json", content: "" }; - const filesFile1: FileOrFolder = { + const filesFile1: File = { path: "/a/b/projects/files/file1.ts", content: "export let a = 10;" }; - const filesFile2: FileOrFolder = { + const filesFile2: File = { path: "/a/b/projects/files/file2.ts", content: "export let aa = 10;" }; @@ -3179,15 +3181,15 @@ namespace ts.projectSystem { it("requests are done on file on pendingReload but has svc for previous version", () => { const projectLocation = "/user/username/projects/project"; - const file1: FileOrFolder = { + const file1: File = { path: `${projectLocation}/src/file1.ts`, content: `import { y } from "./file2"; let x = 10;` }; - const file2: FileOrFolder = { + const file2: File = { path: `${projectLocation}/src/file2.ts`, content: "export let y = 10;" }; - const config: FileOrFolder = { + const config: File = { path: `${projectLocation}/tsconfig.json`, content: "{}" }; @@ -3262,18 +3264,18 @@ namespace ts.projectSystem { it("Orphan source files are handled correctly on watch trigger", () => { const projectLocation = "/user/username/projects/project"; - const file1: FileOrFolder = { + const file1: File = { path: `${projectLocation}/src/file1.ts`, content: `export let x = 10;` }; - const file2: FileOrFolder = { + const file2: File = { path: `${projectLocation}/src/file2.ts`, content: "export let y = 10;" }; const configContent1 = JSON.stringify({ files: ["src/file1.ts", "src/file2.ts"] }); - const config: FileOrFolder = { + const config: File = { path: `${projectLocation}/tsconfig.json`, content: configContent1 }; @@ -3424,15 +3426,15 @@ namespace ts.projectSystem { it("folder rename updates project structure and reports no errors", () => { const projectDir = "/a/b/projects/myproject"; - const app: FileOrFolder = { + const app: File = { path: `${projectDir}/bar/app.ts`, content: "class Bar implements foo.Foo { getFoo() { return ''; } get2() { return 1; } }" }; - const foo: FileOrFolder = { + const foo: File = { path: `${projectDir}/foo/foo.ts`, content: "declare namespace foo { interface Foo { get2(): number; getFoo(): string; } }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectDir}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", targer: "es5" }, exclude: ["node_modules"] }) }; @@ -3479,7 +3481,7 @@ namespace ts.projectSystem { }); it("Getting errors before opening file", () => { - const file: FileOrFolder = { + const file: File = { path: "/a/b/project/file.ts", content: "let x: number = false;" }; @@ -3505,15 +3507,15 @@ namespace ts.projectSystem { it("Reports errors correctly when file referenced by inferred project root, is opened right after closing the root file", () => { const projectRoot = "/user/username/projects/myproject"; - const app: FileOrFolder = { + const app: File = { path: `${projectRoot}/src/client/app.js`, content: "" }; - const serverUtilities: FileOrFolder = { + const serverUtilities: File = { path: `${projectRoot}/src/server/utilities.js`, content: `function getHostName() { return "hello"; } export { getHostName };` }; - const backendTest: FileOrFolder = { + const backendTest: File = { path: `${projectRoot}/test/backend/index.js`, content: `import { getHostName } from '../../src/server/utilities';export default getHostName;` }; @@ -3657,11 +3659,11 @@ namespace ts.projectSystem { } it("should not include type symbols", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.js", content: "function foo() {}" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/jsconfig.json", content: "{}" }; @@ -4050,19 +4052,19 @@ namespace ts.projectSystem { } function verifyOpenFileWorks(useCaseSensitiveFileNames: boolean) { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/src/app.ts", content: "let x = 10;" }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/B/lib/module2.ts", content: "let z = 10;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "" }; - const configFile2: FileOrFolder = { + const configFile2: File = { path: "/a/tsconfig.json", content: "" }; @@ -4081,7 +4083,7 @@ namespace ts.projectSystem { verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? configFile2 : configFile); verifyConfigFileName(file2, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); - function verifyConfigFileName(file: FileOrFolder, projectRoot: string, expectedConfigFile: FileOrFolder | undefined) { + function verifyConfigFileName(file: File, projectRoot: string, expectedConfigFile: File | undefined) { const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot); assert.equal(configFileName, expectedConfigFile && expectedConfigFile.path); service.closeClientFile(file.path); @@ -4097,11 +4099,11 @@ namespace ts.projectSystem { it("uses existing project even if project refresh is pending", () => { const projectFolder = "/user/someuser/projects/myproject"; - const aFile: FileOrFolder = { + const aFile: File = { path: `${projectFolder}/src/a.ts`, content: "export const x = 0;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: "{}" }; @@ -4111,7 +4113,7 @@ namespace ts.projectSystem { service.openClientFile(aFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder); verifyProject(); - const bFile: FileOrFolder = { + const bFile: File = { path: `${projectFolder}/src/b.ts`, content: `export {}; declare module "./a" { export const y: number; }` }; @@ -4320,7 +4322,7 @@ namespace ts.projectSystem { it("npm install @types works", () => { const folderPath = "/a/b/projects/temp"; - const file1: FileOrFolder = { + const file1: File = { path: `${folderPath}/a.ts`, content: 'import f = require("pad"); f;' }; @@ -4367,7 +4369,7 @@ namespace ts.projectSystem { checkCompleteEvent(session, 2, expectedSequenceId); session.clearMessages(); - const padIndex: FileOrFolder = { + const padIndex: File = { path: `${folderPath}/node_modules/@types/pad/index.d.ts`, content: "export = pad;declare function pad(length: number, text: string, char ?: string): string;" }; @@ -4386,7 +4388,7 @@ namespace ts.projectSystem { }); it("suggestion diagnostics", () => { - const file: FileOrFolder = { + const file: File = { path: "/a.js", content: "function f(p) {}", }; @@ -4439,7 +4441,7 @@ namespace ts.projectSystem { }); it("disable suggestion diagnostics", () => { - const file: FileOrFolder = { + const file: File = { path: "/a.js", content: 'require("b")', }; @@ -4490,7 +4492,7 @@ namespace ts.projectSystem { }); it("suppressed diagnostic events", () => { - const file: FileOrFolder = { + const file: File = { path: "/a.ts", content: "1 = 2;", }; @@ -5261,13 +5263,13 @@ namespace ts.projectSystem { assert.equal(projectService.inferredProjects[2].getCompilationSettings().target, ScriptTarget.ES2015); }); - function checkInferredProject(inferredProject: server.InferredProject, actualFiles: FileOrFolder[], target: ScriptTarget) { + function checkInferredProject(inferredProject: server.InferredProject, actualFiles: File[], target: ScriptTarget) { checkProjectActualFiles(inferredProject, actualFiles.map(f => f.path)); assert.equal(inferredProject.getCompilationSettings().target, target); } function verifyProjectRootWithCaseSensitivity(useCaseSensitiveFileNames: boolean) { - const files: [FileOrFolder, FileOrFolder, FileOrFolder, FileOrFolder] = [ + const files: [File, File, File, File] = [ { path: "/a/file1.ts", content: "let x = 1;" }, { path: "/A/file2.ts", content: "let y = 2;" }, { path: "/b/file2.ts", content: "let x = 3;" }, @@ -5351,7 +5353,7 @@ namespace ts.projectSystem { files.forEach(file => projectService.closeClientFile(file.path)); } - function verifyInferredProjectsState(expected: [FileOrFolder[], ScriptTarget][]) { + function verifyInferredProjectsState(expected: [File[], ScriptTarget][]) { checkNumberOfProjects(projectService, { inferredProjects: expected.length }); projectService.inferredProjects.forEach((p, index) => { const [actualFiles, target] = expected[index]; @@ -5610,11 +5612,11 @@ namespace ts.projectSystem { describe("when the opened file is not from project root", () => { const projectRoot = "/a/b/projects/project"; - const file: FileOrFolder = { + const file: File = { path: `${projectRoot}/src/index.ts`, content: "let y = 10" }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${projectRoot}/tsconfig.json`, content: "{}" }; @@ -5622,7 +5624,7 @@ namespace ts.projectSystem { const filesWithConfig = files.concat(tsconfig); const dirOfFile = getDirectoryPath(file.path); - function openClientFile(files: FileOrFolder[]) { + function openClientFile(files: File[]) { const host = createServerHost(files); const projectService = createProjectService(host); @@ -5963,7 +5965,7 @@ namespace ts.projectSystem { describe("tsserverProjectSystem occurence highlight on string", () => { it("should be marked if only on string values", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: `let t1 = "div";\nlet t2 = "div";\nlet t3 = { "div": 123 };\nlet t4 = t3["div"];` }; @@ -6009,11 +6011,11 @@ namespace ts.projectSystem { describe("tsserverProjectSystem maxNodeModuleJsDepth for inferred projects", () => { it("should be set to 2 if the project has js root files", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.js", content: `var t = require("test"); t.` }; - const moduleFile: FileOrFolder = { + const moduleFile: File = { path: "/a/b/node_modules/test/index.js", content: `var v = 10; module.exports = v;` }; @@ -6278,12 +6280,12 @@ namespace ts.projectSystem { it("works using legacy resolution logic", () => { let rootContent = `import {x} from "f1"`; - const root: FileOrFolder = { + const root: File = { path: "/c/d/f0.ts", content: rootContent }; - const imported: FileOrFolder = { + const imported: File = { path: "/c/f1.ts", content: `foo()` }; @@ -6394,12 +6396,12 @@ namespace ts.projectSystem { }); it("loads missing files from disk", () => { - const root: FileOrFolder = { + const root: File = { path: "/c/foo.ts", content: `import {y} from "bar"` }; - const imported: FileOrFolder = { + const imported: File = { path: "/c/bar.d.ts", content: `export var y = 1` }; @@ -6431,25 +6433,25 @@ namespace ts.projectSystem { }); it("when calling goto definition of module", () => { - const clientFile: FileOrFolder = { + const clientFile: File = { path: "/a/b/controllers/vessels/client.ts", content: ` import { Vessel } from '~/models/vessel'; const v = new Vessel(); ` }; - const anotherModuleFile: FileOrFolder = { + const anotherModuleFile: File = { path: "/a/b/utils/db.ts", content: "export class Bookshelf { }" }; - const moduleFile: FileOrFolder = { + const moduleFile: File = { path: "/a/b/models/vessel.ts", content: ` import { Bookshelf } from '~/utils/db'; export class Vessel extends Bookshelf {} ` }; - const tsconfigFile: FileOrFolder = { + const tsconfigFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -6510,25 +6512,25 @@ namespace ts.projectSystem { const frontendDir = "/Users/someuser/work/applications/frontend"; const toCanonical: (s: string) => Path = useCaseSensitiveFileNames ? s => s as Path : s => s.toLowerCase() as Path; const canonicalFrontendDir = toCanonical(frontendDir); - const file1: FileOrFolder = { + const file1: File = { path: `${frontendDir}/src/app/utils/Analytic.ts`, content: "export class SomeClass { };" }; - const file2: FileOrFolder = { + const file2: File = { path: `${frontendDir}/src/app/redux/configureStore.ts`, content: "export class configureStore { }" }; - const file3: FileOrFolder = { + const file3: File = { path: `${frontendDir}/src/app/utils/Cookie.ts`, content: "export class Cookie { }" }; - const es2016LibFile: FileOrFolder = { + const es2016LibFile: File = { path: "/a/lib/lib.es2016.full.d.ts", content: libFile.content }; const typeRoots = ["types", "node_modules/@types"]; const types = ["node", "jest"]; - const tsconfigFile: FileOrFolder = { + const tsconfigFile: File = { path: `${frontendDir}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -6602,7 +6604,7 @@ namespace ts.projectSystem { verifyProjectAndWatchedDirectories(); callsTrackingHost.verifyNoHostCalls(); - function getFilePathIfNotOpen(f: FileOrFolder) { + function getFilePathIfNotOpen(f: File) { const path = toCanonical(f.path); const info = projectService.getScriptInfoForPath(toCanonical(f.path)); return info && info.isScriptOpen() ? undefined : path; @@ -6628,15 +6630,15 @@ namespace ts.projectSystem { describe("Subfolder invalidations correctly include parent folder failed lookup locations", () => { function runFailedLookupTest(resolution: "Node" | "Classic") { const projectLocation = "/proj"; - const file1: FileOrFolder = { + const file1: File = { path: `${projectLocation}/foo/boo/app.ts`, content: `import * as debug from "debug"` }; - const file2: FileOrFolder = { + const file2: File = { path: `${projectLocation}/foo/boo/moo/app.ts`, content: `import * as debug from "debug"` }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${projectLocation}/tsconfig.json`, content: JSON.stringify({ files: ["foo/boo/app.ts", "foo/boo/moo/app.ts"], @@ -6654,7 +6656,7 @@ namespace ts.projectSystem { assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file1.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file2.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); - const debugTypesFile: FileOrFolder = { + const debugTypesFile: File = { path: `${projectLocation}/node_modules/debug/index.d.ts`, content: "export {}" }; @@ -6677,19 +6679,19 @@ namespace ts.projectSystem { describe("Verify npm install in directory with tsconfig file works when", () => { function verifyNpmInstall(timeoutDuringPartialInstallation: boolean) { const root = "/user/username/rootfolder/otherfolder"; - const getRootedFileOrFolder = (fileOrFolder: FileOrFolder) => { + const getRootedFileOrFolder = (fileOrFolder: File) => { fileOrFolder.path = root + fileOrFolder.path; return fileOrFolder; }; - const app: FileOrFolder = getRootedFileOrFolder({ + const app: File = getRootedFileOrFolder({ path: "/a/b/app.ts", content: "import _ from 'lodash';" }); - const tsconfigJson: FileOrFolder = getRootedFileOrFolder({ + const tsconfigJson: File = getRootedFileOrFolder({ path: "/a/b/tsconfig.json", content: '{ "compilerOptions": { } }' }); - const packageJson: FileOrFolder = getRootedFileOrFolder({ + const packageJson: File = getRootedFileOrFolder({ path: "/a/b/package.json", content: ` { @@ -6728,7 +6730,7 @@ namespace ts.projectSystem { let timeoutAfterReloadFs = timeoutDuringPartialInstallation; // Simulate npm install - const filesAndFoldersToAdd: FileOrFolder[] = [ + const filesAndFoldersToAdd: File[] = [ { path: "/a/b/node_modules" }, { path: "/a/b/node_modules/.staging/@types" }, { path: "/a/b/node_modules/.staging/lodash-b0733faa" }, @@ -6843,11 +6845,11 @@ namespace ts.projectSystem { it("when node_modules dont receive event for the @types file addition", () => { const projectLocation = "/user/username/folder/myproject"; - const app: FileOrFolder = { + const app: File = { path: `${projectLocation}/app.ts`, content: `import * as debug from "debug"` }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${projectLocation}/tsconfig.json`, content: "" }; @@ -6861,7 +6863,7 @@ namespace ts.projectSystem { checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(app.path).map(diag => diag.messageText), ["Cannot find module 'debug'."]); - const debugTypesFile: FileOrFolder = { + const debugTypesFile: File = { path: `${projectLocation}/node_modules/@types/debug/index.d.ts`, content: "export {}" }; @@ -6892,7 +6894,7 @@ namespace ts.projectSystem { } function createVerifyInitialOpen(session: TestSession, verifyProjectsUpdatedInBackgroundEventHandler: (events: server.ProjectsUpdatedInBackgroundEvent[]) => void) { - return (file: FileOrFolder) => { + return (file: File) => { session.executeCommandSeq({ command: server.CommandNames.Open, arguments: { @@ -6906,24 +6908,24 @@ namespace ts.projectSystem { interface ProjectsUpdatedInBackgroundEventVerifier { session: TestSession; verifyProjectsUpdatedInBackgroundEventHandler(events: server.ProjectsUpdatedInBackgroundEvent[]): void; - verifyInitialOpen(file: FileOrFolder): void; + verifyInitialOpen(file: File): void; } function verifyProjectsUpdatedInBackgroundEvent(createSession: (host: TestServerHost) => ProjectsUpdatedInBackgroundEventVerifier) { it("when adding new file", () => { - const commonFile1: FileOrFolder = { + const commonFile1: File = { path: "/a/b/file1.ts", content: "export var x = 10;" }; - const commonFile2: FileOrFolder = { + const commonFile2: File = { path: "/a/b/file2.ts", content: "export var y = 10;" }; - const commonFile3: FileOrFolder = { + const commonFile3: File = { path: "/a/b/file3.ts", content: "export var z = 10;" }; - const configFile: FileOrFolder = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; @@ -6953,18 +6955,18 @@ namespace ts.projectSystem { describe("with --out or --outFile setting", () => { function verifyEventWithOutSettings(compilerOptions: CompilerOptions = {}) { - const config: FileOrFolder = { + const config: File = { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions }) }; - const f1: FileOrFolder = { + const f1: File = { path: "/a/a.ts", content: "export let x = 1" }; - const f2: FileOrFolder = { + const f2: File = { path: "/a/b.ts", content: "export let y = 1" }; @@ -7020,32 +7022,32 @@ namespace ts.projectSystem { /** custom config file options */ configObj?: any; /** Additional files and folders to add */ - getAdditionalFileOrFolder?(): FileOrFolder[]; + getAdditionalFileOrFolder?(): File[]; /** initial list of files to reload in fs and first file in this list being the file to open */ firstReloadFileList?: string[]; } function getInitialState({ configObj = {}, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}) { - const moduleFile1: FileOrFolder = { + const moduleFile1: File = { path: moduleFile1Path, content: "export function Foo() { };", }; - const file1Consumer1: FileOrFolder = { + const file1Consumer1: File = { path: file1Consumer1Path, content: `import {Foo} from "./moduleFile1"; export var y = 10;`, }; - const file1Consumer2: FileOrFolder = { + const file1Consumer2: File = { path: "/a/b/file1Consumer2.ts", content: `import {Foo} from "./moduleFile1"; let z = 10;`, }; - const moduleFile2: FileOrFolder = { + const moduleFile2: File = { path: "/a/b/moduleFile2.ts", content: `export var Foo4 = 10;`, }; - const globalFile3: FileOrFolder = { + const globalFile3: File = { path: "/a/b/globalFile3.ts", content: `interface GlobalFoo { age: number }` }; @@ -7085,13 +7087,13 @@ namespace ts.projectSystem { return find(files, file => file.path === fileName); } - function verifyNoProjectsUpdatedInBackgroundEvent(filesToReload?: FileOrFolder[]) { + function verifyNoProjectsUpdatedInBackgroundEvent(filesToReload?: File[]) { host.reloadFS(filesToReload || files); host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([]); } - function verifyProjectsUpdatedInBackgroundEvent(filesToReload?: FileOrFolder[]) { + function verifyProjectsUpdatedInBackgroundEvent(filesToReload?: File[]) { host.reloadFS(filesToReload || files); host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ @@ -7102,7 +7104,7 @@ namespace ts.projectSystem { }]); } - function updateContentOfOpenFile(file: FileOrFolder, newContent: string) { + function updateContentOfOpenFile(file: File, newContent: string) { session.executeCommandSeq({ command: server.CommandNames.Change, arguments: { @@ -7172,7 +7174,7 @@ namespace ts.projectSystem { it("should be up-to-date with newly created files", () => { const { moduleFile1, files, verifyProjectsUpdatedInBackgroundEvent, } = getInitialState(); - const file1Consumer3: FileOrFolder = { + const file1Consumer3: File = { path: "/a/b/file1Consumer3.ts", content: `import {Foo} from "./moduleFile1"; let y = Foo();` }; @@ -7220,7 +7222,7 @@ namespace ts.projectSystem { }); it("should return cascaded affected file list", () => { - const file1Consumer1Consumer1: FileOrFolder = { + const file1Consumer1Consumer1: File = { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";` }; @@ -7242,13 +7244,13 @@ namespace ts.projectSystem { }); it("should work fine for files with circular references", () => { - const file1: FileOrFolder = { + const file1: File = { path: "/a/b/file1.ts", content: ` /// export var t1 = 10;` }; - const file2: FileOrFolder = { + const file2: File = { path: "/a/b/file2.ts", content: ` /// @@ -7264,7 +7266,7 @@ namespace ts.projectSystem { }); it("should detect removed code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -7279,7 +7281,7 @@ namespace ts.projectSystem { }); it("should detect non-existing code file", () => { - const referenceFile1: FileOrFolder = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -7301,19 +7303,19 @@ namespace ts.projectSystem { describe("resolution when resolution cache size", () => { function verifyWithMaxCacheLimit(limitHit: boolean, useSlashRootAsSomeNotRootFolderInUserDirectory: boolean) { const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory ? "/user/username/rootfolder/otherfolder/" : "/"; - const file1: FileOrFolder = { + const file1: File = { path: rootFolder + "a/b/project/file1.ts", content: 'import a from "file2"' }; - const file2: FileOrFolder = { + const file2: File = { path: rootFolder + "a/b/node_modules/file2.d.ts", content: "export class a { }" }; - const file3: FileOrFolder = { + const file3: File = { path: rootFolder + "a/b/project/file3.ts", content: "export class c { }" }; - const configFile: FileOrFolder = { + const configFile: File = { path: rootFolder + "a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { typeRoots: [] } }) }; @@ -7479,15 +7481,15 @@ namespace ts.projectSystem { describe("tsserverProjectSystem Watched recursive directories with windows style file system", () => { function verifyWatchedDirectories(useProjectAtRoot: boolean) { const root = useProjectAtRoot ? "c:/" : "c:/myfolder/allproject/"; - const configFile: FileOrFolder = { + const configFile: File = { path: root + "project/tsconfig.json", content: "{}" }; - const file1: FileOrFolder = { + const file1: File = { path: root + "project/file1.ts", content: "let x = 10;" }; - const file2: FileOrFolder = { + const file2: File = { path: root + "project/file2.ts", content: "let y = 10;" }; @@ -7520,13 +7522,13 @@ namespace ts.projectSystem { it("when projectRootPath is provided", () => { const projects = "/users/username/projects"; const projectRootPath = `${projects}/san2`; - const file: FileOrFolder = { + const file: File = { path: `${projectRootPath}/x.js`, content: "const aaaaaaav = 1;" }; const currentDirectory = `${projects}/anotherProject`; - const packageJsonInCurrentDirectory: FileOrFolder = { + const packageJsonInCurrentDirectory: File = { path: `${currentDirectory}/package.json`, content: JSON.stringify({ devDependencies: { @@ -7534,7 +7536,7 @@ namespace ts.projectSystem { }, }) }; - const packageJsonOfPkgcurrentdirectory: FileOrFolder = { + const packageJsonOfPkgcurrentdirectory: File = { path: `${currentDirectory}/node_modules/pkgcurrentdirectory/package.json`, content: JSON.stringify({ name: "pkgcurrentdirectory", @@ -7542,20 +7544,20 @@ namespace ts.projectSystem { typings: "index.d.ts" }) }; - const indexOfPkgcurrentdirectory: FileOrFolder = { + const indexOfPkgcurrentdirectory: File = { path: `${currentDirectory}/node_modules/pkgcurrentdirectory/index.d.ts`, content: "export function foo() { }" }; const typingsCache = `/users/username/Library/Caches/typescript/2.7`; - const typingsCachePackageJson: FileOrFolder = { + const typingsCachePackageJson: File = { path: `${typingsCache}/package.json`, content: JSON.stringify({ devDependencies: { }, }) }; - const typingsCachePackageLockJson: FileOrFolder = { + const typingsCachePackageLockJson: File = { path: `${typingsCache}/package-lock.json`, content: JSON.stringify({ dependencies: { @@ -7598,37 +7600,37 @@ namespace ts.projectSystem { it("rename in common file renames all project", () => { const projects = "/users/username/projects"; const folderA = `${projects}/a`; - const aFile: FileOrFolder = { + const aFile: File = { path: `${folderA}/a.ts`, content: `import {C} from "./c/fc"; console.log(C)` }; - const aTsconfig: FileOrFolder = { + const aTsconfig: File = { path: `${folderA}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "commonjs" } }) }; - const aC: FileOrFolder = { + const aC: SymLink = { path: `${folderA}/c`, symLink: "../c" }; const aFc = `${folderA}/c/fc.ts`; const folderB = `${projects}/b`; - const bFile: FileOrFolder = { + const bFile: File = { path: `${folderB}/b.ts`, content: `import {C} from "./c/fc"; console.log(C)` }; - const bTsconfig: FileOrFolder = { + const bTsconfig: File = { path: `${folderB}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "commonjs" } }) }; - const bC: FileOrFolder = { + const bC: SymLink = { path: `${folderB}/c`, symLink: "../c" }; const bFc = `${folderB}/c/fc.ts`; const folderC = `${projects}/c`; - const cFile: FileOrFolder = { + const cFile: File = { path: `${folderC}/fc.ts`, content: `export const C = 8` }; @@ -7709,19 +7711,19 @@ namespace ts.projectSystem { describe("tsserverProjectSystem forceConsistentCasingInFileNames", () => { it("works when extends is specified with a case insensitive file system", () => { const rootPath = "/Users/username/dev/project"; - const file1: FileOrFolder = { + const file1: File = { path: `${rootPath}/index.ts`, content: 'import {x} from "file2";', }; - const file2: FileOrFolder = { + const file2: File = { path: `${rootPath}/file2.js`, content: "", }; - const file2Dts: FileOrFolder = { + const file2Dts: File = { path: `${rootPath}/types/file2/index.d.ts`, content: "export declare const x: string;", }; - const tsconfigAll: FileOrFolder = { + const tsconfigAll: File = { path: `${rootPath}/tsconfig.all.json`, content: JSON.stringify({ compilerOptions: { @@ -7732,7 +7734,7 @@ namespace ts.projectSystem { }, }), }; - const tsconfig: FileOrFolder = { + const tsconfig: File = { path: `${rootPath}/tsconfig.json`, content: JSON.stringify({ extends: "./tsconfig.all.json" }), }; @@ -7752,17 +7754,17 @@ namespace ts.projectSystem { describe("tsserverProjectSystem module resolution caching", () => { const projectLocation = "/user/username/projects/myproject"; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { traceResolution: true } }) }; function getModules(module1Path: string, module2Path: string) { - const module1: FileOrFolder = { + const module1: File = { path: module1Path, content: `export function module1() {}` }; - const module2: FileOrFolder = { + const module2: File = { path: module2Path, content: `export function module2() {}` }; @@ -7774,7 +7776,7 @@ namespace ts.projectSystem { resolutionTrace.length = 0; } - function getExpectedFileDoesNotExistResolutionTrace(host: TestServerHost, expectedTrace: string[], foundModule: boolean, module: FileOrFolder, directory: string, file: string, ignoreIfParentMissing?: boolean) { + function getExpectedFileDoesNotExistResolutionTrace(host: TestServerHost, expectedTrace: string[], foundModule: boolean, module: File, directory: string, file: string, ignoreIfParentMissing?: boolean) { if (!foundModule) { const path = combinePaths(directory, file); if (!ignoreIfParentMissing || host.directoryExists(getDirectoryPath(path))) { @@ -7789,7 +7791,7 @@ namespace ts.projectSystem { return foundModule; } - function getExpectedMissedLocationResolutionTrace(host: TestServerHost, expectedTrace: string[], dirPath: string, module: FileOrFolder, moduleName: string, useNodeModules: boolean, cacheLocation?: string) { + function getExpectedMissedLocationResolutionTrace(host: TestServerHost, expectedTrace: string[], dirPath: string, module: File, moduleName: string, useNodeModules: boolean, cacheLocation?: string) { let foundModule = false; forEachAncestorDirectory(dirPath, dirPath => { if (dirPath === cacheLocation) { @@ -7813,14 +7815,14 @@ namespace ts.projectSystem { }); } - function getExpectedResolutionTraceHeader(expectedTrace: string[], file: FileOrFolder, moduleName: string) { + function getExpectedResolutionTraceHeader(expectedTrace: string[], file: File, moduleName: string) { expectedTrace.push( `======== Resolving module '${moduleName}' from '${file.path}'. ========`, `Module resolution kind is not specified, using 'NodeJs'.` ); } - function getExpectedResolutionTraceFooter(expectedTrace: string[], module: FileOrFolder, moduleName: string, addRealPathTrace: boolean, ignoreModuleFileFound?: boolean) { + function getExpectedResolutionTraceFooter(expectedTrace: string[], module: File, moduleName: string, addRealPathTrace: boolean, ignoreModuleFileFound?: boolean) { if (!ignoreModuleFileFound) { expectedTrace.push(`File '${module.path}' exist - use it as a name resolution result.`); } @@ -7830,7 +7832,7 @@ namespace ts.projectSystem { expectedTrace.push(`======== Module name '${moduleName}' was successfully resolved to '${module.path}'. ========`); } - function getExpectedRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) { + function getExpectedRelativeModuleResolutionTrace(host: TestServerHost, file: File, module: File, moduleName: string, expectedTrace: string[] = []) { getExpectedResolutionTraceHeader(expectedTrace, file, moduleName); expectedTrace.push(`Loading module as file / folder, candidate module location '${removeFileExtension(module.path)}', target file type 'TypeScript'.`); getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(normalizePath(combinePaths(getDirectoryPath(file.path), moduleName))), module, moduleName.substring(moduleName.lastIndexOf("/") + 1), /*useNodeModules*/ false); @@ -7838,7 +7840,7 @@ namespace ts.projectSystem { return expectedTrace; } - function getExpectedNonRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) { + function getExpectedNonRelativeModuleResolutionTrace(host: TestServerHost, file: File, module: File, moduleName: string, expectedTrace: string[] = []) { getExpectedResolutionTraceHeader(expectedTrace, file, moduleName); expectedTrace.push(`Loading module '${moduleName}' from 'node_modules' folder, target file type 'TypeScript'.`); getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(file.path), module, moduleName, /*useNodeModules*/ true); @@ -7846,7 +7848,7 @@ namespace ts.projectSystem { return expectedTrace; } - function getExpectedNonRelativeModuleResolutionFromCacheTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, cacheLocation: string, expectedTrace: string[] = []) { + function getExpectedNonRelativeModuleResolutionFromCacheTrace(host: TestServerHost, file: File, module: File, moduleName: string, cacheLocation: string, expectedTrace: string[] = []) { getExpectedResolutionTraceHeader(expectedTrace, file, moduleName); expectedTrace.push(`Loading module '${moduleName}' from 'node_modules' folder, target file type 'TypeScript'.`); getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(file.path), module, moduleName, /*useNodeModules*/ true, cacheLocation); @@ -7855,11 +7857,11 @@ namespace ts.projectSystem { return expectedTrace; } - function getExpectedReusingResolutionFromOldProgram(file: FileOrFolder, moduleName: string) { + function getExpectedReusingResolutionFromOldProgram(file: File, moduleName: string) { return `Reusing resolution of module '${moduleName}' to file '${file.path}' from old program.`; } - function verifyWatchesWithConfigFile(host: TestServerHost, files: FileOrFolder[], openFile: FileOrFolder) { + function verifyWatchesWithConfigFile(host: TestServerHost, files: File[], openFile: File) { checkWatchedFiles(host, mapDefined(files, f => f === openFile ? undefined : f.path)); checkWatchedDirectories(host, [], /*recursive*/ false); const configDirectory = getDirectoryPath(configFile.path); @@ -7868,11 +7870,11 @@ namespace ts.projectSystem { describe("from files in same folder", () => { function getFiles(fileContent: string) { - const file1: FileOrFolder = { + const file1: File = { path: `${projectLocation}/src/file1.ts`, content: fileContent }; - const file2: FileOrFolder = { + const file2: File = { path: `${projectLocation}/src/file2.ts`, content: fileContent }; @@ -7936,19 +7938,19 @@ namespace ts.projectSystem { describe("from files in different folders", () => { function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) { - const file1: FileOrFolder = { + const file1: File = { path: `${projectLocation}/product/src/file1.ts`, content: fileContent1 }; - const file2: FileOrFolder = { + const file2: File = { path: `${projectLocation}/product/src/feature/file2.ts`, content: fileContent2 }; - const file3: FileOrFolder = { + const file3: File = { path: `${projectLocation}/product/test/src/file3.ts`, content: fileContent3 }; - const file4: FileOrFolder = { + const file4: File = { path: `${projectLocation}/product/test/file4.ts`, content: fileContent4 }; @@ -8103,15 +8105,15 @@ namespace ts.projectSystem { function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) { const projectFolder = "/a/username/project"; const projectSrcFolder = `${projectFolder}/src`; - const configFile: FileOrFolder = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: "{}" }; - const index: FileOrFolder = { + const index: File = { path: `${projectSrcFolder}/index.ts`, content: `import {} from "./"` }; - const file1: FileOrFolder = { + const file1: File = { path: `${projectSrcFolder}/file1.ts`, content: "" }; @@ -8145,7 +8147,7 @@ namespace ts.projectSystem { verifyProjectAndCompletions(); // Add file2 - const file2: FileOrFolder = { + const file2: File = { path: `${projectSrcFolder}/file2.ts`, content: "" }; diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index a8c7d4895d1..2f83fe90c8a 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -30,7 +30,7 @@ namespace ts.projectSystem { } } - function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[] | string, typingFiles: FileOrFolder[], cb: TI.RequestCompletedAction): void { + function executeCommand(self: Installer, host: TestServerHost, installedTypings: string[] | string, typingFiles: File[], cb: TI.RequestCompletedAction): void { self.addPostExecAction(installedTypings, success => { for (const file of typingFiles) { host.ensureFileOrFolder(file); @@ -417,7 +417,7 @@ namespace ts.projectSystem { } installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings: string[] = []; - const typingFiles: FileOrFolder[] = []; + const typingFiles: File[] = []; executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -460,7 +460,7 @@ namespace ts.projectSystem { } installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { const installedTypings: string[] = []; - const typingFiles: FileOrFolder[] = []; + const typingFiles: File[] = []; executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -697,7 +697,7 @@ namespace ts.projectSystem { super(host, { throttleLimit: 1, typesRegistry: createTypesRegistry("commander", "jquery", "lodash", "cordova", "gulp", "grunt") }); } installWorker(_requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { - let typingFiles: (FileOrFolder & { typings: string })[] = []; + let typingFiles: (File & { typings: string })[] = []; if (args.indexOf(typingsName("commander")) >= 0) { typingFiles = [commander, jquery, lodash, cordova]; } @@ -1193,7 +1193,7 @@ namespace ts.projectSystem { } installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) { const installedTypings: string[] = []; - const typingFiles: FileOrFolder[] = []; + const typingFiles: File[] = []; executeCommand(this, host, installedTypings, typingFiles, cb); } })(); @@ -1656,12 +1656,12 @@ namespace ts.projectSystem { return foooResolution; } - function verifyUnresolvedImportResolutions(appContents: string, typingNames: string[], typingFiles: FileOrFolder[]) { - const app: FileOrFolder = { + function verifyUnresolvedImportResolutions(appContents: string, typingNames: string[], typingFiles: File[]) { + const app: File = { path: appPath, content: `${appContents}import * as x from "fooo";` }; - const fooo: FileOrFolder = { + const fooo: File = { path: foooPath, content: `export var x: string;` }; @@ -1697,15 +1697,15 @@ namespace ts.projectSystem { }); it("correctly invalidate the resolutions with typing names that are trimmed", () => { - const fooAA: FileOrFolder = { + const fooAA: File = { path: `${globalTypingsCacheLocation}/node_modules/foo/a/a.d.ts`, content: "export function a (): void;" }; - const fooAB: FileOrFolder = { + const fooAB: File = { path: `${globalTypingsCacheLocation}/node_modules/foo/a/b.d.ts`, content: "export function b (): void;" }; - const fooAC: FileOrFolder = { + const fooAC: File = { path: `${globalTypingsCacheLocation}/node_modules/foo/a/c.d.ts`, content: "export function c (): void;" }; diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 323a51c25ae..1ff6e4dbdf6 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -1,7 +1,7 @@ /// namespace ts.TestFSWithWatch { - export const libFile: FileOrFolder = { + export const libFile: File = { path: "/a/lib/lib.d.ts", content: `/// interface Boolean {} @@ -39,7 +39,7 @@ interface Array {}` environmentVariables?: Map; } - export function createWatchedSystem(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { + export function createWatchedSystem(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { if (!params) { params = {}; } @@ -54,7 +54,7 @@ interface Array {}` return host; } - export function createServerHost(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { + export function createServerHost(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { if (!params) { params = {}; } @@ -69,11 +69,28 @@ interface Array {}` return host; } - export interface FileOrFolder { + export interface File { path: string; - content?: string; + content: string; fileSize?: number; - symLink?: string; + } + + export interface Folder { + path: string; + } + + export interface SymLink { + path: string; + symLink: string; + } + + export type FileOrFolderOrSymLink = File | Folder | SymLink; + function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is File { + return isString((fileOrFolderOrSymLink).content); + } + + function isSymLink(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is SymLink { + return isString((fileOrFolderOrSymLink).symLink); } interface FSEntry { @@ -82,29 +99,29 @@ interface Array {}` modifiedTime: Date; } - interface File extends FSEntry { + interface FsFile extends FSEntry { content: string; fileSize?: number; } - interface Folder extends FSEntry { + interface FsFolder extends FSEntry { entries: SortedArray; } - interface SymLink extends FSEntry { + interface FsSymLink extends FSEntry { symLink: string; } - function isFolder(s: FSEntry): s is Folder { - return s && isArray((s).entries); + function isFsFolder(s: FSEntry): s is FsFolder { + return s && isArray((s).entries); } - function isFile(s: FSEntry): s is File { - return s && isString((s).content); + function isFsFile(s: FSEntry): s is FsFile { + return s && isString((s).content); } - function isSymLink(s: FSEntry): s is SymLink { - return s && isString((s).symLink); + function isFsSymLink(s: FSEntry): s is FsSymLink { + return s && isString((s).symLink); } function invokeWatcherCallbacks(callbacks: T[], invokeCallback: (cb: T) => void): void { @@ -306,12 +323,12 @@ interface Array {}` private readonly dynamicPriorityWatchFile: HostWatchFile; private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined; - constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map) { + constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map) { this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName); this.executingFilePath = this.getHostSpecificPath(executingFilePath); this.currentDirectory = this.getHostSpecificPath(currentDirectory); - this.reloadFS(fileOrFolderList); + this.reloadFS(fileOrFolderorSymLinkList); this.dynamicPriorityWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE") === "DynamicPriorityPolling" ? createDynamicPriorityPollingWatchFile(this) : undefined; @@ -373,12 +390,12 @@ interface Array {}` return new Date(this.time); } - reloadFS(fileOrFolderList: ReadonlyArray, options?: Partial) { + reloadFS(fileOrFolderOrSymLinkList: ReadonlyArray, options?: Partial) { const mapNewLeaves = createMap(); const isNewFs = this.fs.size === 0; - fileOrFolderList = fileOrFolderList.concat(this.withSafeList ? safeList : []); - const filesOrFoldersToLoad: ReadonlyArray = !this.useWindowsStylePath ? fileOrFolderList : - fileOrFolderList.map(f => { + fileOrFolderOrSymLinkList = fileOrFolderOrSymLinkList.concat(this.withSafeList ? safeList : []); + const filesOrFoldersToLoad: ReadonlyArray = !this.useWindowsStylePath ? fileOrFolderOrSymLinkList : + fileOrFolderOrSymLinkList.map(f => { const result = clone(f); result.path = this.getHostSpecificPath(f.path); return result; @@ -389,8 +406,8 @@ interface Array {}` // If its a change const currentEntry = this.fs.get(path); if (currentEntry) { - if (isFile(currentEntry)) { - if (isString(fileOrDirectory.content)) { + if (isFsFile(currentEntry)) { + if (isFile(fileOrDirectory)) { // Update file if (currentEntry.content !== fileOrDirectory.content) { this.modifyFile(fileOrDirectory.path, fileOrDirectory.content, options); @@ -400,12 +417,12 @@ interface Array {}` // TODO: Changing from file => folder/Symlink } } - else if (isSymLink(currentEntry)) { + else if (isFsSymLink(currentEntry)) { // TODO: update symlinks } else { // Folder - if (isString(fileOrDirectory.content)) { + if (isFile(fileOrDirectory)) { // TODO: Changing from folder => file } else { @@ -424,7 +441,7 @@ interface Array {}` // If this entry is not from the new file or folder if (!mapNewLeaves.get(path)) { // Leaf entries that arent in new list => remove these - if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory) || isFolder(fileOrDirectory) && fileOrDirectory.entries.length === 0) { + if (isFsFile(fileOrDirectory) || isFsSymLink(fileOrDirectory) || isFsFolder(fileOrDirectory) && fileOrDirectory.entries.length === 0) { this.removeFileOrFolder(fileOrDirectory, folder => !mapNewLeaves.get(folder.path)); } } @@ -435,7 +452,7 @@ interface Array {}` modifyFile(filePath: string, content: string, options?: Partial) { const path = this.toFullPath(filePath); const currentEntry = this.fs.get(path); - if (!currentEntry || !isFile(currentEntry)) { + if (!currentEntry || !isFsFile(currentEntry)) { throw new Error(`file not present: ${filePath}`); } @@ -459,7 +476,7 @@ interface Array {}` renameFolder(folderName: string, newFolderName: string) { const fullPath = getNormalizedAbsolutePath(folderName, this.currentDirectory); const path = this.toPath(fullPath); - const folder = this.fs.get(path) as Folder; + const folder = this.fs.get(path) as FsFolder; Debug.assert(!!folder); // Only remove the folder @@ -467,19 +484,19 @@ interface Array {}` // Add updated folder with new folder name const newFullPath = getNormalizedAbsolutePath(newFolderName, this.currentDirectory); - const newFolder = this.toFolder(newFullPath); + const newFolder = this.toFsFolder(newFullPath); const newPath = newFolder.path; const basePath = getDirectoryPath(path); Debug.assert(basePath !== path); Debug.assert(basePath === getDirectoryPath(newPath)); - const baseFolder = this.fs.get(basePath) as Folder; + const baseFolder = this.fs.get(basePath) as FsFolder; this.addFileOrFolderInFolder(baseFolder, newFolder); // Invoke watches for files in the folder as deleted (from old path) this.renameFolderEntries(folder, newFolder); } - private renameFolderEntries(oldFolder: Folder, newFolder: Folder) { + private renameFolderEntries(oldFolder: FsFolder, newFolder: FsFolder) { for (const entry of oldFolder.entries) { this.fs.delete(entry.path); this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Deleted); @@ -491,38 +508,38 @@ interface Array {}` } this.fs.set(entry.path, entry); this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Created); - if (isFolder(entry)) { + if (isFsFolder(entry)) { this.renameFolderEntries(entry, entry); } } } - ensureFileOrFolder(fileOrDirectory: FileOrFolder, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean) { - if (isString(fileOrDirectory.content)) { - const file = this.toFile(fileOrDirectory); + ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLink, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean) { + if (isFile(fileOrDirectoryOrSymLink)) { + const file = this.toFsFile(fileOrDirectoryOrSymLink); // file may already exist when updating existing type declaration file if (!this.fs.get(file.path)) { const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath)); this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate); } } - else if (isString(fileOrDirectory.symLink)) { - const symLink = this.toSymLink(fileOrDirectory); + else if (isSymLink(fileOrDirectoryOrSymLink)) { + const symLink = this.toFsSymLink(fileOrDirectoryOrSymLink); Debug.assert(!this.fs.get(symLink.path)); const baseFolder = this.ensureFolder(getDirectoryPath(symLink.fullPath)); this.addFileOrFolderInFolder(baseFolder, symLink, ignoreWatchInvokedWithTriggerAsFileCreate); } else { - const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory); + const fullPath = getNormalizedAbsolutePath(fileOrDirectoryOrSymLink.path, this.currentDirectory); this.ensureFolder(fullPath); } } - private ensureFolder(fullPath: string): Folder { + private ensureFolder(fullPath: string): FsFolder { const path = this.toPath(fullPath); - let folder = this.fs.get(path) as Folder; + let folder = this.fs.get(path) as FsFolder; if (!folder) { - folder = this.toFolder(fullPath); + folder = this.toFsFolder(fullPath); const baseFullPath = getDirectoryPath(fullPath); if (fullPath !== baseFullPath) { // Add folder in the base folder @@ -535,11 +552,11 @@ interface Array {}` this.fs.set(path, folder); } } - Debug.assert(isFolder(folder)); + Debug.assert(isFsFolder(folder)); return folder; } - private addFileOrFolderInFolder(folder: Folder, fileOrDirectory: File | Folder | SymLink, ignoreWatch?: boolean) { + private addFileOrFolderInFolder(folder: FsFolder, fileOrDirectory: FsFile | FsFolder | FsSymLink, ignoreWatch?: boolean) { insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path))); folder.modifiedTime = this.now(); this.fs.set(fileOrDirectory.path, fileOrDirectory); @@ -551,9 +568,9 @@ interface Array {}` this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath); } - private removeFileOrFolder(fileOrDirectory: File | Folder | SymLink, isRemovableLeafFolder: (folder: Folder) => boolean, isRenaming?: boolean) { + private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRemovableLeafFolder: (folder: FsFolder) => boolean, isRenaming?: boolean) { const basePath = getDirectoryPath(fileOrDirectory.path); - const baseFolder = this.fs.get(basePath) as Folder; + const baseFolder = this.fs.get(basePath) as FsFolder; if (basePath !== fileOrDirectory.path) { Debug.assert(!!baseFolder); baseFolder.modifiedTime = this.now(); @@ -562,7 +579,7 @@ interface Array {}` this.fs.delete(fileOrDirectory.path); this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted); - if (isFolder(fileOrDirectory)) { + if (isFsFolder(fileOrDirectory)) { Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming); const relativePath = this.getRelativePathToDirectory(fileOrDirectory.fullPath, fileOrDirectory.fullPath); // Invoke directory and recursive directory watcher for the folder @@ -635,23 +652,23 @@ interface Array {}` }; } - private toFile(fileOrDirectory: FileOrFolder): File { - const file = this.toFsEntry(fileOrDirectory.path) as File; - file.content = fileOrDirectory.content; - file.fileSize = fileOrDirectory.fileSize; - return file; + private toFsFile(file: File): FsFile { + const fsFile = this.toFsEntry(file.path) as FsFile; + fsFile.content = file.content; + fsFile.fileSize = file.fileSize; + return fsFile; } - private toSymLink(fileOrDirectory: FileOrFolder): SymLink { - const symLink = this.toFsEntry(fileOrDirectory.path) as SymLink; - symLink.symLink = getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(symLink.fullPath)); - return symLink; + private toFsSymLink(symLink: SymLink): FsSymLink { + const fsSymLink = this.toFsEntry(symLink.path) as FsSymLink; + fsSymLink.symLink = getNormalizedAbsolutePath(symLink.symLink, getDirectoryPath(fsSymLink.fullPath)); + return fsSymLink; } - private toFolder(path: string): Folder { - const folder = this.toFsEntry(path) as Folder; - folder.entries = [] as SortedArray; - return folder; + private toFsFolder(path: string): FsFolder { + const fsFolder = this.toFsEntry(path) as FsFolder; + fsFolder.entries = [] as SortedArray; + return fsFolder; } private getRealFsEntry(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)): T | undefined { @@ -659,7 +676,7 @@ interface Array {}` return fsEntry; } - if (isSymLink(fsEntry)) { + if (isFsSymLink(fsEntry)) { return this.getRealFsEntry(isFsEntry, this.toPath(fsEntry.symLink)); } @@ -676,20 +693,20 @@ interface Array {}` return undefined; } - private isFile(fsEntry: FSEntry) { + private isFsFile(fsEntry: FSEntry) { return !!this.getRealFile(fsEntry.path, fsEntry); } - private getRealFile(path: Path, fsEntry?: FSEntry): File | undefined { - return this.getRealFsEntry(isFile, path, fsEntry); + private getRealFile(path: Path, fsEntry?: FSEntry): FsFile | undefined { + return this.getRealFsEntry(isFsFile, path, fsEntry); } - private isFolder(fsEntry: FSEntry) { + private isFsFolder(fsEntry: FSEntry) { return !!this.getRealFolder(fsEntry.path, fsEntry); } - private getRealFolder(path: Path, fsEntry = this.fs.get(path)): Folder | undefined { - return this.getRealFsEntry(isFolder, path, fsEntry); + private getRealFolder(path: Path, fsEntry = this.fs.get(path)): FsFolder | undefined { + return this.getRealFsEntry(isFsFolder, path, fsEntry); } fileExists(s: string) { @@ -711,7 +728,7 @@ interface Array {}` getFileSize(s: string) { const path = this.toFullPath(s); const entry = this.fs.get(path); - if (isFile(entry)) { + if (isFsFile(entry)) { return entry.fileSize ? entry.fileSize : entry.content.length; } return undefined; @@ -726,7 +743,7 @@ interface Array {}` const path = this.toFullPath(s); const folder = this.getRealFolder(path); if (folder) { - return mapDefined(folder.entries, entry => this.isFolder(entry) ? getBaseFileName(entry.fullPath) : undefined); + return mapDefined(folder.entries, entry => this.isFsFolder(entry) ? getBaseFileName(entry.fullPath) : undefined); } Debug.fail(folder ? "getDirectories called on file" : "getDirectories called on missing folder"); return []; @@ -739,10 +756,10 @@ interface Array {}` const folder = this.getRealFolder(this.toPath(dir)); if (folder) { folder.entries.forEach((entry) => { - if (this.isFolder(entry)) { + if (this.isFsFolder(entry)) { directories.push(getBaseFileName(entry.fullPath)); } - else if (this.isFile(entry)) { + else if (this.isFsFile(entry)) { files.push(getBaseFileName(entry.fullPath)); } else { @@ -840,24 +857,24 @@ interface Array {}` } createDirectory(directoryName: string): void { - const folder = this.toFolder(directoryName); + const folder = this.toFsFolder(directoryName); // base folder has to be present const base = getDirectoryPath(folder.path); - const baseFolder = this.fs.get(base) as Folder; - Debug.assert(isFolder(baseFolder)); + const baseFolder = this.fs.get(base) as FsFolder; + Debug.assert(isFsFolder(baseFolder)); Debug.assert(!this.fs.get(folder.path)); this.addFileOrFolderInFolder(baseFolder, folder); } writeFile(path: string, content: string): void { - const file = this.toFile({ path, content }); + const file = this.toFsFile({ path, content }); // base folder has to be present const base = getDirectoryPath(file.path); - const folder = this.fs.get(base) as Folder; - Debug.assert(isFolder(folder)); + const folder = this.fs.get(base) as FsFolder; + Debug.assert(isFsFolder(folder)); this.addFileOrFolderInFolder(folder, file); } @@ -885,7 +902,7 @@ interface Array {}` const dirFullPath = this.realpath(getDirectoryPath(fullPath)); const realFullPath = combinePaths(dirFullPath, getBaseFileName(fullPath)); const fsEntry = this.fs.get(this.toPath(realFullPath)); - if (isSymLink(fsEntry)) { + if (isFsSymLink(fsEntry)) { return this.realpath(fsEntry.symLink); } From 528bf84a7a864e4d52e202588b74e9d59abd34e8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 3 May 2018 12:20:29 -0700 Subject: [PATCH 07/64] Create a test case for module resolution when symlinked folder contents change and resolve modules Test case for #22349 --- .../unittests/tsserverProjectSystem.ts | 180 ++++++++++++++++++ src/harness/virtualFileSystemWithWatch.ts | 30 ++- 2 files changed, 205 insertions(+), 5 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index bed1940ee88..3404eb5a767 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -7706,6 +7706,186 @@ namespace ts.projectSystem { } } }); + + describe("module resolution when symlinked folder contents change and resolve modules", () => { + const projectRootPath = "/users/username/projects/myproject"; + const packages = `${projectRootPath}/javascript/packages`; + const recognizersDateTime = `${packages}/recognizers-date-time`; + const recognizersText = `${packages}/recognizers-text`; + const recognizersTextDist = `${recognizersText}/dist`; + const moduleName = "@microsoft/recognizers-text"; + const moduleNameInFile = `"${moduleName}"`; + const recognizersDateTimeSrcFile: File = { + path: `${recognizersDateTime}/src/datetime/baseDate.ts`, + content: `import {C} from ${moduleNameInFile}; +new C();` + }; + const recognizerDateTimeTsconfigPath = `${recognizersDateTime}/tsconfig.json`; + const recognizerDateTimeTsconfigWithoutPathMapping: File = { + path: recognizerDateTimeTsconfigPath, + content: JSON.stringify({ + include: ["src"] + }) + }; + const recognizerDateTimeTsconfigWithPathMapping: File = { + path: recognizerDateTimeTsconfigPath, + content: JSON.stringify({ + compilerOptions: { + rootDir: "src", + baseUrl: "./", + paths: { + "@microsoft/*": ["../*"] + } + }, + include: ["src"] + }) + }; + const nodeModulesRecorgnizersText: SymLink = { + path: `${recognizersDateTime}/node_modules/@microsoft/recognizers-text`, + symLink: recognizersText + }; + const recognizerTextSrcFile: File = { + path: `${recognizersText}/src/recognizers-text.ts`, + content: `export class C { method () { return 10; } }` + }; + const recongnizerTextDistTypingFile: File = { + path: `${recognizersTextDist}/types/recognizers-text.d.ts`, + content: `export class C { method(): number; }` + }; + const recongnizerTextPackageJson: File = { + path: `${recognizersText}/package.json`, + content: JSON.stringify({ + typings: "dist/types/recognizers-text.d.ts" + }) + }; + const filesInProjectWithUnresolvedModule = [recognizerDateTimeTsconfigPath, libFile.path, recognizersDateTimeSrcFile.path]; + const filesInProjectWithResolvedModule = [...filesInProjectWithUnresolvedModule, recongnizerTextDistTypingFile.path]; + + function verifyErrors(session: TestSession, semanticErrors: protocol.Diagnostic[]) { + session.clearMessages(); + const expectedSequenceId = session.getNextSeq(); + session.executeCommandSeq({ + command: server.CommandNames.Geterr, + arguments: { + delay: 0, + files: [recognizersDateTimeSrcFile.path], + } + }); + + const host = session.host; + host.checkTimeoutQueueLengthAndRun(1); + + checkErrorMessage(session, "syntaxDiag", { file: recognizersDateTimeSrcFile.path, diagnostics: [] }); + session.clearMessages(); + + host.runQueuedImmediateCallbacks(1); + + checkErrorMessage(session, "semanticDiag", { file: recognizersDateTimeSrcFile.path, diagnostics: semanticErrors }); + session.clearMessages(); + + host.runQueuedImmediateCallbacks(1); + + checkErrorMessage(session, "suggestionDiag", { + file: recognizersDateTimeSrcFile.path, + diagnostics: [], + }); + checkCompleteEvent(session, 2, expectedSequenceId); + } + + function createSingleWatchMap(paths: string[]) { + return arrayToMap(paths, p => p, () => 1); + } + + function verifyWatchedFilesAndDirectories(host: TestServerHost, files: string[], directories: string[]) { + checkWatchedFilesDetailed(host, createSingleWatchMap(files.filter(f => f !== recognizersDateTimeSrcFile.path))); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, createSingleWatchMap(directories), /*recursive*/ true); + } + + function createSessionAndOpenFile(host: TestServerHost) { + const session = createSession(host, { canUseEvents: true }); + session.executeCommandSeq({ + command: protocol.CommandTypes.Open, + arguments: { + file: recognizersDateTimeSrcFile.path, + projectRootPath + } + }); + return session; + } + + function verifyModuleResolution(withPathMapping: boolean) { + describe(withPathMapping ? "when tsconfig file contains path mapping" : "when tsconfig does not contain path mapping", () => { + const filesWithSources = [libFile, recognizersDateTimeSrcFile, withPathMapping ? recognizerDateTimeTsconfigWithPathMapping : recognizerDateTimeTsconfigWithoutPathMapping, recognizerTextSrcFile, recongnizerTextPackageJson]; + const filesWithNodeModulesSetup = [...filesWithSources, nodeModulesRecorgnizersText]; + const filesAfterCompilation = [...filesWithNodeModulesSetup, recongnizerTextDistTypingFile]; + + const watchedDirectoriesWithResolvedModule = [`${recognizersDateTime}/src`, withPathMapping ? packages : recognizersDateTime, ...getTypeRootsFromLocation(recognizersDateTime)]; + const watchedDirectoriesWithUnresolvedModule = [recognizersDateTime, ...watchedDirectoriesWithResolvedModule, ...getNodeModuleDirectories(packages)]; + + function verifyProjectWithResolvedModule(session: TestSession) { + const projectService = session.getProjectService(); + const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath); + checkProjectActualFiles(project, filesInProjectWithResolvedModule); + verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule); + verifyErrors(session, []); + } + + function verifyProjectWithUnresolvedModule(session: TestSession) { + const projectService = session.getProjectService(); + const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath); + checkProjectActualFiles(project, filesInProjectWithUnresolvedModule); + verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule); + const startOffset = recognizersDateTimeSrcFile.content.indexOf('"') + 1; + verifyErrors(session, [ + createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + moduleNameInFile.length }, Diagnostics.Cannot_find_module_0, [moduleName]) + ]); + } + + it("when project compiles from sources", () => { + const host = createServerHost(filesWithSources); + const session = createSessionAndOpenFile(host); + verifyProjectWithUnresolvedModule(session); + + host.reloadFS(filesAfterCompilation); + host.runQueuedTimeoutCallbacks(); + + verifyProjectWithResolvedModule(session); + }); + + it("when project has node_modules setup but doesnt have modules in typings folder and then recompiles", () => { + const host = createServerHost(filesWithNodeModulesSetup); + const session = createSessionAndOpenFile(host); + verifyProjectWithUnresolvedModule(session); + + host.reloadFS(filesAfterCompilation); + host.runQueuedTimeoutCallbacks(); + + verifyProjectWithResolvedModule(session); + }); + + it("when project recompiles after deleting generated folders", () => { + const host = createServerHost(filesAfterCompilation); + const session = createSessionAndOpenFile(host); + + verifyProjectWithResolvedModule(session); + + host.removeFolder(recognizersTextDist, /*recursive*/ true); + host.runQueuedTimeoutCallbacks(); + + verifyProjectWithUnresolvedModule(session); + + host.ensureFileOrFolder(recongnizerTextDistTypingFile); + host.runQueuedTimeoutCallbacks(); + + verifyProjectWithResolvedModule(session); + }); + }); + } + + verifyModuleResolution(/*withPathMapping*/ false); + verifyModuleResolution(/*withPathMapping*/ true); + }); }); describe("tsserverProjectSystem forceConsistentCasingInFileNames", () => { diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 1ff6e4dbdf6..ef3d4955e42 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -93,25 +93,27 @@ interface Array {}` return isString((fileOrFolderOrSymLink).symLink); } - interface FSEntry { + interface FSEntryBase { path: Path; fullPath: string; modifiedTime: Date; } - interface FsFile extends FSEntry { + interface FsFile extends FSEntryBase { content: string; fileSize?: number; } - interface FsFolder extends FSEntry { + interface FsFolder extends FSEntryBase { entries: SortedArray; } - interface FsSymLink extends FSEntry { + interface FsSymLink extends FSEntryBase { symLink: string; } + type FSEntry = FsFile | FsFolder | FsSymLink; + function isFsFolder(s: FSEntry): s is FsFolder { return s && isArray((s).entries); } @@ -599,6 +601,24 @@ interface Array {}` } } + removeFolder(folderPath: string, recursive?: boolean) { + const path = this.toFullPath(folderPath); + const currentEntry = this.fs.get(path) as FsFolder; + Debug.assert(isFsFolder(currentEntry)); + if (recursive && currentEntry.entries.length) { + const subEntries = currentEntry.entries.slice(); + subEntries.forEach(fsEntry => { + if (isFsFolder(fsEntry)) { + this.removeFolder(fsEntry.fullPath, recursive); + } + else { + this.removeFileOrFolder(fsEntry, returnFalse); + } + }); + } + this.removeFileOrFolder(currentEntry, returnFalse); + } + // For overriding the methods invokeWatchedDirectoriesCallback(folderFullPath: string, relativePath: string) { invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath)); @@ -643,7 +663,7 @@ interface Array {}` } } - private toFsEntry(path: string): FSEntry { + private toFsEntry(path: string): FSEntryBase { const fullPath = getNormalizedAbsolutePath(path, this.currentDirectory); return { path: this.toPath(fullPath), From 1a2fda0f568b9e88d7e0f12e9dfda5a1cc6d545a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 4 May 2018 15:38:26 -0700 Subject: [PATCH 08/64] Add support to update module resolutions on watches from mono repo like setup with path mapping Fixes #22349 --- src/compiler/resolutionCache.ts | 50 +++++++++++++++---- .../unittests/tsserverProjectSystem.ts | 16 +++++- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 35e056546c0..d94bc6d4ae7 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -59,12 +59,15 @@ namespace ts { watcher: FileWatcher; /** ref count keeping this directory watch alive */ refCount: number; + /** map of refcount for the subDirectory */ + subDirectoryMap?: Map; } interface DirectoryOfFailedLookupWatch { dir: string; dirPath: Path; ignore?: true; + subDirectory?: Path; } export const maxNumberOfFilesToIterateForInvalidation = 256; @@ -393,18 +396,20 @@ namespace ts { } // Use some ancestor of the root directory + let subDirectory: Path | undefined; if (rootPath !== undefined) { while (!isInDirectoryPath(dirPath, rootPath)) { const parentPath = getDirectoryPath(dirPath); if (parentPath === dirPath) { break; } + subDirectory = dirPath.slice(parentPath.length + directorySeparator.length) as Path; dirPath = parentPath; dir = getDirectoryPath(dir); } } - return filterFSRootDirectoriesToWatch({ dir, dirPath }, dirPath); + return filterFSRootDirectoriesToWatch({ dir, dirPath, subDirectory }, dirPath); } function isPathWithDefaultFailedLookupExtension(path: Path) { @@ -427,7 +432,7 @@ namespace ts { let setAtRoot = false; for (const failedLookupLocation of failedLookupLocations) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); - const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + const { dir, dirPath, ignore , subDirectory } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); if (!ignore) { // If the failed lookup location path is not one of the supported extensions, // store it in the custom path @@ -439,7 +444,7 @@ namespace ts { setAtRoot = true; } else { - setDirectoryWatcher(dir, dirPath); + setDirectoryWatcher(dir, dirPath, subDirectory); } } } @@ -449,13 +454,20 @@ namespace ts { } } - function setDirectoryWatcher(dir: string, dirPath: Path) { - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + function setDirectoryWatcher(dir: string, dirPath: Path, subDirectory?: Path) { + let dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); if (dirWatcher) { dirWatcher.refCount++; } else { - directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }); + dirWatcher = { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }; + directoryWatchesOfFailedLookups.set(dirPath, dirWatcher); + } + + if (subDirectory) { + const subDirectoryMap = dirWatcher.subDirectoryMap || (dirWatcher.subDirectoryMap = createMap()); + const existing = subDirectoryMap.get(subDirectory) || 0; + subDirectoryMap.set(subDirectory, existing + 1); } } @@ -473,7 +485,7 @@ namespace ts { let removeAtRoot = false; for (const failedLookupLocation of failedLookupLocations) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); - const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + const { dirPath, ignore, subDirectory } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); if (!ignore) { const refCount = customFailedLookupPaths.get(failedLookupLocationPath); if (refCount) { @@ -490,7 +502,7 @@ namespace ts { removeAtRoot = true; } else { - removeDirectoryWatcher(dirPath); + removeDirectoryWatcher(dirPath, subDirectory); } } } @@ -499,12 +511,30 @@ namespace ts { } } - function removeDirectoryWatcher(dirPath: string) { + function removeDirectoryWatcher(dirPath: string, subDirectory?: Path) { const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + if (subDirectory) { + const existing = dirWatcher.subDirectoryMap.get(subDirectory); + if (existing === 1) { + dirWatcher.subDirectoryMap.delete(subDirectory); + } + else { + dirWatcher.subDirectoryMap.set(subDirectory, existing - 1); + } + } // Do not close the watcher yet since it might be needed by other failed lookup locations. dirWatcher.refCount--; } + function inWatchedSubdirectory(dirPath: Path, fileOrDirectoryPath: Path) { + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + if (!dirWatcher || !dirWatcher.subDirectoryMap) return false; + return forEachKey(dirWatcher.subDirectoryMap, subDirectory => { + const fullSubDirectory = `${dirPath}/${subDirectory}` as Path; + return fullSubDirectory === fileOrDirectoryPath || isInDirectoryPath(fullSubDirectory, fileOrDirectoryPath); + }); + } + function createDirectoryWatcher(directory: string, dirPath: Path) { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); @@ -516,7 +546,7 @@ namespace ts { // If the files are added to project root or node_modules directory, always run through the invalidation process // Otherwise run through invalidation only if adding to the immediate directory if (!allFilesHaveInvalidatedResolution && - dirPath === rootPath || isNodeModulesDirectory(dirPath) || getDirectoryPath(fileOrDirectoryPath) === dirPath) { + (dirPath === rootPath || isNodeModulesDirectory(dirPath) || getDirectoryPath(fileOrDirectoryPath) === dirPath || inWatchedSubdirectory(dirPath, fileOrDirectoryPath))) { if (invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) { resolutionHost.onInvalidatedResolution(); } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 3404eb5a767..f54bd56f1ba 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -7861,7 +7861,13 @@ new C();` host.reloadFS(filesAfterCompilation); host.runQueuedTimeoutCallbacks(); - verifyProjectWithResolvedModule(session); + if (withPathMapping) { + verifyProjectWithResolvedModule(session); + } + else { + // Cannot handle the resolution update + verifyProjectWithUnresolvedModule(session); + } }); it("when project recompiles after deleting generated folders", () => { @@ -7878,7 +7884,13 @@ new C();` host.ensureFileOrFolder(recongnizerTextDistTypingFile); host.runQueuedTimeoutCallbacks(); - verifyProjectWithResolvedModule(session); + if (withPathMapping) { + verifyProjectWithResolvedModule(session); + } + else { + // Cannot handle the resolution update + verifyProjectWithUnresolvedModule(session); + } }); }); } From 21a6a9afccd9bcb4de12a9b85006d16e9984f67b Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 May 2018 15:51:46 -0700 Subject: [PATCH 09/64] Remove unused interface (#23905) --- src/compiler/utilities.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3f7affcc044..7cf00b04846 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6,13 +6,6 @@ namespace ts { export const externalHelpersModuleNameText = "tslib"; - export interface ReferencePathMatchResult { - fileReference?: FileReference; - diagnosticMessage?: DiagnosticMessage; - isNoDefaultLib?: boolean; - isTypeReferenceDirective?: boolean; - } - export function getDeclarationOfKind(symbol: Symbol, kind: T["kind"]): T { const declarations = symbol.declarations; if (declarations) { From ea966387012291a9dec2f8ecf1703fb79674580d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 4 May 2018 15:59:55 -0700 Subject: [PATCH 10/64] Fix indentation --- src/services/outliningElementsCollector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index c58e122356a..eb5bfa4c0d5 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -185,7 +185,7 @@ namespace ts.OutliningElementsCollector { return spanForObjectOrArrayLiteral(n); case SyntaxKind.ArrayLiteralExpression: return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken); - } + } function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { // If the block has no leading keywords and is inside an array literal, From cecad276621d13958f527fcf620b16eb46c5db9f Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 May 2018 16:58:07 -0700 Subject: [PATCH 11/64] findAllReferences: Treat a nested property in a jsdoc type literal as a definition (#23901) * findAllReferences: Treat a nested property in a jsdoc type literal as a definition * Fix lint --- src/compiler/utilities.ts | 10 ++++++++-- .../fourslash/findAllReferencesJsDocTypeLiteral.ts | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7cf00b04846..22eb3d2c97c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2102,8 +2102,14 @@ namespace ts { if (isDeclaration(name.parent)) { return name.parent.name === name; } - const binExp = name.parent.parent; - return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name; + else if (isQualifiedName(name.parent)) { + const tag = name.parent.parent; + return isJSDocParameterTag(tag) && tag.name === name.parent; + } + else { + const binExp = name.parent.parent; + return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name; + } default: return false; } diff --git a/tests/cases/fourslash/findAllReferencesJsDocTypeLiteral.ts b/tests/cases/fourslash/findAllReferencesJsDocTypeLiteral.ts index 5234faf9d64..48befe13442 100644 --- a/tests/cases/fourslash/findAllReferencesJsDocTypeLiteral.ts +++ b/tests/cases/fourslash/findAllReferencesJsDocTypeLiteral.ts @@ -8,9 +8,9 @@ //// * @param {string} o.x - a thing, its ok //// * @param {number} o.y - another thing //// * @param {Object} o.nested - very nested -//// * @param {boolean} o.nested.[|great|] - much greatness +//// * @param {boolean} o.nested.[|{| "isWriteAccess": true, "isDefinition": true |}great|] - much greatness //// * @param {number} o.nested.times - twice? probably!?? //// */ //// function f(o) { return o.nested.[|great|]; } -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) great: boolean"); From e8cd6b1111b72c5c9575d7a609d737291c8ee17a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 4 May 2018 17:10:48 -0700 Subject: [PATCH 12/64] Suggest json files in completion when resolveJsonModule is set and module resolution is node Fixes #23899 --- src/services/pathCompletions.ts | 13 ++++++++++--- tests/cases/fourslash/completionsPathsJsonModule.ts | 12 ++++++++++++ .../fourslash/completionsPathsJsonModuleWithAmd.ts | 12 ++++++++++++ ...etionsPathsJsonModuleWithoutResolveJsonModule.ts | 11 +++++++++++ .../fourslash/completionsPathsRelativeJsonModule.ts | 12 ++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/completionsPathsJsonModule.ts create mode 100644 tests/cases/fourslash/completionsPathsJsonModuleWithAmd.ts create mode 100644 tests/cases/fourslash/completionsPathsJsonModuleWithoutResolveJsonModule.ts create mode 100644 tests/cases/fourslash/completionsPathsRelativeJsonModule.ts diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 7fd3b7cfd0b..e2725bd46fa 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -27,7 +27,7 @@ namespace ts.Completions.PathCompletions { const scriptDirectory = getDirectoryPath(scriptPath); if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) { - const extensions = getSupportedExtensions(compilerOptions); + const extensions = getSupportExtensionsForModuleResolution(compilerOptions); if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, compilerOptions, host, scriptPath); @@ -42,6 +42,13 @@ namespace ts.Completions.PathCompletions { } } + function getSupportExtensionsForModuleResolution(compilerOptions: CompilerOptions) { + const extensions = getSupportedExtensions(compilerOptions); + return compilerOptions.resolveJsonModule && getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? + extensions.concat(Extension.Json) : + extensions; + } + /** * Takes a script path and returns paths for all potential folders that could be merged with its * containing folder via the "rootDirs" compiler option @@ -122,7 +129,7 @@ namespace ts.Completions.PathCompletions { continue; } - const foundFileName = includeExtensions ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath)); + const foundFileName = includeExtensions || fileExtensionIs(filePath, Extension.Json) ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath)); if (!foundFiles.has(foundFileName)) { foundFiles.set(foundFileName, true); @@ -162,7 +169,7 @@ namespace ts.Completions.PathCompletions { const result: NameAndKind[] = []; - const fileExtensions = getSupportedExtensions(compilerOptions); + const fileExtensions = getSupportExtensionsForModuleResolution(compilerOptions); if (baseUrl) { const projectDir = compilerOptions.project || host.getCurrentDirectory(); const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); diff --git a/tests/cases/fourslash/completionsPathsJsonModule.ts b/tests/cases/fourslash/completionsPathsJsonModule.ts new file mode 100644 index 00000000000..6d1a621d69a --- /dev/null +++ b/tests/cases/fourslash/completionsPathsJsonModule.ts @@ -0,0 +1,12 @@ +/// + +// @moduleResolution: node +// @resolveJsonModule: true + +// @Filename: /project/node_modules/test.json +////not read + +// @Filename: /project/index.ts +////import { } from "/**/"; + +verify.completionsAt("", ["test.json"], { isNewIdentifierLocation: true }); \ No newline at end of file diff --git a/tests/cases/fourslash/completionsPathsJsonModuleWithAmd.ts b/tests/cases/fourslash/completionsPathsJsonModuleWithAmd.ts new file mode 100644 index 00000000000..8a2388655af --- /dev/null +++ b/tests/cases/fourslash/completionsPathsJsonModuleWithAmd.ts @@ -0,0 +1,12 @@ +/// + +// @module: amd +// @resolveJsonModule: true + +// @Filename: /project/test.json +////not read + +// @Filename: /project/index.ts +////import { } from ".//**/"; + +verify.completionsAt("", [], { isNewIdentifierLocation: true }); \ No newline at end of file diff --git a/tests/cases/fourslash/completionsPathsJsonModuleWithoutResolveJsonModule.ts b/tests/cases/fourslash/completionsPathsJsonModuleWithoutResolveJsonModule.ts new file mode 100644 index 00000000000..432fc6e858b --- /dev/null +++ b/tests/cases/fourslash/completionsPathsJsonModuleWithoutResolveJsonModule.ts @@ -0,0 +1,11 @@ +/// + +// @moduleResolution: node + +// @Filename: /project/test.json +////not read + +// @Filename: /project/index.ts +////import { } from ".//**/"; + +verify.completionsAt("", [], { isNewIdentifierLocation: true }); diff --git a/tests/cases/fourslash/completionsPathsRelativeJsonModule.ts b/tests/cases/fourslash/completionsPathsRelativeJsonModule.ts new file mode 100644 index 00000000000..93a6ac6e4e2 --- /dev/null +++ b/tests/cases/fourslash/completionsPathsRelativeJsonModule.ts @@ -0,0 +1,12 @@ +/// + +// @moduleResolution: node +// @resolveJsonModule: true + +// @Filename: /project/test.json +////not read + +// @Filename: /project/index.ts +////import { } from ".//**/"; + +verify.completionsAt("", ["test.json"], { isNewIdentifierLocation: true }); \ No newline at end of file From fa94fb079c42f406eaa936469b9ac66ca2bc614a Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Sat, 5 May 2018 02:44:35 +0200 Subject: [PATCH 13/64] Always yield await in async generator --- src/compiler/transformers/esnext.ts | 50 +++++--- .../reference/asyncImportNestedYield.js | 7 +- ...ter.asyncGenerators.classMethods.es2015.js | 4 +- ...mitter.asyncGenerators.classMethods.es5.js | 10 +- ...cGenerators.functionDeclarations.es2015.js | 4 +- ...syncGenerators.functionDeclarations.es5.js | 10 +- ...ncGenerators.functionExpressions.es2015.js | 4 +- ...asyncGenerators.functionExpressions.es5.js | 10 +- ...cGenerators.objectLiteralMethods.es2015.js | 4 +- ...syncGenerators.objectLiteralMethods.es5.js | 10 +- .../reference/emitter.forAwait.es2015.js | 6 +- .../reference/emitter.forAwait.es2017.js | 6 +- .../reference/emitter.forAwait.es5.js | 111 +++++++++--------- ...mportHelpersNoHelpersForAsyncGenerators.js | 9 +- 14 files changed, 137 insertions(+), 108 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index e60a39eecd2..fde07b6323e 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -118,28 +118,44 @@ namespace ts { } function visitYieldExpression(node: YieldExpression) { - if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator && node.asteriskToken) { - const expression = visitNode(node.expression, visitor, isExpression); - return setOriginalNode( - setTextRange( - createYield( - createAwaitHelper(context, - updateYield( - node, - node.asteriskToken, - createAsyncDelegatorHelper( - context, - createAsyncValuesHelper(context, expression, expression), - expression + if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { + if (node.asteriskToken) { + const expression = visitNode(node.expression, visitor, isExpression); + + return setOriginalNode( + setTextRange( + createYield( + createAwaitHelper(context, + updateYield( + node, + node.asteriskToken, + createAsyncDelegatorHelper( + context, + createAsyncValuesHelper(context, expression, expression), + expression + ) ) ) - ) + ), + node ), node - ), - node - ); + ); + } + + if (node.expression && node.expression.kind !== SyntaxKind.AwaitExpression) { + return setOriginalNode( + setTextRange( + createYield( + createDownlevelAwait(node.expression) + ), + node + ), + node + ); + } } + return visitEachChild(node, visitor, context); } diff --git a/tests/baselines/reference/asyncImportNestedYield.js b/tests/baselines/reference/asyncImportNestedYield.js index 4c83c6caf17..ac27e581186 100644 --- a/tests/baselines/reference/asyncImportNestedYield.js +++ b/tests/baselines/reference/asyncImportNestedYield.js @@ -54,9 +54,10 @@ function foo() { return __asyncGenerator(this, arguments, function foo_1() { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, "foo"]; - case 1: return [4 /*yield*/, __await.apply(void 0, [Promise.resolve().then(function () { return require(_a.sent()); })])]; - case 2: + case 0: return [4 /*yield*/, __await("foo")]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: return [4 /*yield*/, __await.apply(void 0, [Promise.resolve().then(function () { return require(_a.sent()); })])]; + case 3: Promise.resolve().then(function () { return require((_a.sent())["default"]); }); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 639e56f7b7e..0eb63ae638f 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -136,7 +136,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar class C3 { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield 1; + const x = yield yield __await(1); }); } } @@ -210,7 +210,7 @@ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { class C5 { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield 1; }); })()))); + const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield yield __await(1); }); })()))); }); } } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index 359c86683dd..827e1e535df 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -239,8 +239,9 @@ var C3 = /** @class */ (function () { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } @@ -412,8 +413,9 @@ var C5 = /** @class */ (function () { switch (_a.label) { case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index f8d5b9b158e..f3cde3c01ea 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -100,7 +100,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; function f3() { return __asyncGenerator(this, arguments, function* f3_1() { - const x = yield 1; + const x = yield yield __await(1); }); } //// [F4.js] @@ -170,7 +170,7 @@ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { }; function f5() { return __asyncGenerator(this, arguments, function* f5_1() { - const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield 1; }); })()))); + const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield yield __await(1); }); })()))); }); } //// [F6.js] diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index 9ca02ccdfaa..4895ff855e6 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -195,8 +195,9 @@ function f3() { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } @@ -358,8 +359,9 @@ function f5() { switch (_a.label) { case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index a25653a10fd..fb5577ef8d1 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -100,7 +100,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; const f3 = function () { return __asyncGenerator(this, arguments, function* () { - const x = yield 1; + const x = yield yield __await(1); }); }; //// [F4.js] @@ -170,7 +170,7 @@ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { }; const f5 = function () { return __asyncGenerator(this, arguments, function* () { - const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield 1; }); })()))); + const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield yield __await(1); }); })()))); }); }; //// [F6.js] diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index 22a934c6f67..25d688d5115 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -195,8 +195,9 @@ var f3 = function () { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } @@ -358,8 +359,9 @@ var f5 = function () { switch (_a.label) { case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 9cce459c9da..025713c1d1c 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -119,7 +119,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar const o3 = { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield 1; + const x = yield yield __await(1); }); } }; @@ -193,7 +193,7 @@ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) { const o5 = { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield 1; }); })()))); + const x = yield __await(yield* __asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function* () { yield yield __await(1); }); })()))); }); } }; diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 6b50d4c0834..32d6ce06c46 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -214,8 +214,9 @@ var o3 = { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } @@ -381,8 +382,9 @@ var o5 = { switch (_a.label) { case 0: return [5 /*yield**/, __values(__asyncDelegator(__asyncValues((function () { return __asyncGenerator(this, arguments, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, 1]; - case 1: + case 0: return [4 /*yield*/, __await(1)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.forAwait.es2015.js b/tests/baselines/reference/emitter.forAwait.es2015.js index ade1964638f..5f84389cd4e 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.js +++ b/tests/baselines/reference/emitter.forAwait.es2015.js @@ -135,7 +135,7 @@ function f3() { let y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - const x = yield __await(y_1_1.value); + const x = yield yield __await(__await(y_1_1.value)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -178,7 +178,7 @@ function f4() { let x, y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - x = yield __await(y_1_1.value); + x = yield yield __await(__await(y_1_1.value)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -256,7 +256,7 @@ function f6() { let y; try { outer: for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - const x = yield __await(y_1_1.value); + const x = yield yield __await(__await(y_1_1.value)); continue outer; } } diff --git a/tests/baselines/reference/emitter.forAwait.es2017.js b/tests/baselines/reference/emitter.forAwait.es2017.js index df401094158..525c7176372 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.js +++ b/tests/baselines/reference/emitter.forAwait.es2017.js @@ -115,7 +115,7 @@ function f3() { let y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - const x = yield __await(y_1_1.value); + const x = yield yield __await(__await(y_1_1.value)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -158,7 +158,7 @@ function f4() { let x, y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - x = yield __await(y_1_1.value); + x = yield yield __await(__await(y_1_1.value)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } @@ -226,7 +226,7 @@ function f6() { let y; try { outer: for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield __await(y_1.next()), !y_1_1.done;) { - const x = yield __await(y_1_1.value); + const x = yield yield __await(__await(y_1_1.value)); continue outer; } } diff --git a/tests/baselines/reference/emitter.forAwait.es5.js b/tests/baselines/reference/emitter.forAwait.es5.js index d847c216bb2..956ef4a4f02 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.js +++ b/tests/baselines/reference/emitter.forAwait.es5.js @@ -259,35 +259,36 @@ function f3() { return __generator(this, function (_b) { switch (_b.label) { case 0: - _b.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 7, 8, 13]); y_1 = __asyncValues(y); _b.label = 1; case 1: return [4 /*yield*/, __await(y_1.next())]; case 2: - if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 5]; - return [4 /*yield*/, __await(y_1_1.value)]; - case 3: + if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 6]; + return [4 /*yield*/, __await(__await(y_1_1.value))]; + case 3: return [4 /*yield*/, _b.sent()]; + case 4: x = _b.sent(); - _b.label = 4; - case 4: return [3 /*break*/, 1]; - case 5: return [3 /*break*/, 12]; - case 6: + _b.label = 5; + case 5: return [3 /*break*/, 1]; + case 6: return [3 /*break*/, 13]; + case 7: e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; - return [3 /*break*/, 12]; - case 7: - _b.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, __await(_a.call(y_1))]; + return [3 /*break*/, 13]; case 8: + _b.trys.push([8, , 11, 12]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 10]; + return [4 /*yield*/, __await(_a.call(y_1))]; + case 9: _b.sent(); - _b.label = 9; - case 9: return [3 /*break*/, 11]; - case 10: + _b.label = 10; + case 10: return [3 /*break*/, 12]; + case 11: if (e_1) throw e_1.error; return [7 /*endfinally*/]; - case 11: return [7 /*endfinally*/]; - case 12: return [2 /*return*/]; + case 12: return [7 /*endfinally*/]; + case 13: return [2 /*return*/]; } }); }); @@ -350,35 +351,36 @@ function f4() { return __generator(this, function (_b) { switch (_b.label) { case 0: - _b.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 7, 8, 13]); y_1 = __asyncValues(y); _b.label = 1; case 1: return [4 /*yield*/, __await(y_1.next())]; case 2: - if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 5]; - return [4 /*yield*/, __await(y_1_1.value)]; - case 3: + if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 6]; + return [4 /*yield*/, __await(__await(y_1_1.value))]; + case 3: return [4 /*yield*/, _b.sent()]; + case 4: x = _b.sent(); - _b.label = 4; - case 4: return [3 /*break*/, 1]; - case 5: return [3 /*break*/, 12]; - case 6: + _b.label = 5; + case 5: return [3 /*break*/, 1]; + case 6: return [3 /*break*/, 13]; + case 7: e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; - return [3 /*break*/, 12]; - case 7: - _b.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, __await(_a.call(y_1))]; + return [3 /*break*/, 13]; case 8: + _b.trys.push([8, , 11, 12]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 10]; + return [4 /*yield*/, __await(_a.call(y_1))]; + case 9: _b.sent(); - _b.label = 9; - case 9: return [3 /*break*/, 11]; - case 10: + _b.label = 10; + case 10: return [3 /*break*/, 12]; + case 11: if (e_1) throw e_1.error; return [7 /*endfinally*/]; - case 11: return [7 /*endfinally*/]; - case 12: return [2 /*return*/]; + case 12: return [7 /*endfinally*/]; + case 13: return [2 /*return*/]; } }); }); @@ -523,35 +525,36 @@ function f6() { return __generator(this, function (_b) { switch (_b.label) { case 0: - _b.trys.push([0, 6, 7, 12]); + _b.trys.push([0, 7, 8, 13]); y_1 = __asyncValues(y); _b.label = 1; case 1: return [4 /*yield*/, __await(y_1.next())]; case 2: - if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 5]; - return [4 /*yield*/, __await(y_1_1.value)]; - case 3: + if (!(y_1_1 = _b.sent(), !y_1_1.done)) return [3 /*break*/, 6]; + return [4 /*yield*/, __await(__await(y_1_1.value))]; + case 3: return [4 /*yield*/, _b.sent()]; + case 4: x = _b.sent(); - return [3 /*break*/, 4]; - case 4: return [3 /*break*/, 1]; - case 5: return [3 /*break*/, 12]; - case 6: + return [3 /*break*/, 5]; + case 5: return [3 /*break*/, 1]; + case 6: return [3 /*break*/, 13]; + case 7: e_1_1 = _b.sent(); e_1 = { error: e_1_1 }; - return [3 /*break*/, 12]; - case 7: - _b.trys.push([7, , 10, 11]); - if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 9]; - return [4 /*yield*/, __await(_a.call(y_1))]; + return [3 /*break*/, 13]; case 8: + _b.trys.push([8, , 11, 12]); + if (!(y_1_1 && !y_1_1.done && (_a = y_1.return))) return [3 /*break*/, 10]; + return [4 /*yield*/, __await(_a.call(y_1))]; + case 9: _b.sent(); - _b.label = 9; - case 9: return [3 /*break*/, 11]; - case 10: + _b.label = 10; + case 10: return [3 /*break*/, 12]; + case 11: if (e_1) throw e_1.error; return [7 /*endfinally*/]; - case 11: return [7 /*endfinally*/]; - case 12: return [2 /*return*/]; + case 12: return [7 /*endfinally*/]; + case 13: return [2 /*return*/]; } }); }); diff --git a/tests/baselines/reference/importHelpersNoHelpersForAsyncGenerators.js b/tests/baselines/reference/importHelpersNoHelpersForAsyncGenerators.js index 699c4faf921..14057a6cdab 100644 --- a/tests/baselines/reference/importHelpersNoHelpersForAsyncGenerators.js +++ b/tests/baselines/reference/importHelpersNoHelpersForAsyncGenerators.js @@ -22,12 +22,13 @@ function f() { case 0: return [4 /*yield*/, tslib_1.__await(1)]; case 1: _a.sent(); - return [4 /*yield*/, 2]; - case 2: + return [4 /*yield*/, tslib_1.__await(2)]; + case 2: return [4 /*yield*/, _a.sent()]; + case 3: _a.sent(); return [5 /*yield**/, tslib_1.__values(tslib_1.__asyncDelegator(tslib_1.__asyncValues([3])))]; - case 3: return [4 /*yield*/, tslib_1.__await.apply(void 0, [_a.sent()])]; - case 4: + case 4: return [4 /*yield*/, tslib_1.__await.apply(void 0, [_a.sent()])]; + case 5: _a.sent(); return [2 /*return*/]; } From 4318d975310a00730c51fe7eab3e8644d1360f09 Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Sat, 5 May 2018 02:45:33 +0200 Subject: [PATCH 14/64] Revert "Resolve promise inside async generator" This reverts commit 3e4279195f3eabdf1a473e0acaa942175ad81d7c. --- src/compiler/transformers/esnext.ts | 9 +-- .../reference/asyncImportNestedYield.js | 9 +-- ...ter.asyncGenerators.classMethods.es2015.js | 81 +++---------------- ...mitter.asyncGenerators.classMethods.es5.js | 81 +++---------------- ...cGenerators.functionDeclarations.es2015.js | 63 ++------------- ...syncGenerators.functionDeclarations.es5.js | 63 ++------------- ...ncGenerators.functionExpressions.es2015.js | 63 ++------------- ...asyncGenerators.functionExpressions.es5.js | 63 ++------------- ...cGenerators.objectLiteralMethods.es2015.js | 63 ++------------- ...syncGenerators.objectLiteralMethods.es5.js | 63 ++------------- .../reference/emitter.forAwait.es2015.js | 27 +------ .../reference/emitter.forAwait.es2017.js | 27 +------ .../reference/emitter.forAwait.es5.js | 27 +------ 13 files changed, 71 insertions(+), 568 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index fde07b6323e..109025c375d 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -922,14 +922,7 @@ namespace ts { return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/asyncImportNestedYield.js b/tests/baselines/reference/asyncImportNestedYield.js index ac27e581186..776caed5167 100644 --- a/tests/baselines/reference/asyncImportNestedYield.js +++ b/tests/baselines/reference/asyncImportNestedYield.js @@ -38,14 +38,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 0eb63ae638f..15bab8b98ae 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -68,14 +68,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -94,14 +87,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -121,14 +107,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -158,14 +137,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -185,14 +157,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -222,14 +187,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -249,14 +207,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -276,14 +227,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -305,14 +249,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index 827e1e535df..85357291a6b 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -95,14 +95,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -154,14 +147,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -219,14 +205,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -295,14 +274,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -371,14 +343,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -465,14 +430,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -530,14 +488,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -589,14 +540,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -661,14 +605,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index f3cde3c01ea..31b0fb24a56 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -37,14 +37,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -61,14 +54,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -86,14 +72,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -121,14 +100,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -146,14 +118,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -181,14 +146,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -206,14 +164,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index 4895ff855e6..ef965090196 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -64,14 +64,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -118,14 +111,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -178,14 +164,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -249,14 +228,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -320,14 +292,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -409,14 +374,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -469,14 +427,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index fb5577ef8d1..f460d91bc8b 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -37,14 +37,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -61,14 +54,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -86,14 +72,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -121,14 +100,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -146,14 +118,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -181,14 +146,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -206,14 +164,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index 25d688d5115..e175f32278c 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -64,14 +64,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -118,14 +111,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -178,14 +164,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -249,14 +228,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -320,14 +292,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -409,14 +374,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -469,14 +427,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 025713c1d1c..9a0a9a42b36 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -51,14 +51,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -77,14 +70,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -104,14 +90,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -141,14 +120,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -168,14 +140,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -205,14 +170,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -232,14 +190,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 32d6ce06c46..608d57e5eb7 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -78,14 +78,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -134,14 +127,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -196,14 +182,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -269,14 +248,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -342,14 +314,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -433,14 +398,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -495,14 +453,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es2015.js b/tests/baselines/reference/emitter.forAwait.es2015.js index 5f84389cd4e..980dc3a8e3b 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.js +++ b/tests/baselines/reference/emitter.forAwait.es2015.js @@ -118,14 +118,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -161,14 +154,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -238,14 +224,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es2017.js b/tests/baselines/reference/emitter.forAwait.es2017.js index 525c7176372..9fcf6190990 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.js +++ b/tests/baselines/reference/emitter.forAwait.es2017.js @@ -98,14 +98,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -141,14 +134,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -208,14 +194,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } diff --git a/tests/baselines/reference/emitter.forAwait.es5.js b/tests/baselines/reference/emitter.forAwait.es5.js index 956ef4a4f02..277bc2b4e6b 100644 --- a/tests/baselines/reference/emitter.forAwait.es5.js +++ b/tests/baselines/reference/emitter.forAwait.es5.js @@ -241,14 +241,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -333,14 +326,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } @@ -506,14 +492,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { - if (r.value instanceof __await) { - Promise.resolve(r.value.v).then(fulfill, reject); - } else if (r.value instanceof Promise) { - r.value.then(function(rv) { settle(q[0][2], resolve(r, rv)); }, function(e) { settle(q[0][3], resolve(r, e)); }); - } else { settle(q[0][2], r); } - } - function resolve(r, rv) { return { value: rv, done: r.done }; } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } From 4c48e2ca058b184f4b3901fc20d7353c19ee779f Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 5 May 2018 04:10:17 +0000 Subject: [PATCH 15/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1cfc21834fe..0364ba3402a 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2520,6 +2520,15 @@ + + + + + + + + + @@ -2547,6 +2556,15 @@ + + + + + + + + + @@ -7428,6 +7446,15 @@ + + + + + + + + + @@ -9366,6 +9393,15 @@ + + + + + + + + + From a2d42a6421945054ce1f099661cf9aea1280e5fe Mon Sep 17 00:00:00 2001 From: Paul Koerbitz Date: Sat, 5 May 2018 17:03:05 +0200 Subject: [PATCH 16/64] Add WSH as an alias for WScript in scripthost.d.ts --- src/lib/scripthost.d.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/scripthost.d.ts b/src/lib/scripthost.d.ts index 1fbd185949f..c3ac4a7e656 100644 --- a/src/lib/scripthost.d.ts +++ b/src/lib/scripthost.d.ts @@ -201,6 +201,11 @@ declare var WScript: { Sleep(intTime: number): void; }; +/** + * WSH is an alias for WScript under Windows Script Host + */ +declare var WSH: typeof WScript; + /** * Represents an Automation SAFEARRAY */ From 8072dae16bd0bf86f4ca4a0cbea1213a315340e4 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 5 May 2018 12:02:29 -0700 Subject: [PATCH 17/64] Change kind name to `imports` --- src/harness/fourslash.ts | 4 ++-- src/services/types.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 6c6d95c0682..6464f4a5f82 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2470,7 +2470,7 @@ Actual: ${stringify(fullActual)}`); Harness.IO.log(stringify(spans)); } - public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "import") { + public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "imports") { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { @@ -4302,7 +4302,7 @@ namespace FourSlashInterface { this.state.verifyCurrentNameOrDottedNameSpanText(text); } - public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "import") { + public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "imports") { this.state.verifyOutliningSpans(spans, kind); } diff --git a/src/services/types.ts b/src/services/types.ts index 48eb25f8a3e..d832bca7ce7 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -827,7 +827,7 @@ namespace ts { Comment = "comment", Region = "region", Code = "code", - Import = "import" + Imports = "imports" } export const enum OutputFileType { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 778bc0e51fd..7532c6779fb 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4893,7 +4893,7 @@ declare namespace ts { Comment = "comment", Region = "region", Code = "code", - Import = "import" + Imports = "imports" } enum OutputFileType { JavaScript = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index deabfc15441..33e9347f481 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4893,7 +4893,7 @@ declare namespace ts { Comment = "comment", Region = "region", Code = "code", - Import = "import" + Imports = "imports" } enum OutputFileType { JavaScript = 0, From 12ed49bada77c43a4319249813cef00a9a11bf84 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 5 May 2018 12:04:12 -0700 Subject: [PATCH 18/64] Revert adding named import binding list outlining spans --- src/services/outliningElementsCollector.ts | 20 ++----------------- .../fourslash/getOutliningSpansForImports.ts | 4 ++-- ...tliningSpansForImportsWithNamedBindings.ts | 17 ---------------- 3 files changed, 4 insertions(+), 37 deletions(-) delete mode 100644 tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index eb5bfa4c0d5..0d13a3c33a4 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -20,28 +20,12 @@ namespace ts.OutliningElementsCollector { if (current === n) break; const firstImport = statements[current]; while (current < n && isAnyImportSyntax(statements[current])) { - visitImportNode(statements[current] as AnyImportSyntax, sourceFile, cancellationToken, out); + addOutliningForLeadingCommentsForNode(statements[current], sourceFile, cancellationToken, out); current++; } const lastImport = current < n ? statements[current - 1] : statements[n - 1]; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(findChildOfKind(firstImport, SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), lastImport.getEnd(), OutliningSpanKind.Import)); - } - } - - function visitImportNode(node: AnyImportSyntax, sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push) { - // Add outlining spans for comments if they exist - addOutliningForLeadingCommentsForNode(node, sourceFile, cancellationToken, out); - // Add outlining spans for the import statement itself if applicable - if (isImportDeclaration(node) && node.importClause && node.importClause.namedBindings && - node.importClause.namedBindings.kind !== SyntaxKind.NamespaceImport && node.importClause.namedBindings.elements.length) { - const openToken = findChildOfKind(node.importClause.namedBindings, SyntaxKind.OpenBraceToken, sourceFile); - const closeToken = findChildOfKind(node.importClause.namedBindings, SyntaxKind.CloseBraceToken, sourceFile); - if (openToken && closeToken) { - out.push(createOutliningSpan( - createTextSpanFromBounds(openToken.getStart(sourceFile), closeToken.getEnd()), - OutliningSpanKind.Import, createTextSpanFromNode(node, sourceFile))); - } + out.push(createOutliningSpanFromBounds(findChildOfKind(firstImport, SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), lastImport.getEnd(), OutliningSpanKind.Imports)); } } diff --git a/tests/cases/fourslash/getOutliningSpansForImports.ts b/tests/cases/fourslash/getOutliningSpansForImports.ts index 198adc9c551..23b625059c5 100644 --- a/tests/cases/fourslash/getOutliningSpansForImports.ts +++ b/tests/cases/fourslash/getOutliningSpansForImports.ts @@ -4,7 +4,7 @@ ////[|import * as ns from "mod"; //// ////import d from "mod"; -////import [|{ a, b, c }|] from "mod"; +////import { a, b, c } from "mod"; //// ////import r = require("mod");|] //// @@ -14,7 +14,7 @@ ////// another set of imports ////[|import * as ns from "mod"; ////import d from "mod"; -////import [|{ a, b, c }|] from "mod"; +////import { a, b, c } from "mod"; ////import r = require("mod");|] verify.outliningSpansInCurrentFile(test.ranges(), "import"); diff --git a/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts b/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts deleted file mode 100644 index 4e5336ba3b0..00000000000 --- a/tests/cases/fourslash/getOutliningSpansForImportsWithNamedBindings.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - - -////[|import [|{ -//// a, -//// b as B, -//// c -////}|] from "mod"; -//// -//// -////import { } from "mod"; -////import * as ns from "mod"; -////import d from "mod";|] - -verify.outliningSpansInCurrentFile(test.ranges(), "import"); - - From 3bc3f2d4041da90eee0c0e06f7cd45a3aa66e29b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 5 May 2018 12:38:59 -0700 Subject: [PATCH 19/64] Add comments to kinds --- src/services/types.ts | 7 +++++++ tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++++ tests/baselines/reference/api/typescript.d.ts | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/src/services/types.ts b/src/services/types.ts index d832bca7ce7..69e33ce6732 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -824,9 +824,16 @@ namespace ts { } export const enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + + /** Declarations and expressions */ Code = "code", + + /** Contiguous blocks of import declarations */ Imports = "imports" } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 7532c6779fb..5d1ef5e7a75 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4890,9 +4890,13 @@ declare namespace ts { kind: OutliningSpanKind; } enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + /** Declarations and expressions */ Code = "code", + /** Contiguous blocks of import declarations */ Imports = "imports" } enum OutputFileType { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 33e9347f481..211c2fbbdf4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4890,9 +4890,13 @@ declare namespace ts { kind: OutliningSpanKind; } enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + /** Declarations and expressions */ Code = "code", + /** Contiguous blocks of import declarations */ Imports = "imports" } enum OutputFileType { From 64d6b24c87cd39e7e0cede6391190e10e022a3c9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 5 May 2018 13:22:48 -0700 Subject: [PATCH 20/64] Code review comments --- src/services/outliningElementsCollector.ts | 6 +++--- tests/cases/fourslash/getOutliningSpansForImports.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 0d13a3c33a4..91754e2ac76 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -18,14 +18,14 @@ namespace ts.OutliningElementsCollector { current++; } if (current === n) break; - const firstImport = statements[current]; + const firstImport = current; while (current < n && isAnyImportSyntax(statements[current])) { addOutliningForLeadingCommentsForNode(statements[current], sourceFile, cancellationToken, out); current++; } - const lastImport = current < n ? statements[current - 1] : statements[n - 1]; + const lastImport = current - 1; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(findChildOfKind(firstImport, SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), lastImport.getEnd(), OutliningSpanKind.Imports)); + out.push(createOutliningSpanFromBounds(findChildOfKind(statements[firstImport], SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), statements[lastImport].getEnd(), OutliningSpanKind.Imports)); } } diff --git a/tests/cases/fourslash/getOutliningSpansForImports.ts b/tests/cases/fourslash/getOutliningSpansForImports.ts index 23b625059c5..703c4f5891c 100644 --- a/tests/cases/fourslash/getOutliningSpansForImports.ts +++ b/tests/cases/fourslash/getOutliningSpansForImports.ts @@ -17,4 +17,4 @@ ////import { a, b, c } from "mod"; ////import r = require("mod");|] -verify.outliningSpansInCurrentFile(test.ranges(), "import"); +verify.outliningSpansInCurrentFile(test.ranges(), "imports"); From f3e4f596a96caa6895b325df16f602e0934ef16b Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 5 May 2018 22:10:26 +0000 Subject: [PATCH 21/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 098f08d8cd2..055e897855c 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2519,6 +2519,15 @@ + + + + + + + + + @@ -2546,6 +2555,15 @@ + + + + + + + + + @@ -4283,6 +4301,12 @@ + + + + + + @@ -5579,6 +5603,12 @@ + + + + + + @@ -7427,6 +7457,15 @@ + + + + + + + + + @@ -9365,6 +9404,15 @@ + + + + + + + + + From 34323b69fbfbe445c701c015b8a4112e489b25e0 Mon Sep 17 00:00:00 2001 From: Zzzen <843968788@qq.com> Date: Sat, 5 May 2018 22:51:16 +0800 Subject: [PATCH 22/64] Document highlights on async/await keywords should highlight other occurrences in the same body fix #22944 --- src/services/documentHighlights.ts | 33 +++++++++++++++++++ .../fourslash/getOccurrencesAsyncAwait.ts | 22 +++++++++++++ .../fourslash/getOccurrencesAsyncAwait2.ts | 16 +++++++++ .../fourslash/getOccurrencesAsyncAwait3.ts | 13 ++++++++ 4 files changed, 84 insertions(+) create mode 100644 tests/cases/fourslash/getOccurrencesAsyncAwait.ts create mode 100644 tests/cases/fourslash/getOccurrencesAsyncAwait2.ts create mode 100644 tests/cases/fourslash/getOccurrencesAsyncAwait3.ts diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 69c75548fe5..3c898551ac9 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -74,6 +74,10 @@ namespace ts.DocumentHighlights { case SyntaxKind.GetKeyword: case SyntaxKind.SetKeyword: return getFromAllDeclarations(isAccessor, [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword]); + case SyntaxKind.AwaitKeyword: + return useParent(node.parent, isAwaitExpression, getAsyncAndAwaitOccurrences); + case SyntaxKind.AsyncKeyword: + return highlightSpans(getAsyncAndAwaitOccurrences(node)); default: return isModifierKind(node.kind) && (isDeclaration(node.parent) || isVariableStatement(node.parent)) ? highlightSpans(getModifierOccurrences(node.kind, node.parent)) @@ -368,6 +372,35 @@ namespace ts.DocumentHighlights { return keywords; } + function getAsyncAndAwaitOccurrences(node: Node): Node[] | undefined { + const func = getContainingFunction(node); + if (!func) { + return undefined; + } + + const keywords: Node[] = []; + + if (func.modifiers) { + func.modifiers.forEach(modifier => { + pushKeywordIf(keywords, modifier, SyntaxKind.AsyncKeyword); + }); + } + + forEachChild(func, aggregate); + + return keywords; + + function aggregate(node: Node): void { + if (isAwaitExpression(node)) { + pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.AwaitKeyword); + } + // Do not cross function boundaries. + if (!isFunctionLike(node)) { + forEachChild(node, aggregate); + } + } + } + function getIfElseOccurrences(ifStatement: IfStatement, sourceFile: SourceFile): HighlightSpan[] { const keywords = getIfElseKeywords(ifStatement, sourceFile); const result: HighlightSpan[] = []; diff --git a/tests/cases/fourslash/getOccurrencesAsyncAwait.ts b/tests/cases/fourslash/getOccurrencesAsyncAwait.ts new file mode 100644 index 00000000000..f2224255d14 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesAsyncAwait.ts @@ -0,0 +1,22 @@ +/// + +////[|async|] function f() { +//// [|await|] 100; +//// [|a/**/wait|] [|await|] 200; +//// return [|await|] async function () { +//// await 300; +//// } +////} +////async function g() { +//// await 300; +//// async function f() { +//// await 400; +//// } +////} + +verify.rangesAreOccurrences(false); + +goTo.marker(); +for (const range of test.ranges()) { + verify.occurrencesAtPositionContains(range, false); +} diff --git a/tests/cases/fourslash/getOccurrencesAsyncAwait2.ts b/tests/cases/fourslash/getOccurrencesAsyncAwait2.ts new file mode 100644 index 00000000000..530f26bc18d --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesAsyncAwait2.ts @@ -0,0 +1,16 @@ +/// + +////[|a/**/sync|] function f() { +//// [|await|] 100; +//// [|await|] [|await|] 200; +//// return [|await|] async function () { +//// await 300; +//// } +////} + +verify.rangesAreOccurrences(false); + +goTo.marker(); +for (const range of test.ranges()) { + verify.occurrencesAtPositionContains(range, false); +} diff --git a/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts b/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts new file mode 100644 index 00000000000..67d56167b82 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts @@ -0,0 +1,13 @@ +/// + +// Not valid TS ('await' expression is only allowed within an async function.) + +////a/**/wait 100; +////async function f() { +//// await 300; +////} + +verify.rangesAreOccurrences(false); + +goTo.marker(); +verify.occurrencesAtPositionCount(0); \ No newline at end of file From 1fda3a4165b83fb82b666bd15e601c73590b52ec Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 6 May 2018 19:08:54 +0900 Subject: [PATCH 23/64] Check detected npm path is existing --- src/server/typingsInstaller/nodeTypingsInstaller.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 35f926f1c14..875f5d881f0 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -2,7 +2,8 @@ namespace ts.server.typingsInstaller { const fs: { - appendFileSync(file: string, content: string): void + appendFileSync(file: string, content: string): void; + existsSync(path: string): boolean; } = require("fs"); const path: { @@ -32,11 +33,12 @@ namespace ts.server.typingsInstaller { /** Used if `--npmLocation` is not passed. */ function getDefaultNPMLocation(processName: string) { if (path.basename(processName).indexOf("node") === 0) { - return `"${path.join(path.dirname(process.argv[0]), "npm")}"`; - } - else { - return "npm"; + const npmPath = `"${path.join(path.dirname(process.argv[0]), "npm")}"`; + if (fs.existsSync(npmPath)) { + return npmPath; + } } + return "npm"; } interface TypesRegistryFile { From 7fa5f70b9a8faaa9a2060e629a894cb3f83d991b Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 10:08:38 -0700 Subject: [PATCH 24/64] Remove verify.referencesAre, verify.referencesOf, verify.rangesReferenceEachOther (#23900) --- src/harness/fourslash.ts | 75 +++---------------- src/services/findAllReferences.ts | 2 +- .../esModuleInteropFindAllReferences.ts | 4 +- .../esModuleInteropFindAllReferences2.ts | 4 +- ...rPropertyAccessExpressionHeritageClause.ts | 7 +- .../findAllReferencesDynamicImport1.ts | 2 +- .../findAllReferencesDynamicImport2.ts | 8 +- tests/cases/fourslash/findAllRefsBadImport.ts | 5 +- .../cases/fourslash/findAllRefsThisKeyword.ts | 2 +- .../findAllRefsThisKeywordMultipleFiles.ts | 2 +- tests/cases/fourslash/findAllRefsTypedef.ts | 4 +- tests/cases/fourslash/fourslash.ts | 11 --- tests/cases/fourslash/server/references01.ts | 18 +++-- .../server/referencesInConfiguredProject.ts | 17 ++++- .../cases/fourslash/tsxFindAllReferences1.ts | 7 +- .../cases/fourslash/tsxFindAllReferences10.ts | 8 +- .../cases/fourslash/tsxFindAllReferences11.ts | 5 +- .../cases/fourslash/tsxFindAllReferences2.ts | 6 +- .../cases/fourslash/tsxFindAllReferences3.ts | 10 +-- .../cases/fourslash/tsxFindAllReferences4.ts | 8 +- .../cases/fourslash/tsxFindAllReferences5.ts | 4 +- .../cases/fourslash/tsxFindAllReferences6.ts | 5 +- .../cases/fourslash/tsxFindAllReferences7.ts | 8 +- .../cases/fourslash/tsxFindAllReferences8.ts | 8 +- .../cases/fourslash/tsxFindAllReferences9.ts | 8 +- .../tsxFindAllReferencesUnionElementType1.ts | 8 +- .../tsxFindAllReferencesUnionElementType2.ts | 4 +- 27 files changed, 101 insertions(+), 149 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 513c0fdd8f4..7807d10b0f9 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1142,32 +1142,6 @@ namespace FourSlash { } } - private verifyReferencesAre(expectedReferences: Range[]) { - const actualReferences = this.getReferencesAtCaret() || []; - - if (actualReferences.length > expectedReferences.length) { - // Find the unaccounted-for reference. - for (const actual of actualReferences) { - if (!ts.forEach(expectedReferences, r => r.pos === actual.textSpan.start)) { - this.raiseError(`A reference ${stringify(actual)} is unaccounted for.`); - } - } - // Probably will never reach here. - this.raiseError(`There are ${actualReferences.length} references but only ${expectedReferences.length} were expected.`); - } - - for (const reference of expectedReferences) { - const { fileName, pos, end } = reference; - if (reference.marker && reference.marker.data) { - const { isWriteAccess, isDefinition } = reference.marker.data as { isWriteAccess?: boolean, isDefinition?: boolean }; - this.verifyReferencesWorker(actualReferences, fileName, pos, end, isWriteAccess, isDefinition); - } - else { - this.verifyReferencesWorker(actualReferences, fileName, pos, end); - } - } - } - private verifyDocumentHighlightsRespectFilesList(files: ReadonlyArray): void { const startFile = this.activeFile.fileName; for (const fileName of files) { @@ -1179,20 +1153,6 @@ namespace FourSlash { } } - public verifyReferencesOf(range: Range, references: Range[]) { - this.goToRangeStart(range); - this.verifyDocumentHighlightsRespectFilesList(unique(references, e => e.fileName)); - this.verifyReferencesAre(references); - } - - public verifyRangesReferenceEachOther(ranges?: Range[]) { - ranges = ranges || this.getRanges(); - assert(ranges.length); - for (const range of ranges) { - this.verifyReferencesOf(range, ranges); - } - } - public verifyReferenceGroups(starts: ArrayOrSingle | ArrayOrSingle, parts: ReadonlyArray | undefined): void { interface ReferenceGroupJson { definition: string | { text: string, range: ts.TextSpan }; @@ -1250,6 +1210,12 @@ namespace FourSlash { } } + // Necessary to have this function since `findReferences` isn't implemented in `client.ts` + public verifyGetReferencesForServerTest(expected: ReadonlyArray): void { + const refs = this.getReferencesAtCaret(); + assert.deepEqual(refs, expected); + } + public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) { ranges = ranges || this.getRanges(); this.verifyReferenceGroups(ranges, [{ definition, ranges }]); @@ -1314,23 +1280,6 @@ Actual: ${stringify(fullActual)}`); TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts")); } - private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) { - for (const reference of references) { - if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) { - if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) { - this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`); - } - if (typeof isDefinition !== "undefined" && reference.isDefinition !== isDefinition) { - this.raiseError(`verifyReferencesAtPositionListContains failed - item isDefinition value does not match, actual: ${reference.isDefinition}, expected: ${isDefinition}.`); - } - return; - } - } - - const missingItem = { fileName, start, end, isWriteAccess, isDefinition }; - this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`); - } - private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo { return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options); } @@ -4210,10 +4159,6 @@ namespace FourSlashInterface { this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected); } - public referencesOf(start: FourSlash.Range, references: FourSlash.Range[]) { - this.state.verifyReferencesOf(start, references); - } - public referenceGroups(starts: Many | Many, parts: ReferenceGroup[]) { this.state.verifyReferenceGroups(starts, parts); } @@ -4222,12 +4167,12 @@ namespace FourSlashInterface { this.state.verifyNoReferences(markerNameOrRange); } - public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[]) { - this.state.verifySingleReferenceGroup(definition, ranges); + public getReferencesForServerTest(expected: ReadonlyArray) { + this.state.verifyGetReferencesForServerTest(expected); } - public rangesReferenceEachOther(ranges?: FourSlash.Range[]) { - this.state.verifyRangesReferenceEachOther(ranges); + public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[]) { + this.state.verifySingleReferenceGroup(definition, ranges); } public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) { diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 8054ea666f3..9995bc858a0 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -119,7 +119,7 @@ namespace ts.FindAllReferences { const { node } = def; const symbol = checker.getSymbolAtLocation(node); const displayParts = symbol && SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( - checker, symbol, node.getSourceFile(), getContainerNode(node), node).displayParts; + checker, symbol, node.getSourceFile(), getContainerNode(node), node).displayParts || [textPart("this")]; return { node, name: "this", kind: ScriptElementKind.variableElement, displayParts }; } case "string": { diff --git a/tests/cases/fourslash/esModuleInteropFindAllReferences.ts b/tests/cases/fourslash/esModuleInteropFindAllReferences.ts index 5ec348bb120..4e493e58c24 100644 --- a/tests/cases/fourslash/esModuleInteropFindAllReferences.ts +++ b/tests/cases/fourslash/esModuleInteropFindAllReferences.ts @@ -4,11 +4,11 @@ // @Filename: /abc.d.ts ////declare module "a" { -//// export const [|x|]: number; +//// export const [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number; ////} // @Filename: /b.ts ////import a from "a"; ////a.[|x|]; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("const x: number"); diff --git a/tests/cases/fourslash/esModuleInteropFindAllReferences2.ts b/tests/cases/fourslash/esModuleInteropFindAllReferences2.ts index 55fc6cc89e4..e55129a357c 100644 --- a/tests/cases/fourslash/esModuleInteropFindAllReferences2.ts +++ b/tests/cases/fourslash/esModuleInteropFindAllReferences2.ts @@ -6,10 +6,10 @@ // @Filename: /a.d.ts ////export as namespace abc; -////export const [|x|]: number; +////export const [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number; // @Filename: /b.ts ////import a from "./a"; ////a.[|x|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup('const x: number'); diff --git a/tests/cases/fourslash/findAllReferPropertyAccessExpressionHeritageClause.ts b/tests/cases/fourslash/findAllReferPropertyAccessExpressionHeritageClause.ts index 2a0b6a57622..61dfb1c33bc 100644 --- a/tests/cases/fourslash/findAllReferPropertyAccessExpressionHeritageClause.ts +++ b/tests/cases/fourslash/findAllReferPropertyAccessExpressionHeritageClause.ts @@ -2,12 +2,9 @@ //// class B {} //// function foo() { -//// return {[|B|]: B}; +//// return {[|{| "isWriteAccess": true, "isDefinition": true |}B|]: B}; //// } //// class C extends (foo()).[|B|] {} //// class C1 extends foo().[|B|] {} -const ranges = test.ranges(); -for (const range of ranges) { - verify.referencesOf(range, ranges); -} \ No newline at end of file +verify.singleReferenceGroup("(property) B: typeof B"); diff --git a/tests/cases/fourslash/findAllReferencesDynamicImport1.ts b/tests/cases/fourslash/findAllReferencesDynamicImport1.ts index ad0f261388d..c2b6f359ba6 100644 --- a/tests/cases/fourslash/findAllReferencesDynamicImport1.ts +++ b/tests/cases/fourslash/findAllReferencesDynamicImport1.ts @@ -6,4 +6,4 @@ //// import("[|./foo|]") //// var x = import("[|./foo|]") -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup('module "/tests/cases/fourslash/foo"'); diff --git a/tests/cases/fourslash/findAllReferencesDynamicImport2.ts b/tests/cases/fourslash/findAllReferencesDynamicImport2.ts index 558e2fed7ef..6644a55ec1b 100644 --- a/tests/cases/fourslash/findAllReferencesDynamicImport2.ts +++ b/tests/cases/fourslash/findAllReferencesDynamicImport2.ts @@ -1,12 +1,12 @@ /// // @Filename: foo.ts -//// export function [|bar|]() { return "bar"; } +//// export function [|{| "isWriteAccess": true, "isDefinition": true |}bar|]() { return "bar"; } //// var x = import("./foo"); //// x.then(foo => { -//// foo.[|bar|](); +//// foo.[|bar|](); //// }) -verify.rangesReferenceEachOther(); -verify.rangesAreRenameLocations(); \ No newline at end of file +verify.singleReferenceGroup("function bar(): string"); +verify.rangesAreRenameLocations(); diff --git a/tests/cases/fourslash/findAllRefsBadImport.ts b/tests/cases/fourslash/findAllRefsBadImport.ts index 89a81d81f79..e04b72df384 100644 --- a/tests/cases/fourslash/findAllRefsBadImport.ts +++ b/tests/cases/fourslash/findAllRefsBadImport.ts @@ -1,7 +1,6 @@ /// -////import { [|ab|] as [|cd|] } from "doesNotExist"; +////import { [|ab|] as [|{| "isWriteAccess": true, "isDefinition": true |}cd|] } from "doesNotExist"; const [r0, r1] = test.ranges(); -verify.referencesOf(r0, [r1]); -verify.referencesOf(r1, [r1]); +verify.referenceGroups([r0, r1], [{ definition: "import cd", ranges: [r1] }]); diff --git a/tests/cases/fourslash/findAllRefsThisKeyword.ts b/tests/cases/fourslash/findAllRefsThisKeyword.ts index 61dd687fd64..975b4b37ac2 100644 --- a/tests/cases/fourslash/findAllRefsThisKeyword.ts +++ b/tests/cases/fourslash/findAllRefsThisKeyword.ts @@ -25,7 +25,7 @@ ////x.[|this|]; const [global, f0, f1, g0, g1, x, y, constructor, method, propDef, propUse] = test.ranges(); -verify.referencesOf(global, [global]); +verify.singleReferenceGroup("this", [global]); verify.referenceGroups(f0, [{ definition: "(parameter) this: any", ranges: [f0, f1] }]); verify.referenceGroups(f1, [{ definition: "this: any", ranges: [f0, f1] }]); verify.referenceGroups(g0, [{ definition: "(parameter) this: any", ranges: [g0, g1] }]); diff --git a/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts b/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts index a4bab7f876c..d94f2993d1d 100644 --- a/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts +++ b/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts @@ -12,4 +12,4 @@ //// // different 'this' //// function f(this) { return this; } -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("this"); diff --git a/tests/cases/fourslash/findAllRefsTypedef.ts b/tests/cases/fourslash/findAllRefsTypedef.ts index c7e2527405d..ecd690c10e5 100644 --- a/tests/cases/fourslash/findAllRefsTypedef.ts +++ b/tests/cases/fourslash/findAllRefsTypedef.ts @@ -5,11 +5,11 @@ // @Filename: /a.js /////** //// * @typedef I {Object} -//// * @prop [|p|] {number} +//// * @prop [|{| "isWriteAccess": true, "isDefinition": true |}p|] {number} //// */ //// /////** @type {I} */ ////let x; ////x.[|p|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) p: number"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index cf554831434..8a7aae00c24 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -253,12 +253,6 @@ declare namespace FourSlashInterface { noReferences(markerNameOrRange?: string | Range): void; symbolAtLocation(startRange: Range, ...declarationRanges: Range[]): void; typeOfSymbolAtLocation(range: Range, symbol: any, expected: string): void; - /** - * @deprecated, prefer 'referenceGroups' - * Like `referencesAre`, but goes to `start` first. - * `start` should be included in `references`. - */ - referencesOf(start: Range, references: Range[]): void; /** * For each of starts, asserts the ranges that are referenced from there. * This uses the 'findReferences' command instead of 'getReferencesAtPosition', so references are grouped by their definition. @@ -268,11 +262,6 @@ declare namespace FourSlashInterface { rangesAreOccurrences(isWriteAccess?: boolean): void; rangesWithSameTextAreRenameLocations(): void; rangesAreRenameLocations(options?: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: Range[] }); - /** - * Performs `referencesOf` for every range on the whole set. - * If `ranges` is omitted, this is `test.ranges()`. - */ - rangesReferenceEachOther(ranges?: Range[]): void; findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]): void; currentParameterHelpArgumentNameIs(name: string): void; currentParameterSpanIs(parameter: string): void; diff --git a/tests/cases/fourslash/server/references01.ts b/tests/cases/fourslash/server/references01.ts index 528f79de5b4..02e0c16f9c7 100644 --- a/tests/cases/fourslash/server/references01.ts +++ b/tests/cases/fourslash/server/references01.ts @@ -2,14 +2,22 @@ // Global class reference. -// @Filename: referencesForGlobals_1.ts -////class [|globalClass|] { +// @Filename: /referencesForGlobals_1.ts +////class [|{| "isWriteAccess": true, "isDefinition": true |}globalClass|] { //// public f() { } ////} -// @Filename: referencesForGlobals_2.ts +// @Filename: /referencesForGlobals_2.ts /////// ////var c = [|globalClass|](); -// Must reverse ranges so that referencesForGlobals_2 goes first -- otherwise referencesForGlobals_1 won't pick it up. -verify.rangesReferenceEachOther(test.ranges().reverse()); +const [r0, r1] = test.ranges(); +goTo.rangeStart(r1); +verify.getReferencesForServerTest([ + { fileName: "/referencesForGlobals_1.ts", isDefinition: true, isWriteAccess: true, textSpan: toSpan(r0) }, + { fileName: "/referencesForGlobals_2.ts", isDefinition: false, isWriteAccess: false, textSpan: toSpan(r1) }, +]); + +function toSpan(r: FourSlashInterface.Range) { + return { start: r.pos, length: r.end - r.pos }; +} diff --git a/tests/cases/fourslash/server/referencesInConfiguredProject.ts b/tests/cases/fourslash/server/referencesInConfiguredProject.ts index 109b5e36e4d..87ca2da9931 100644 --- a/tests/cases/fourslash/server/referencesInConfiguredProject.ts +++ b/tests/cases/fourslash/server/referencesInConfiguredProject.ts @@ -2,15 +2,24 @@ // Global class reference. -// @Filename: referencesForGlobals_1.ts +// @Filename: /referencesForGlobals_1.ts ////class [|globalClass|] { //// public f() { } ////} -// @Filename: referencesForGlobals_2.ts +// @Filename: /referencesForGlobals_2.ts ////var c = [|globalClass|](); -// @Filename: tsconfig.json +// @Filename: /tsconfig.json ////{ "files": ["referencesForGlobals_1.ts", "referencesForGlobals_2.ts"] } -verify.rangesReferenceEachOther(); +const [r0, r1] = test.ranges(); +goTo.rangeStart(r1); +verify.getReferencesForServerTest([ + { fileName: "/referencesForGlobals_1.ts", isDefinition: true, isWriteAccess: true, textSpan: toSpan(r0) }, + { fileName: "/referencesForGlobals_2.ts", isDefinition: false, isWriteAccess: false, textSpan: toSpan(r1) }, +]); + +function toSpan(r: FourSlashInterface.Range) { + return { start: r.pos, length: r.end - r.pos }; +} diff --git a/tests/cases/fourslash/tsxFindAllReferences1.ts b/tests/cases/fourslash/tsxFindAllReferences1.ts index 9b55901ba68..550dd05606c 100644 --- a/tests/cases/fourslash/tsxFindAllReferences1.ts +++ b/tests/cases/fourslash/tsxFindAllReferences1.ts @@ -4,7 +4,7 @@ //// declare module JSX { //// interface Element { } //// interface IntrinsicElements { -//// [|div|]: { +//// [|{| "isWriteAccess": true, "isDefinition": true |}div|]: { //// name?: string; //// isOpen?: boolean; //// }; @@ -13,4 +13,7 @@ //// } //// var x = <[|div|] />; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup(`(property) JSX.IntrinsicElements.div: { + name?: string; + isOpen?: boolean; +}`); diff --git a/tests/cases/fourslash/tsxFindAllReferences10.ts b/tests/cases/fourslash/tsxFindAllReferences10.ts index a027671ec3d..04ac864e4f2 100644 --- a/tests/cases/fourslash/tsxFindAllReferences10.ts +++ b/tests/cases/fourslash/tsxFindAllReferences10.ts @@ -15,7 +15,7 @@ //// className?: string; //// } //// interface ButtonProps extends ClickableProps { -//// [|onClick|](event?: React.MouseEvent): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}onClick|](event?: React.MouseEvent): void; //// } //// interface LinkProps extends ClickableProps { //// goTo: string; @@ -25,9 +25,9 @@ //// declare function MainButton(props: ButtonProps | LinkProps): JSX.Element; //// let opt = ; //// let opt = ; -//// let opt = {}} />; -//// let opt = {}} ignore-prop />; +//// let opt = {}} />; +//// let opt = {}} ignore-prop />; //// let opt = ; //// let opt = ; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("(method) ButtonProps.onClick(event?: any): void"); diff --git a/tests/cases/fourslash/tsxFindAllReferences11.ts b/tests/cases/fourslash/tsxFindAllReferences11.ts index ef2f7722243..8c7e7a46909 100644 --- a/tests/cases/fourslash/tsxFindAllReferences11.ts +++ b/tests/cases/fourslash/tsxFindAllReferences11.ts @@ -23,7 +23,6 @@ //// declare function MainButton(buttonProps: ButtonProps): JSX.Element; //// declare function MainButton(linkProps: LinkProps): JSX.Element; //// declare function MainButton(props: ButtonProps | LinkProps): JSX.Element; -//// let opt = ; // r1 +//// let opt = ; -const [r1] = test.ranges(); -verify.referencesOf(r1, [r1]); \ No newline at end of file +verify.singleReferenceGroup("(property) wrong: true"); diff --git a/tests/cases/fourslash/tsxFindAllReferences2.ts b/tests/cases/fourslash/tsxFindAllReferences2.ts index 8522874865a..e7fda5ab308 100644 --- a/tests/cases/fourslash/tsxFindAllReferences2.ts +++ b/tests/cases/fourslash/tsxFindAllReferences2.ts @@ -5,12 +5,12 @@ //// interface Element { } //// interface IntrinsicElements { //// div: { -//// [|name|]?: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}name|]?: string; //// isOpen?: boolean; //// }; //// span: { n: string; }; //// } //// } -//// var x =
; +//// var x =
; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("(property) name?: string"); diff --git a/tests/cases/fourslash/tsxFindAllReferences3.ts b/tests/cases/fourslash/tsxFindAllReferences3.ts index 2f78cc08ba9..2682e01e7d1 100644 --- a/tests/cases/fourslash/tsxFindAllReferences3.ts +++ b/tests/cases/fourslash/tsxFindAllReferences3.ts @@ -9,11 +9,11 @@ //// } //// class MyClass { //// props: { -//// [|name|]?: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}name|]?: string; //// size?: number; //// } -//// -//// -//// var x = ; +//// +//// +//// var x = ; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("(property) name?: string"); diff --git a/tests/cases/fourslash/tsxFindAllReferences4.ts b/tests/cases/fourslash/tsxFindAllReferences4.ts index a1309bfaef9..c932ea57f36 100644 --- a/tests/cases/fourslash/tsxFindAllReferences4.ts +++ b/tests/cases/fourslash/tsxFindAllReferences4.ts @@ -7,13 +7,13 @@ //// } //// interface ElementAttributesProperty { props } //// } -//// class [|MyClass|] { +//// class [|{| "isWriteAccess": true, "isDefinition": true |}MyClass|] { //// props: { //// name?: string; //// size?: number; //// } -//// -//// +//// +//// //// var x = <[|MyClass|] name='hello'>; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("class MyClass"); diff --git a/tests/cases/fourslash/tsxFindAllReferences5.ts b/tests/cases/fourslash/tsxFindAllReferences5.ts index 018b7568df1..9358dd73dc5 100644 --- a/tests/cases/fourslash/tsxFindAllReferences5.ts +++ b/tests/cases/fourslash/tsxFindAllReferences5.ts @@ -15,11 +15,11 @@ //// propString: string //// optional?: boolean //// } -//// declare function [|Opt|](attributes: OptionPropBag): JSX.Element; +//// declare function [|{| "isWriteAccess": true, "isDefinition": true |}Opt|](attributes: OptionPropBag): JSX.Element; //// let opt = <[|Opt|] />; //// let opt1 = <[|Opt|] propx={100} propString />; //// let opt2 = <[|Opt|] propx={100} optional/>; //// let opt3 = <[|Opt|] wrong />; //// let opt4 = <[|Opt|] propx={100} propString="hi" />; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("function Opt(attributes: OptionPropBag): JSX.Element"); diff --git a/tests/cases/fourslash/tsxFindAllReferences6.ts b/tests/cases/fourslash/tsxFindAllReferences6.ts index ad689a53baf..c0e119a4e45 100644 --- a/tests/cases/fourslash/tsxFindAllReferences6.ts +++ b/tests/cases/fourslash/tsxFindAllReferences6.ts @@ -17,7 +17,6 @@ //// optional?: boolean //// } //// declare function Opt(attributes: OptionPropBag): JSX.Element; -//// let opt = ; //r1 +//// let opt = ; -const [r1] = test.ranges(); -verify.referencesOf(r1, [r1]); \ No newline at end of file +verify.singleReferenceGroup("(property) wrong: true"); diff --git a/tests/cases/fourslash/tsxFindAllReferences7.ts b/tests/cases/fourslash/tsxFindAllReferences7.ts index b1f5231a198..37ea60c7a38 100644 --- a/tests/cases/fourslash/tsxFindAllReferences7.ts +++ b/tests/cases/fourslash/tsxFindAllReferences7.ts @@ -11,14 +11,14 @@ //// interface ElementAttributesProperty { props; } //// } //// interface OptionPropBag { -//// [|propx|]: number +//// [|{| "isWriteAccess": true, "isDefinition": true |}propx|]: number //// propString: string //// optional?: boolean //// } //// declare function Opt(attributes: OptionPropBag): JSX.Element; //// let opt = ; -//// let opt1 = ; -//// let opt2 = ; +//// let opt1 = ; +//// let opt2 = ; //// let opt3 = ; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("(property) OptionPropBag.propx: number"); diff --git a/tests/cases/fourslash/tsxFindAllReferences8.ts b/tests/cases/fourslash/tsxFindAllReferences8.ts index 434e8cf3303..0c216488892 100644 --- a/tests/cases/fourslash/tsxFindAllReferences8.ts +++ b/tests/cases/fourslash/tsxFindAllReferences8.ts @@ -20,9 +20,9 @@ //// interface LinkProps extends ClickableProps { //// goTo: string; //// } -//// declare function [|MainButton|](buttonProps: ButtonProps): JSX.Element; -//// declare function [|MainButton|](linkProps: LinkProps): JSX.Element; -//// declare function [|MainButton|](props: ButtonProps | LinkProps): JSX.Element; +//// declare function [|{| "isWriteAccess": true, "isDefinition": true |}MainButton|](buttonProps: ButtonProps): JSX.Element; +//// declare function [|{| "isWriteAccess": true, "isDefinition": true |}MainButton|](linkProps: LinkProps): JSX.Element; +//// declare function [|{| "isWriteAccess": true, "isDefinition": true |}MainButton|](props: ButtonProps | LinkProps): JSX.Element; //// let opt = <[|MainButton|] />; //// let opt = <[|MainButton|] children="chidlren" />; //// let opt = <[|MainButton|] onClick={()=>{}} />; @@ -30,4 +30,4 @@ //// let opt = <[|MainButton|] goTo="goTo" />; //// let opt = <[|MainButton|] wrong />; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("function MainButton(buttonProps: ButtonProps): JSX.Element (+2 overloads)"); diff --git a/tests/cases/fourslash/tsxFindAllReferences9.ts b/tests/cases/fourslash/tsxFindAllReferences9.ts index 5ac6ad344d8..9fe02500ad9 100644 --- a/tests/cases/fourslash/tsxFindAllReferences9.ts +++ b/tests/cases/fourslash/tsxFindAllReferences9.ts @@ -18,7 +18,7 @@ //// onClick(event?: React.MouseEvent): void; //// } //// interface LinkProps extends ClickableProps { -//// [|goTo|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}goTo|]: string; //// } //// declare function MainButton(buttonProps: ButtonProps): JSX.Element; //// declare function MainButton(linkProps: LinkProps): JSX.Element; @@ -27,8 +27,8 @@ //// let opt = ; //// let opt = {}} />; //// let opt = {}} ignore-prop />; -//// let opt = ; -//// let opt = ; +//// let opt = ; +//// let opt = ; //// let opt = ; -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("(property) LinkProps.goTo: string"); diff --git a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts index e7c2a1a567c..87adbc11873 100644 --- a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts +++ b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType1.ts @@ -18,7 +18,11 @@ //// return

World

; //// } -//// var [|SFCComp|] = SFC1 || SFC2; +//// var [|{| "isWriteAccess": true, "isDefinition": true |}SFCComp|] = SFC1 || SFC2; //// <[|SFCComp|] x={ "hi" } /> -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup(`var SFCComp: ((prop: { + x: number; +}) => JSX.Element) | ((prop: { + x: boolean; +}) => JSX.Element)`); diff --git a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts index 3089279b2e7..2498c8bf996 100644 --- a/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts +++ b/tests/cases/fourslash/tsxFindAllReferencesUnionElementType2.ts @@ -17,7 +17,7 @@ //// private method() { } //// } -//// var [|RCComp|] = RC1 || RC2; +//// var [|{| "isWriteAccess": true, "isDefinition": true |}RCComp|] = RC1 || RC2; //// <[|RCComp|] /> -verify.rangesReferenceEachOther(); \ No newline at end of file +verify.singleReferenceGroup("var RCComp: typeof RC1"); From d6701d3987ffc0b31d8880791c7cd9d0129926a5 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 11:06:21 -0700 Subject: [PATCH 25/64] Replace `verify.rangesReferenceEachOther` with `verify.singleReferenceGroup` (#23933) --- tests/cases/fourslash/findAllRefsImportType.ts | 2 +- tests/cases/fourslash/findAllRefsTypedef_importType.ts | 2 +- .../fourslash/findAllRefs_importType_meaningAtLocation.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/cases/fourslash/findAllRefsImportType.ts b/tests/cases/fourslash/findAllRefsImportType.ts index dda48580b66..9f1fa09436e 100644 --- a/tests/cases/fourslash/findAllRefsImportType.ts +++ b/tests/cases/fourslash/findAllRefsImportType.ts @@ -9,4 +9,4 @@ // @Filename: /b.js ////type T = import("./a").[|N|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("type N = number"); diff --git a/tests/cases/fourslash/findAllRefsTypedef_importType.ts b/tests/cases/fourslash/findAllRefsTypedef_importType.ts index a9104fb398e..ddd0cb7c966 100644 --- a/tests/cases/fourslash/findAllRefsTypedef_importType.ts +++ b/tests/cases/fourslash/findAllRefsTypedef_importType.ts @@ -11,4 +11,4 @@ /////** @type {import('./a').[|Foo|]} */ ////const x = 0; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("type Foo = number"); diff --git a/tests/cases/fourslash/findAllRefs_importType_meaningAtLocation.ts b/tests/cases/fourslash/findAllRefs_importType_meaningAtLocation.ts index 21cc1afebb0..4bb5cb27a17 100644 --- a/tests/cases/fourslash/findAllRefs_importType_meaningAtLocation.ts +++ b/tests/cases/fourslash/findAllRefs_importType_meaningAtLocation.ts @@ -9,5 +9,5 @@ ////const x: typeof import("./a").[|T|] = 0; const [r0, r1, r2, r3] = test.ranges(); -verify.rangesReferenceEachOther([r0, r2]); -verify.rangesReferenceEachOther([r1, r3]); +verify.singleReferenceGroup("type T = 0\nconst T: 0", [r0, r2]); +verify.singleReferenceGroup("type T = 0\nconst T: 0", [r1, r3]); From a05feed839b5f19b04369ca9cc4909794b4ea4ad Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 11:33:00 -0700 Subject: [PATCH 26/64] generateGetAccessorAndSetAccessor: Preserve a parameter property declaration (#23318) --- .../generateGetAccessorAndSetAccessor.ts | 25 +++++-------------- src/services/utilities.ts | 6 ++--- ...efactorConvertToGetAccessAndSetAccess16.ts | 3 +-- ...efactorConvertToGetAccessAndSetAccess17.ts | 3 +-- ...efactorConvertToGetAccessAndSetAccess18.ts | 3 +-- ...efactorConvertToGetAccessAndSetAccess22.ts | 3 +-- 6 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 33ecbbaab66..523ad97e5fa 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -49,7 +49,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { : undefined; const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined; - updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers, container); + updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers); const getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); const setAccessor = generateSetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); @@ -60,7 +60,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const edits = changeTracker.getChanges(); const renameFilename = file.fileName; const renameLocationOffset = isIdentifier(fieldName) ? 0 : -1; - const renameLocation = renameLocationOffset + getRenameLocation(edits, renameFilename, fieldName.text, /*isDeclaredBeforeUse*/ false); + const renameLocation = renameLocationOffset + getRenameLocation(edits, renameFilename, fieldName.text, /*preferLastLocation*/ isParameter(declaration)); return { renameFilename, renameLocation, edits }; } @@ -163,26 +163,12 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { changeTracker.replaceNode(file, declaration, property); } - function updateParameterPropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: ParameterDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined, classLikeContainer: ClassLikeDeclaration) { - const property = createProperty( - declaration.decorators, - modifiers, - fieldName, - declaration.questionToken, - declaration.type, - declaration.initializer - ); - - changeTracker.insertNodeAtClassStart(file, classLikeContainer, property); - changeTracker.deleteNodeInList(file, declaration); - } - - function updatePropertyAssignmentDeclaration (changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) { + function updatePropertyAssignmentDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) { const assignment = updatePropertyAssignment(declaration, fieldName, declaration.initializer); changeTracker.replacePropertyAssignment(file, declaration, assignment); } - function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: AcceptedDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined, container: ContainerDeclaration) { + function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: AcceptedDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) { if (isPropertyDeclaration(declaration)) { updatePropertyDeclaration(changeTracker, file, declaration, fieldName, modifiers); } @@ -190,7 +176,8 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { updatePropertyAssignmentDeclaration(changeTracker, file, declaration, fieldName); } else { - updateParameterPropertyDeclaration(changeTracker, file, declaration, fieldName, modifiers, container); + changeTracker.replaceNode(file, declaration, + updateParameter(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer)); } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 453abdea9ee..d5694c936de 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1538,7 +1538,7 @@ namespace ts { * user was before extracting it. */ /* @internal */ - export function getRenameLocation(edits: ReadonlyArray, renameFilename: string, name: string, isDeclaredBeforeUse: boolean): number { + export function getRenameLocation(edits: ReadonlyArray, renameFilename: string, name: string, preferLastLocation: boolean): number { let delta = 0; let lastPos = -1; for (const { fileName, textChanges } of edits) { @@ -1550,7 +1550,7 @@ namespace ts { lastPos = span.start + delta + index; // If the reference comes first, return immediately. - if (!isDeclaredBeforeUse) { + if (!preferLastLocation) { return lastPos; } } @@ -1559,7 +1559,7 @@ namespace ts { } // If the declaration comes first, return the position of the last occurrence. - Debug.assert(isDeclaredBeforeUse); + Debug.assert(preferLastLocation); Debug.assert(lastPos >= 0); return lastPos; } diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts index 03cadfbceec..bb2e20eaa8f 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts @@ -10,7 +10,6 @@ edit.applyRefactor({ actionName: "Generate 'get' and 'set' accessors", actionDescription: "Generate 'get' and 'set' accessors", newContent: `class A { - private /*RENAME*/_a: string; public get a(): string { return this._a; } @@ -18,6 +17,6 @@ edit.applyRefactor({ this._a = value; } - constructor() { } + constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts index a04932fe68d..85d5c001490 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts @@ -10,7 +10,6 @@ edit.applyRefactor({ actionName: "Generate 'get' and 'set' accessors", actionDescription: "Generate 'get' and 'set' accessors", newContent: `class A { - private /*RENAME*/_a: string; protected get a(): string { return this._a; } @@ -18,6 +17,6 @@ edit.applyRefactor({ this._a = value; } - constructor() { } + constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts index a48361288e0..4bc91af7ff5 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts @@ -10,7 +10,6 @@ edit.applyRefactor({ actionName: "Generate 'get' and 'set' accessors", actionDescription: "Generate 'get' and 'set' accessors", newContent: `class A { - private /*RENAME*/_a: string; public get a(): string { return this._a; } @@ -18,6 +17,6 @@ edit.applyRefactor({ this._a = value; } - constructor() { } + constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts index d1002c2e809..68622150edc 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts @@ -11,7 +11,6 @@ edit.applyRefactor({ actionName: "Generate 'get' and 'set' accessors", actionDescription: "Generate 'get' and 'set' accessors", newContent: `class A { - private /*RENAME*/_a: string; public get a(): string { return this._a; } @@ -20,7 +19,7 @@ edit.applyRefactor({ } public a_1: number; - constructor() { } + constructor(private /*RENAME*/_a: string) { } }`, }); From 92296b34ddb2ecbf7ee200d630a575462b1a4c3e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 7 May 2018 12:14:53 -0700 Subject: [PATCH 27/64] Rename --- src/services/pathCompletions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index e2725bd46fa..f42d70a0c52 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -27,7 +27,7 @@ namespace ts.Completions.PathCompletions { const scriptDirectory = getDirectoryPath(scriptPath); if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) { - const extensions = getSupportExtensionsForModuleResolution(compilerOptions); + const extensions = getSupportedExtensionsForModuleResolution(compilerOptions); if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, compilerOptions, host, scriptPath); @@ -42,7 +42,7 @@ namespace ts.Completions.PathCompletions { } } - function getSupportExtensionsForModuleResolution(compilerOptions: CompilerOptions) { + function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions) { const extensions = getSupportedExtensions(compilerOptions); return compilerOptions.resolveJsonModule && getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? extensions.concat(Extension.Json) : @@ -169,7 +169,7 @@ namespace ts.Completions.PathCompletions { const result: NameAndKind[] = []; - const fileExtensions = getSupportExtensionsForModuleResolution(compilerOptions); + const fileExtensions = getSupportedExtensionsForModuleResolution(compilerOptions); if (baseUrl) { const projectDir = compilerOptions.project || host.getCurrentDirectory(); const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); From 05b250691f3eceac877309d592aafefe1434366c Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 12:38:38 -0700 Subject: [PATCH 28/64] Expose ProjectService to plugins (#23824) Add refreshDiagnostics() method to Project --- src/server/editorServices.ts | 3 ++- src/server/project.ts | 7 ++++++- tests/baselines/reference/api/tsserverlibrary.d.ts | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 4a91b287986..085ac1d8d73 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -577,7 +577,8 @@ namespace ts.server { return this.pendingProjectUpdates.has(project.getProjectName()); } - private sendProjectsUpdatedInBackgroundEvent() { + /* @internal */ + sendProjectsUpdatedInBackgroundEvent() { if (!this.eventHandler) { return; } diff --git a/src/server/project.ts b/src/server/project.ts index 9d8b3a36dd4..a97fb9a9bf0 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -164,7 +164,7 @@ namespace ts.server { return hasOneOrMoreJsAndNoTsFiles(this); } - public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} { + public static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined { const resolvedPath = normalizeSlashes(host.resolvePath(combinePaths(initialDir, "node_modules"))); log(`Loading ${moduleName} from ${initialDir} (resolved to ${resolvedPath})`); const result = host.require(resolvedPath, moduleName); @@ -1102,6 +1102,11 @@ namespace ts.server { } } + /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */ + refreshDiagnostics() { + this.projectService.sendProjectsUpdatedInBackgroundEvent(); + } + private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) { try { if (typeof pluginModuleFactory !== "function") { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5d1ef5e7a75..16277d93b0c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7748,7 +7748,7 @@ declare namespace ts.server { private readonly cancellationToken; isNonTsProject(): boolean; isJsOnlyProject(): boolean; - static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; + static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {} | undefined; isKnownTypesPackageName(name: string): boolean; installPackage(options: InstallPackageOptions): Promise; private readonly typingsCache; @@ -7829,6 +7829,8 @@ declare namespace ts.server { protected removeRoot(info: ScriptInfo): void; protected enableGlobalPlugins(): void; protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]): void; + /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */ + refreshDiagnostics(): void; private enableProxy; } /** @@ -8081,7 +8083,6 @@ declare namespace ts.server { updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void; private delayEnsureProjectForOpenFiles; private delayUpdateProjectGraph; - private sendProjectsUpdatedInBackgroundEvent; private delayUpdateProjectGraphs; setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void; findProject(projectName: string): Project | undefined; From 2604bb4dd3663e620df4fcc30781c317de26cedf Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 12:39:00 -0700 Subject: [PATCH 29/64] Add 'string' ScriptElementKind (#23821) --- src/services/completions.ts | 2 +- src/services/types.ts | 3 +++ tests/baselines/reference/api/tsserverlibrary.d.ts | 4 +++- tests/baselines/reference/api/typescript.d.ts | 4 +++- tests/cases/fourslash/completionForStringLiteral_details.ts | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index f5aba7f99e8..ef1bd5ebd3c 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -81,7 +81,7 @@ namespace ts.Completions { return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, entries }; } case StringLiteralCompletionKind.Types: { - const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.typeElement, sortText: "0" })); + const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.string, sortText: "0" })); return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, entries }; } default: diff --git a/src/services/types.ts b/src/services/types.ts index 69e33ce6732..cd4a497f694 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -995,6 +995,9 @@ namespace ts { * */ jsxAttribute = "JSX attribute", + + /** String literal */ + string = "string", } export const enum ScriptElementKindModifier { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 16277d93b0c..b8cb75677cb 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5021,7 +5021,9 @@ declare namespace ts { /** * */ - jsxAttribute = "JSX attribute" + jsxAttribute = "JSX attribute", + /** String literal */ + string = "string" } enum ScriptElementKindModifier { none = "", diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 211c2fbbdf4..ff0b1f65134 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5021,7 +5021,9 @@ declare namespace ts { /** * */ - jsxAttribute = "JSX attribute" + jsxAttribute = "JSX attribute", + /** String literal */ + string = "string" } enum ScriptElementKindModifier { none = "", diff --git a/tests/cases/fourslash/completionForStringLiteral_details.ts b/tests/cases/fourslash/completionForStringLiteral_details.ts index 46832bc9025..059770023c9 100644 --- a/tests/cases/fourslash/completionForStringLiteral_details.ts +++ b/tests/cases/fourslash/completionForStringLiteral_details.ts @@ -21,7 +21,7 @@ goTo.marker("path"); verify.completionListContains("other", "other", "", "script"); goTo.marker("type"); -verify.completionListContains("a", "a", "", "type"); +verify.completionListContains("a", "a", "", "string"); goTo.marker("prop"); verify.completionListContains("x", "(property) I.x: number", "Prop doc ", "property"); From 004a5581259ff590a400750eccf38b18c958acb4 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 12:40:33 -0700 Subject: [PATCH 30/64] Avoid unnecessary newline when inserting node at start of class (#23935) --- src/services/textChanges.ts | 28 +++++++++++-------- .../fourslash/codeFixAddMissingMember.ts | 1 - .../fourslash/codeFixAddMissingMember2.ts | 1 - .../fourslash/codeFixAddMissingMember3.ts | 1 - .../fourslash/codeFixAddMissingMember_all.ts | 1 - .../codeFixAddMissingMember_all_js.ts | 1 - .../codeFixUndeclaredInStaticMethod.ts | 9 ------ .../fourslash/codeFixUndeclaredMethod.ts | 6 ---- ...efactorConvertToGetAccessAndSetAccess16.ts | 1 - ...efactorConvertToGetAccessAndSetAccess17.ts | 1 - ...efactorConvertToGetAccessAndSetAccess18.ts | 1 - ...efactorConvertToGetAccessAndSetAccess22.ts | 1 - 12 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index d5ef90ff3ef..eca1c639196 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -442,19 +442,25 @@ namespace ts.textChanges { public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration, newElement: ClassElement): void { const clsStart = cls.getStart(sourceFile); - let prefix = ""; - let suffix = this.newLineCharacter; - if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) { - prefix = this.newLineCharacter; - // For `class C {\n}`, don't add the trailing "\n" - if (cls.members.length === 0 && !(positionsAreOnSameLine as any)(...getClassBraceEnds(cls, sourceFile), sourceFile)) { // TODO: GH#4130 remove 'as any' - suffix = ""; - } - } - const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options) + this.formatContext.options.indentSize; - this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, prefix, suffix }); + this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) }); + } + + private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration): { prefix: string, suffix: string } { + if (cls.members.length === 0) { + if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) { + // For `class C {\n}`, don't add the trailing "\n" + const shouldSuffix = (positionsAreOnSameLine as any)(...getClassBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any' + return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" }; + } + else { + return { prefix: "", suffix: this.newLineCharacter }; + } + } + else { + return { prefix: this.newLineCharacter, suffix: "" }; + } } public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node): this { diff --git a/tests/cases/fourslash/codeFixAddMissingMember.ts b/tests/cases/fourslash/codeFixAddMissingMember.ts index c507d8b80c9..f5bdf567b20 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember.ts @@ -11,7 +11,6 @@ verify.codeFix({ index: 0, newFileContent: `class C { foo: number; - method() { this.foo = 10; } diff --git a/tests/cases/fourslash/codeFixAddMissingMember2.ts b/tests/cases/fourslash/codeFixAddMissingMember2.ts index b19632dd104..a4b7ffb3bfe 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember2.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember2.ts @@ -11,7 +11,6 @@ verify.codeFix({ index: 1, newFileContent: `class C { [x: string]: number; - method() { this.foo = 10; } diff --git a/tests/cases/fourslash/codeFixAddMissingMember3.ts b/tests/cases/fourslash/codeFixAddMissingMember3.ts index 88ea2efef66..82512406985 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember3.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember3.ts @@ -11,7 +11,6 @@ verify.codeFix({ index: 0, newFileContent: `class C { static foo: number; - static method() { this.foo = 10; } diff --git a/tests/cases/fourslash/codeFixAddMissingMember_all.ts b/tests/cases/fourslash/codeFixAddMissingMember_all.ts index 0e7abb79cc2..5a2f8606f2d 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember_all.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember_all.ts @@ -17,7 +17,6 @@ verify.codeFixAll({ y(): any { throw new Error("Method not implemented."); } - method() { this.x = 0; this.y(); diff --git a/tests/cases/fourslash/codeFixAddMissingMember_all_js.ts b/tests/cases/fourslash/codeFixAddMissingMember_all_js.ts index 48455943af5..5e5a2895fdc 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember_all_js.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember_all_js.ts @@ -21,7 +21,6 @@ verify.codeFixAll({ y() { throw new Error("Method not implemented."); } - constructor() { this.x = undefined; } diff --git a/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts b/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts index 84b0ebd4414..60693a22fca 100644 --- a/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts +++ b/tests/cases/fourslash/codeFixUndeclaredInStaticMethod.ts @@ -17,7 +17,6 @@ verify.codeFix({ static m1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - static foo0() { this.m1(1,2,3); A.m2(1,2); @@ -35,11 +34,9 @@ verify.codeFix({ static m2(arg0: any, arg1: any): any { throw new Error("Method not implemented."); } - static m1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - static foo0() { this.m1(1,2,3); A.m2(1,2); @@ -55,15 +52,12 @@ verify.codeFix({ newFileContent: `class A { static prop1: number; - static m2(arg0: any, arg1: any): any { throw new Error("Method not implemented."); } - static m1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - static foo0() { this.m1(1,2,3); A.m2(1,2); @@ -80,15 +74,12 @@ verify.codeFix({ `class A { static prop1: number; static prop2: string; - static m2(arg0: any, arg1: any): any { throw new Error("Method not implemented."); } - static m1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - static foo0() { this.m1(1,2,3); A.m2(1,2); diff --git a/tests/cases/fourslash/codeFixUndeclaredMethod.ts b/tests/cases/fourslash/codeFixUndeclaredMethod.ts index b85e5fbfdfa..41e27dcf207 100644 --- a/tests/cases/fourslash/codeFixUndeclaredMethod.ts +++ b/tests/cases/fourslash/codeFixUndeclaredMethod.ts @@ -18,7 +18,6 @@ verify.codeFix({ foo1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - constructor() { this.foo1(1,2,3); // 7 type args @@ -37,11 +36,9 @@ verify.codeFix({ foo2(): any { throw new Error("Method not implemented."); } - foo1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - constructor() { this.foo1(1,2,3); // 7 type args @@ -60,15 +57,12 @@ verify.codeFix({ foo3(): any { throw new Error("Method not implemented."); } - foo2(): any { throw new Error("Method not implemented."); } - foo1(arg0: any, arg1: any, arg2: any): any { throw new Error("Method not implemented."); } - constructor() { this.foo1(1,2,3); // 7 type args diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts index bb2e20eaa8f..5206eada35d 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess16.ts @@ -16,7 +16,6 @@ edit.applyRefactor({ public set a(value: string) { this._a = value; } - constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts index 85d5c001490..71e058b7c83 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess17.ts @@ -16,7 +16,6 @@ edit.applyRefactor({ protected set a(value: string) { this._a = value; } - constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts index 4bc91af7ff5..f1203730b3c 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess18.ts @@ -16,7 +16,6 @@ edit.applyRefactor({ public set a(value: string) { this._a = value; } - constructor(private /*RENAME*/_a: string) { } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts index 68622150edc..ceec2721709 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess22.ts @@ -17,7 +17,6 @@ edit.applyRefactor({ public set a(value: string) { this._a = value; } - public a_1: number; constructor(private /*RENAME*/_a: string) { } }`, From ffa0ccba2a7ee2d0627f474436024c6f5f8868e8 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 7 May 2018 15:12:50 -0700 Subject: [PATCH 31/64] Project References Core support --- src/compiler/checker.ts | 17 +- src/compiler/commandLineParser.ts | 105 ++++++- src/compiler/core.ts | 4 + src/compiler/diagnosticMessages.json | 37 +++ src/compiler/emitter.ts | 85 ++++- src/compiler/factory.ts | 22 +- src/compiler/parser.ts | 8 +- src/compiler/program.ts | 294 +++++++++++++++++- src/compiler/transformer.ts | 4 +- src/compiler/transformers/declarations.ts | 6 +- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/es2016.ts | 2 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/es5.ts | 2 +- src/compiler/transformers/esnext.ts | 2 +- src/compiler/transformers/generators.ts | 2 +- src/compiler/transformers/jsx.ts | 2 +- src/compiler/transformers/module/es2015.ts | 2 +- src/compiler/transformers/module/module.ts | 2 +- src/compiler/transformers/module/system.ts | 2 +- src/compiler/transformers/ts.ts | 18 +- src/compiler/transformers/utilities.ts | 12 + src/compiler/tsc.ts | 19 +- src/compiler/types.ts | 77 ++++- src/compiler/utilities.ts | 1 + src/compiler/watch.ts | 42 --- src/harness/fakes.ts | 4 + .../convertCompilerOptionsFromJson.ts | 2 +- src/harness/unittests/projectReferences.ts | 291 +++++++++++++++++ src/server/client.ts | 5 + src/server/editorServices.ts | 7 +- src/server/project.ts | 15 +- src/server/protocol.ts | 1 + src/server/session.ts | 8 +- src/server/utilities.ts | 2 + src/services/documentRegistry.ts | 3 +- src/services/getEditsForFileRename.ts | 2 +- src/services/services.ts | 33 +- src/services/types.ts | 3 + .../reference/api/tsserverlibrary.d.ts | 147 ++++++--- tests/baselines/reference/api/typescript.d.ts | 141 ++++++--- .../reference/declarationMapsOutFile.js.map | 2 +- .../declarationMapsOutFile.sourcemap.txt | 11 +- .../reference/declarationMapsOutFile2.js.map | 2 +- .../declarationMapsOutFile2.sourcemap.txt | 11 +- .../declarationMapsWithSourceMap.js.map | 2 +- ...declarationMapsWithSourceMap.sourcemap.txt | 11 +- .../amd/FolderA/FolderB/fileB.d.ts | 4 + .../amd/FolderA/FolderB/fileB.js | 6 + .../amd/outdir/simple/fileC.d.ts | 2 + .../amd/outdir/simple/fileC.js | 5 + .../node/FolderA/FolderB/fileB.d.ts | 4 + .../node/FolderA/FolderB/fileB.js | 6 + .../node/outdir/simple/fileC.d.ts | 2 + .../node/outdir/simple/fileC.js | 5 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + 64 files changed, 1293 insertions(+), 224 deletions(-) create mode 100644 src/harness/unittests/projectReferences.ts create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.js create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.d.ts create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.js create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.js create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.d.ts create mode 100644 tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.js diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a34f073df3e..6751a122a2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2220,7 +2220,22 @@ namespace ts { } if (moduleNotFoundError) { - // report errors only if it was requested + // For relative paths, see if this was possibly a projectReference redirect + if (pathIsRelative(moduleReference)) { + const sourceFile = getSourceFileOfNode(location); + const redirects = sourceFile.redirectedReferences; + if (redirects) { + const normalizedTargetPath = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(sourceFile.fileName)); + for (const ext of [Extension.Ts, Extension.Tsx]) { + const probePath = normalizedTargetPath + ext; + if (redirects.indexOf(probePath) >= 0) { + error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, moduleReference, probePath); + return undefined; + } + } + } + } + if (resolutionDiagnostic) { error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 9710b0c1262..f648bddefe9 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -235,6 +235,13 @@ namespace ts { category: Diagnostics.Basic_Options, description: Diagnostics.Specify_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, }, + { + name: "composite", + type: "boolean", + isTSConfigOnly: true, + category: Diagnostics.Basic_Options, + description: Diagnostics.Enable_project_compilation, + }, { name: "removeComments", type: "boolean", @@ -814,12 +821,14 @@ namespace ts { export function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine { const options: CompilerOptions = {}; const fileNames: string[] = []; + const projectReferences: ProjectReference[] | undefined = undefined; const errors: Diagnostic[] = []; parseStrings(commandLine); return { options, fileNames, + projectReferences, errors }; @@ -933,6 +942,49 @@ namespace ts { return optionNameMap.get(optionName); } + + export type DiagnosticReporter = (diagnostic: Diagnostic) => void; + /** + * Reports config file diagnostics + */ + export interface ConfigFileDiagnosticsReporter { + /** + * Reports unrecoverable error when parsing config file + */ + onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; + } + + /** + * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors + */ + export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { + getCurrentDirectory(): string; + } + + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ + export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined { + let configFileText: string; + try { + configFileText = host.readFile(configFileName); + } + catch (e) { + const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); + host.onUnRecoverableConfigFileDiagnostic(error); + return undefined; + } + if (!configFileText) { + const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName); + host.onUnRecoverableConfigFileDiagnostic(error); + return undefined; + } + + const result = parseJsonText(configFileName, configFileText); + const cwd = host.getCurrentDirectory(); + return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd)); + } + /** * Read tsconfig.json file * @param fileName The path to the config file @@ -1008,6 +1060,14 @@ namespace ts { name: "extends", type: "string" }, + { + name: "references", + type: "list", + element: { + name: "references", + type: "object" + } + }, { name: "files", type: "list", @@ -1415,7 +1475,7 @@ namespace ts { for (let i = 0; i < nameColumn.length; i++) { const optionName = nameColumn[i]; const description = descriptionColumn[i]; - result.push(optionName && `${tab}${tab}${optionName}${ description && (makePadding(marginLength - optionName.length + 2) + description)}`); + result.push(optionName && `${tab}${tab}${optionName}${description && (makePadding(marginLength - optionName.length + 2) + description)}`); } if (fileNames.length) { result.push(`${tab}},`); @@ -1499,12 +1559,13 @@ namespace ts { const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors); const { raw } = parsedConfig; const options = extend(existingOptions, parsedConfig.options || {}); - options.configFilePath = configFileName; + options.configFilePath = configFileName && normalizeSlashes(configFileName); setConfigFileInOptions(options, sourceFile); - const { fileNames, wildcardDirectories, spec } = getFileNames(); + const { fileNames, wildcardDirectories, spec, projectReferences } = getFileNames(); return { options, fileNames, + projectReferences, typeAcquisition: parsedConfig.typeAcquisition || getDefaultTypeAcquisition(), raw, errors, @@ -1558,10 +1619,33 @@ namespace ts { } const result = matchFileNames(filesSpecs, includeSpecs, excludeSpecs, configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath, options, host, errors, extraFileExtensions, sourceFile); - if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0) { + if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0 && !hasProperty(raw, "references")) { errors.push(getErrorForNoInputFiles(result.spec, configFileName)); } + if (hasProperty(raw, "references") && !isNullOrUndefined(raw.references)) { + if (isArray(raw.references)) { + const references: ProjectReference[] = []; + for (const ref of raw.references) { + if (typeof ref.path !== "string") { + createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string"); + } + else { + references.push({ + path: getNormalizedAbsolutePath(ref.path, basePath), + originalPath: ref.path, + prepend: ref.prepend, + circular: ref.circular + }); + } + } + result.projectReferences = references; + } + else { + createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "references", "Array"); + } + } + return result; } @@ -1850,6 +1934,9 @@ namespace ts { const options = getDefaultCompilerOptions(configFileName); convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); + if (configFileName) { + options.configFilePath = normalizeSlashes(configFileName); + } return options; } @@ -2048,7 +2135,7 @@ namespace ts { // new entries in these paths. const wildcardDirectories = getWildcardDirectories(validatedIncludeSpecs, validatedExcludeSpecs, basePath, host.useCaseSensitiveFileNames); - const spec: ConfigFileSpecs = { filesSpecs, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories }; + const spec: ConfigFileSpecs = { filesSpecs, referencesSpecs: undefined, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories }; return getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions); } @@ -2119,8 +2206,16 @@ namespace ts { const literalFiles = arrayFrom(literalFileMap.values()); const wildcardFiles = arrayFrom(wildcardFileMap.values()); + const projectReferences = spec.referencesSpecs && spec.referencesSpecs.map((r): ProjectReference => { + return { + ...r, + path: getNormalizedAbsolutePath(r.path, basePath) + }; + }); + return { fileNames: literalFiles.concat(wildcardFiles), + projectReferences, wildcardDirectories, spec }; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c5e9a75b4ee..20c3562271c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1963,6 +1963,10 @@ namespace ts { : moduleKind === ModuleKind.System; } + export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean { + return !!(compilerOptions.declaration || compilerOptions.composite); + } + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict"; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c12e0a9931b..1e101ce6e76 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3552,6 +3552,43 @@ "code": 6197 }, + "Projects to reference": { + "category": "Message", + "code": 6300 + }, + "Enable project compilation": { + "category": "Message", + "code": 6302 + }, + "Project references may not form a circular graph. Cycle detected: {0}": { + "category": "Error", + "code": 6202 + }, + "Composite projects may not disable declaration emit.": { + "category": "Error", + "code": 6304 + }, + "Output file '{0}' has not been built from source file '{1}'.": { + "category": "Error", + "code": 6305 + }, + "Referenced project '{0}' must have setting \"composite\": true.": { + "category": "Error", + "code": 6306 + }, + "File '{0}' is not in project file list. Projects must list all files or use an 'include' pattern.": { + "category": "Error", + "code": 6307 + }, + "Cannot prepend project '{0}' because it does not have 'outFile' set": { + "category": "Error", + "code": 6308 + }, + "Output file '{0}' from project '{1}' does not exist": { + "category": "Error", + "code": 6309 + }, + "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0786e849495..20bc916faf4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,4 +1,5 @@ namespace ts { + const infoExtension = ".tsbundleinfo"; const brackets = createBracketsMap(); /*@internal*/ @@ -15,12 +16,11 @@ namespace ts { host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) => T, sourceFilesOrTargetSourceFile?: ReadonlyArray | SourceFile, emitOnlyDtsFiles?: boolean) { - const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile); const options = host.getCompilerOptions(); if (options.outFile || options.out) { if (sourceFiles.length) { - const bundle = createBundle(sourceFiles); + const bundle = createBundle(sourceFiles, host.getPrependNodes()); const result = action(getOutputPathsFor(bundle, host, emitOnlyDtsFiles), bundle); if (result) { return result; @@ -45,7 +45,8 @@ namespace ts { const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = (forceDtsPaths || options.declaration) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined; const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; - return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; + const bundleInfoPath = options.references && jsFilePath && (removeFileExtension(jsFilePath) + infoExtension); + return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }; } else { const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); @@ -54,7 +55,7 @@ namespace ts { const isJs = isSourceFileJavaScript(sourceFile); const declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; - return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; + return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath: undefined }; } } @@ -62,6 +63,13 @@ namespace ts { return (options.sourceMap && !options.inlineSourceMap) ? jsFilePath + ".map" : undefined; } + function createDefaultBundleInfo(): BundleInfo { + return { + originalOffset: -1, + totalLength: -1 + }; + } + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve @@ -87,7 +95,7 @@ namespace ts { /*@internal*/ // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature - export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[]): EmitResult { + export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[]): EmitResult { const compilerOptions = host.getCompilerOptions(); const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; @@ -103,6 +111,7 @@ namespace ts { // Explicitly do not passthru either `inline` option }); + let bundleInfo: BundleInfo = createDefaultBundleInfo(); let emitSkipped = false; // Emit each output file @@ -118,8 +127,8 @@ namespace ts { sourceMaps: sourceMapDataList }; - function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { - emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath); + function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { + emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfoPath); emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath); if (!emitSkipped && emittedFilesList) { @@ -132,11 +141,13 @@ namespace ts { if (declarationFilePath) { emittedFilesList.push(declarationFilePath); } + if (bundleInfoPath) { + emittedFilesList.push(bundleInfoPath); + } } } - function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string) { - const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; + function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string, bundleInfoPath: string | undefined) { // Make sure not to write js file and source map file if any of them cannot be written if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) { emitSkipped = true; @@ -146,7 +157,7 @@ namespace ts { return; } // Transform the source files - const transform = transformNodes(resolver, host, compilerOptions, sourceFiles, transformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false); // Create a printer to print the nodes const printer = createPrinter({ ...compilerOptions, noEmitHelpers: compilerOptions.noEmitHelpers } as PrinterOptions, { @@ -166,7 +177,8 @@ namespace ts { onSetSourceFile: setSourceFile, }); - printSourceFileOrBundle(jsFilePath, sourceMapFilePath, isSourceFile(sourceFileOrBundle) ? transform.transformed[0] : createBundle(transform.transformed), printer, sourceMap); + Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); + printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], bundleInfoPath, printer, sourceMap); // Clean up emit nodes on parse tree transform.dispose(); @@ -179,7 +191,7 @@ namespace ts { const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; // Setup and perform the transformation to retrieve declarations from the input files const nonJsFiles = filter(sourceFiles, isSourceFileNotJavaScript); - const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles)] : nonJsFiles; + const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, [transformDeclarations], /*allowDtsFiles*/ false); if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics) { @@ -203,19 +215,20 @@ namespace ts { const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || emitOnlyDtsFiles) { - printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], declarationPrinter, declarationSourceMap); + Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); + printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, declarationSourceMap); } declarationTransform.dispose(); } - function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, mapRecorder: SourceMapWriter) { + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapRecorder: SourceMapWriter) { const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList); if (bundle) { - printer.writeBundle(bundle, writer); + printer.writeBundle(bundle, writer, bundleInfo); } else { printer.writeFile(sourceFile, writer); @@ -236,9 +249,17 @@ namespace ts { // Write the output file writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles); + // Write bundled offset information if applicable + if (bundleInfoPath) { + bundleInfo.totalLength = writer.getTextPos(); + writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false); + } + // Reset state mapRecorder.reset(); writer.clear(); + + bundleInfo = createDefaultBundleInfo(); } function setSourceFile(node: SourceFile) { @@ -335,6 +356,7 @@ namespace ts { switch (node.kind) { case SyntaxKind.SourceFile: return printFile(node); case SyntaxKind.Bundle: return printBundle(node); + case SyntaxKind.UnparsedSource: return printUnparsedSource(node); } writeNode(hint, node, sourceFile, beginPrint()); return endPrint(); @@ -355,6 +377,11 @@ namespace ts { return endPrint(); } + function printUnparsedSource(unparsed: UnparsedSource): string { + writeUnparsedSource(unparsed, beginPrint()); + return endPrint(); + } + /** * If `sourceFile` is `undefined`, `node` must be a synthesized `TypeNode`. */ @@ -379,7 +406,7 @@ namespace ts { writer = previousWriter; } - function writeBundle(bundle: Bundle, output: EmitTextWriter) { + function writeBundle(bundle: Bundle, output: EmitTextWriter, bundleInfo?: BundleInfo) { isOwnFileEmit = false; const previousWriter = writer; setWriter(output); @@ -387,6 +414,16 @@ namespace ts { emitPrologueDirectivesIfNeeded(bundle); emitHelpers(bundle); emitSyntheticTripleSlashReferencesIfNeeded(bundle); + + for (const prepend of bundle.prepends) { + print(EmitHint.Unspecified, prepend, /*sourceFile*/ undefined); + writeLine(); + } + + if (bundleInfo) { + bundleInfo.originalOffset = writer.getTextPos(); + } + for (const sourceFile of bundle.sourceFiles) { print(EmitHint.SourceFile, sourceFile, sourceFile); } @@ -394,6 +431,14 @@ namespace ts { writer = previousWriter; } + function writeUnparsedSource(unparsed: UnparsedSource, output: EmitTextWriter) { + const previousWriter = writer; + setWriter(output); + print(EmitHint.Unspecified, unparsed, /*sourceFile*/ undefined); + reset(); + writer = previousWriter; + } + function writeFile(sourceFile: SourceFile, output: EmitTextWriter) { isOwnFileEmit = true; const previousWriter = writer; @@ -534,6 +579,9 @@ namespace ts { case SyntaxKind.TemplateTail: return emitLiteral(node); + case SyntaxKind.UnparsedSource: + return emitUnparsedSource(node); + // Identifiers case SyntaxKind.Identifier: return emitIdentifier(node); @@ -978,6 +1026,11 @@ namespace ts { } } + // SyntaxKind.UnparsedSource + function emitUnparsedSource(unparsed: UnparsedSource) { + write(unparsed.text); + } + // // Identifiers // diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 735de930ae9..e8916ac62e5 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2562,15 +2562,29 @@ namespace ts { : node; } - export function createBundle(sourceFiles: ReadonlyArray) { + export function createBundle(sourceFiles: ReadonlyArray, prepends: ReadonlyArray = emptyArray) { const node = createNode(SyntaxKind.Bundle); + node.prepends = prepends; node.sourceFiles = sourceFiles; return node; } - export function updateBundle(node: Bundle, sourceFiles: ReadonlyArray) { - if (node.sourceFiles !== sourceFiles) { - return createBundle(sourceFiles); + export function createUnparsedSourceFile(text: string): UnparsedSource { + const node = createNode(SyntaxKind.UnparsedSource); + node.text = text; + return node; + } + + export function createInputFiles(javascript: string, declaration: string): InputFiles { + const node = createNode(SyntaxKind.InputFiles); + node.javascriptText = javascript; + node.declarationText = declaration; + return node; + } + + export function updateBundle(node: Bundle, sourceFiles: ReadonlyArray, prepends: ReadonlyArray = emptyArray) { + if (node.sourceFiles !== sourceFiles || node.prepends !== prepends) { + return createBundle(sourceFiles, prepends); } return node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b84c8ca004f..9db66792a7a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -503,7 +503,13 @@ namespace ts { export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { performance.mark("beforeParse"); - const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); + let result: SourceFile; + if (languageVersion === ScriptTarget.JSON) { + result = Parser.parseJsonText(fileName, sourceText); + } + else { + result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); + } performance.mark("afterParse"); performance.measure("Parse", "beforeParse", "afterParse"); return result; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 4f052581c20..3da1da2b018 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -188,7 +188,8 @@ namespace ts { directoryExists: directoryName => sys.directoryExists(directoryName), getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "", getDirectories: (path: string) => sys.getDirectories(path), - realpath + realpath, + readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth) }; } @@ -328,14 +329,14 @@ namespace ts { output += formatColorAndReset(relativeFileName, ForegroundColorEscapeSequences.Cyan); output += ":"; - output += formatColorAndReset(`${ firstLine + 1 }`, ForegroundColorEscapeSequences.Yellow); + output += formatColorAndReset(`${firstLine + 1}`, ForegroundColorEscapeSequences.Yellow); output += ":"; - output += formatColorAndReset(`${ firstLineChar + 1 }`, ForegroundColorEscapeSequences.Yellow); + output += formatColorAndReset(`${firstLineChar + 1}`, ForegroundColorEscapeSequences.Yellow); output += " - "; } output += formatColorAndReset(diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category)); - output += formatColorAndReset(` TS${ diagnostic.code }: `, ForegroundColorEscapeSequences.Grey); + output += formatColorAndReset(` TS${diagnostic.code}: `, ForegroundColorEscapeSequences.Grey); output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()); if (diagnostic.file) { @@ -477,6 +478,16 @@ namespace ts { ); } + function createCreateProgramOptions(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): CreateProgramOptions { + return { + rootNames, + options, + host, + oldProgram, + configFileParsingDiagnostics + }; + } + /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -491,7 +502,13 @@ namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ - export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program { + export function createProgram(createProgramOptions: CreateProgramOptions): Program; + export function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + export function createProgram(rootNamesOrOptions: ReadonlyArray | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray): Program { + const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; + const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions; + let { host, oldProgram } = createProgramOptions; + let program: Program; let files: SourceFile[] = []; let commonSourceDirectory: string; @@ -526,6 +543,7 @@ namespace ts { performance.mark("beforeProgram"); host = host || createCompilerHost(options); + const configParsingHost = parseConfigHostFromCompilerHost(host); let skipDefaultLib = options.noLib; const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); @@ -537,6 +555,7 @@ namespace ts { // Map storing if there is emit blocking diagnostics for given input const hasEmitBlockingDiagnostics = createMap(); let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression; + let _referencesArrayLiteralSyntax: ArrayLiteralExpression; let moduleResolutionCache: ModuleResolutionCache; let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[]) => ResolvedModuleFull[]; @@ -581,6 +600,23 @@ namespace ts { // used to track cases when two file names differ only in casing const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap() : undefined; + // A parallel array to projectReferences storing the results of reading in the referenced tsconfig files + const resolvedProjectReferences: (ResolvedProjectReference | undefined)[] | undefined = projectReferences ? [] : undefined; + const projectReferenceRedirects: Map = createMap(); + if (projectReferences) { + for (const ref of projectReferences) { + const parsedRef = parseProjectReferenceConfigFile(ref); + resolvedProjectReferences.push(parsedRef); + if (parsedRef) { + if (parsedRef.commandLine.options.outFile) { + const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts"); + processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*packageId*/ undefined); + } + addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects); + } + } + } + const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options); const structuralIsReused = tryReuseStructureFromOldProgram(); if (structuralIsReused !== StructureIsReused.Completely) { @@ -669,6 +705,7 @@ namespace ts { isEmittedFile, getConfigFileParsingDiagnostics, getResolvedModuleWithFailedLookupLocationsFromCache, + getProjectReferences }; verifyCompilerOptions(); @@ -689,12 +726,18 @@ namespace ts { if (commonSourceDirectory === undefined) { const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary)); if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) { - // If a rootDir is specified and is valid use it as the commonSourceDirectory + // If a rootDir is specified use it as the commonSourceDirectory commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory); } + else if (options.composite) { + // Project compilations never infer their root from the input source paths + commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath)); + checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory); + } else { commonSourceDirectory = computeCommonSourceDirectory(emittedFiles); } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) { // Make sure directory path ends with directory separator so this string can directly // used to replace with "" to get the relative path of the source file and the relative path doesn't @@ -896,6 +939,35 @@ namespace ts { return oldProgram.structureIsReused = StructureIsReused.Not; } + // Check if any referenced project tsconfig files are different + const oldRefs = oldProgram.getProjectReferences(); + if (projectReferences) { + if (!oldRefs) { + return oldProgram.structureIsReused = StructureIsReused.Not; + } + for (let i = 0; i < projectReferences.length; i++) { + const oldRef = oldRefs[i]; + if (oldRef) { + const newRef = parseProjectReferenceConfigFile(projectReferences[i]); + if (!newRef || newRef.sourceFile !== oldRef.sourceFile) { + // Resolved project reference has gone missing or changed + return oldProgram.structureIsReused = StructureIsReused.Not; + } + } + else { + // A previously-unresolved reference may be resolved now + if (parseProjectReferenceConfigFile(projectReferences[i]) !== undefined) { + return oldProgram.structureIsReused = StructureIsReused.Not; + } + } + } + } + else { + if (oldRefs) { + return oldProgram.structureIsReused = StructureIsReused.Not; + } + } + // check if program source files has changed in the way that can affect structure of the program const newSourceFiles: SourceFile[] = []; const filePaths: Path[] = []; @@ -1083,6 +1155,7 @@ namespace ts { function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { return { + getPrependNodes, getCanonicalFileName, getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, @@ -1098,6 +1171,35 @@ namespace ts { }; } + function getProjectReferences() { + if (!resolvedProjectReferences) return; + + return resolvedProjectReferences; + } + + function getPrependNodes(): InputFiles[] { + if (!projectReferences) { + return emptyArray; + } + + const nodes: InputFiles[] = []; + for (let i = 0; i < projectReferences.length; i++) { + const ref = projectReferences[i]; + const resolvedRefOpts = resolvedProjectReferences[i].commandLine; + if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { + // Upstream project didn't have outFile set -- skip (error will have been issued earlier) + if (!resolvedRefOpts.options.outFile) continue; + + const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts"); + const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`; + const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`; + const node = createInputFiles(js, dts); + nodes.push(node); + } + } + return nodes; + } + function isSourceFileFromExternalLibrary(file: SourceFile): boolean { return sourceFilesFoundSearchingNodeModules.get(file.path); } @@ -1723,7 +1825,13 @@ namespace ts { const sourceFile = getSourceFile(fileName); if (fail) { if (!sourceFile) { - fail(Diagnostics.File_0_not_found, fileName); + const redirect = getProjectReferenceRedirect(fileName); + if (redirect) { + fail(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, fileName); + } + else { + fail(Diagnostics.File_0_not_found, fileName); + } } else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { fail(Diagnostics.A_file_cannot_have_a_reference_to_itself); @@ -1819,6 +1927,21 @@ namespace ts { return file; } + let redirectedPath: string | undefined; + if (refFile) { + const redirect = getProjectReferenceRedirect(fileName); + if (redirect) { + ((refFile.redirectedReferences || (refFile.redirectedReferences = [])) as string[]).push(fileName); + fileName = redirect; + // Once we start redirecting to a file, we can potentially come back to it + // via a back-reference from another file in the .d.ts folder. If that happens we'll + // end up trying to add it to the program *again* because we were tracking it via its + // original (un-redirected) name. So we have to map both the original path and the redirected path + // to the source file we're about to find/create + redirectedPath = toPath(redirect); + } + } + // We haven't looked for this file, do so now and cache result const file = host.getSourceFile(fileName, options.target, hostErrorMessage => { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { @@ -1851,6 +1974,10 @@ namespace ts { } filesByName.set(path, file); + if (redirectedPath) { + filesByName.set(redirectedPath, file); + } + if (file) { sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); file.path = path; @@ -1888,6 +2015,23 @@ namespace ts { return file; } + function getProjectReferenceRedirect(fileName: string): string | undefined { + const path = toPath(fileName); + // If this file is produced by a referenced project, we need to rewrite it to + // look in the output folder of the referenced project rather than the input + const normalized = getNormalizedAbsolutePath(fileName, path); + let result: string | undefined; + projectReferenceRedirects.forEach((v, k) => { + if (result !== undefined) { + return undefined; + } + if (normalized.indexOf(k) === 0) { + result = changeExtension(fileName.replace(k, v), ".d.ts"); + } + }); + return result; + } + function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) { forEach(file.referencedFiles, ref => { const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); @@ -1898,6 +2042,10 @@ namespace ts { function processTypeReferenceDirectives(file: SourceFile) { // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. const typeDirectives = map(file.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase()); + if (!typeDirectives) { + return; + } + const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName); for (let i = 0; i < typeDirectives.length; i++) { @@ -2061,6 +2209,31 @@ namespace ts { return allFilesBelongToPath; } + function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined { + // The actual filename (i.e. add "/tsconfig.json" if necessary) + const refPath = resolveProjectReferencePath(host, ref); + // An absolute path pointing to the containing directory of the config file + const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory()); + const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile; + if (sourceFile === undefined) { + return undefined; + } + + const commandLine = parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); + return { commandLine, sourceFile }; + } + + function addProjectReferenceRedirects(referencedProject: ParsedCommandLine, target: Map) { + const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath)); + target.set(rootDir, getDeclarationOutputDirectory(referencedProject)); + } + + function getDeclarationOutputDirectory(proj: ParsedCommandLine) { + return proj.options.declarationDir || + proj.options.outDir || + getDirectoryPath(proj.options.configFilePath); + } + function verifyCompilerOptions() { if (options.strictPropertyInitialization && !options.strictNullChecks) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks"); @@ -2097,6 +2270,47 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option, "paths"); } + if (options.composite) { + if (options.declaration === false) { + createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration"); + } + } + + if (projectReferences) { + for (let i = 0; i < projectReferences.length; i++) { + const ref = projectReferences[i]; + const resolvedRefOpts = resolvedProjectReferences[i] && resolvedProjectReferences[i].commandLine.options; + if (resolvedRefOpts === undefined) { + createDiagnosticForReference(i, Diagnostics.File_0_does_not_exist, ref.path); + continue; + } + if (!resolvedRefOpts.composite) { + createDiagnosticForReference(i, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path); + } + if (ref.prepend) { + if (resolvedRefOpts.outFile) { + if (!host.fileExists(resolvedRefOpts.outFile)) { + createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, resolvedRefOpts.outFile, ref.path); + } + } + else { + createDiagnosticForReference(i, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path); + } + } + } + } + + // List of collected files is complete; validate exhautiveness if this is a project with a file list + if (options.composite && rootNames.length < files.length) { + const normalizedRootNames = rootNames.map(r => normalizePath(r).toLowerCase()); + const sourceFiles = files.filter(f => !f.isDeclarationFile).map(f => normalizePath(f.path).toLowerCase()); + for (const file of sourceFiles) { + if (normalizedRootNames.every(r => r !== file)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern, file)); + } + } + } + if (options.paths) { for (const key in options.paths) { if (!hasProperty(options.paths, key)) { @@ -2332,12 +2546,16 @@ namespace ts { } } - function getOptionPathsSyntax() { + function getOptionsSyntaxByName(name: string): object | undefined { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); if (compilerOptionsObjectLiteralSyntax) { - return getPropertyAssignment(compilerOptionsObjectLiteralSyntax, "paths"); + return getPropertyAssignment(compilerOptionsObjectLiteralSyntax, name); } - return emptyArray; + return undefined; + } + + function getOptionPathsSyntax(): PropertyAssignment[] { + return getOptionsSyntaxByName("paths") as PropertyAssignment[] || emptyArray; } function createDiagnosticForOptionName(message: DiagnosticMessage, option1: string, option2?: string, option3?: string) { @@ -2348,6 +2566,16 @@ namespace ts { createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0); } + function createDiagnosticForReference(index: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number) { + const referencesSyntax = getProjectReferencesSyntax(); + if (referencesSyntax) { + if (createOptionDiagnosticInArrayLiteralSyntax(referencesSyntax, index, message, arg0, arg1)) { + return; + } + } + programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1)); + } + function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || @@ -2358,6 +2586,22 @@ namespace ts { } } + function getProjectReferencesSyntax(): ArrayLiteralExpression | null { + if (_referencesArrayLiteralSyntax === undefined) { + _referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword + if (options.configFile) { + const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile); + for (const prop of getPropertyAssignment(jsonObjectLiteral, "references")) { + if (isArrayLiteralExpression(prop.initializer)) { + _referencesArrayLiteralSyntax = prop.initializer; + break; + } + } + } + } + return _referencesArrayLiteralSyntax; + } + function getCompilerOptionsObjectLiteralSyntax() { if (_compilerOptionsObjectLiteralSyntax === undefined) { _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword @@ -2382,6 +2626,14 @@ namespace ts { return !!props.length; } + function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean { + if (arrayLiteral.elements.length <= index) { + // Out-of-bounds + return false; + } + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2)); + } + function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) { hasEmitBlockingDiagnostics.set(toPath(emitFileName), true); programDiagnostics.add(diag); @@ -2423,6 +2675,28 @@ namespace ts { } } + /* @internal */ + export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost { + return { + fileExists: f => host.fileExists(f), + readDirectory: (root, extensions, includes, depth?) => host.readDirectory ? host.readDirectory(root, extensions, includes, depth) : [], + readFile: f => host.readFile(f), + useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(), + getCurrentDirectory: () => host.getCurrentDirectory(), + onUnRecoverableConfigFileDiagnostic: () => undefined + }; + } + + /** + * Returns the target config filename of a project reference + */ + function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined { + if (!host.fileExists(ref.path)) { + return combinePaths(ref.path, "tsconfig.json"); + } + return ref.path; + } + /* @internal */ /** * Returns a DiagnosticMessage if we won't include a resolved module due to its extension. diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 8cadba453d8..16a6912757f 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -1,6 +1,6 @@ /* @internal */ namespace ts { - function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory { + function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory { switch (moduleKind) { case ModuleKind.ESNext: case ModuleKind.ES2015: @@ -28,7 +28,7 @@ namespace ts { const jsx = compilerOptions.jsx; const languageVersion = getEmitScriptTarget(compilerOptions); const moduleKind = getEmitModuleKind(compilerOptions); - const transformers: TransformerFactory[] = []; + const transformers: TransformerFactory[] = []; addRange(transformers, customTransformers && customTransformers.before); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 67e4fa31cb2..0a7cf397ddd 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -163,7 +163,11 @@ namespace ts { const updated = visitNodes(sourceFile.statements, visitDeclarationStatements); return updateSourceFileNode(sourceFile, filterCandidateImports(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false); } - )); + ), mapDefined(node.prepends, prepend => { + if (prepend.kind === SyntaxKind.InputFiles) { + return createUnparsedSourceFile(prepend.declarationText); + } + })); bundle.syntheticFileReferences = []; bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib; diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 0a607494bb5..76a7219b758 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -295,7 +295,7 @@ namespace ts { */ let enabledSubstitutions: ES2015SubstitutionFlags; - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 22b2f11b612..93b5d45714f 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -3,7 +3,7 @@ namespace ts { export function transformES2016(context: TransformationContext) { const { hoistVariableDeclaration } = context; - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 6689f83ed5b..c61809b64e0 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -40,7 +40,7 @@ namespace ts { context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 92ecce6a15c..bace315e953 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -24,7 +24,7 @@ namespace ts { context.onSubstituteNode = onSubstituteNode; context.enableSubstitution(SyntaxKind.PropertyAccessExpression); context.enableSubstitution(SyntaxKind.PropertyAssignment); - return transformSourceFile; + return chainBundle(transformSourceFile); /** * Transforms an ES5 source file to ES3. diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 68861a5bb43..d2e01b4fbbf 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -26,7 +26,7 @@ namespace ts { let enclosingFunctionFlags: FunctionFlags; let enclosingSuperContainerFlags: NodeCheckFlags = 0; - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 15f0d2d0f81..a1d610280c0 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -289,7 +289,7 @@ namespace ts { let currentExceptionBlock: ExceptionBlock; // The current exception block. let withBlockStack: WithBlock[]; // A stack containing `with` blocks. - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) { diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 4acdf63b275..48d3bee42d6 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -4,7 +4,7 @@ namespace ts { const compilerOptions = context.getCompilerOptions(); let currentSourceFile: SourceFile; - return transformSourceFile; + return chainBundle(transformSourceFile); /** * Transform JSX-specific syntax in a SourceFile. diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index a3315852632..070980df5de 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -10,7 +10,7 @@ namespace ts { context.enableSubstitution(SyntaxKind.Identifier); let currentSourceFile: SourceFile; - return transformSourceFile; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile) { diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index d87712d451d..503d662ad58 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -45,7 +45,7 @@ namespace ts { let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored. let needUMDDynamicImportHelper: boolean; - return transformSourceFile; + return chainBundle(transformSourceFile); /** * Transforms the module aspects of a SourceFile. diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 5cde69e2ef6..047b552415d 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -39,7 +39,7 @@ namespace ts { let enclosingBlockScopedContainer: Node; let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored. - return transformSourceFile; + return chainBundle(transformSourceFile); /** * Transforms the module aspects of a SourceFile. diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 7c561e7d696..862b79dbf24 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -88,7 +88,23 @@ namespace ts { */ let pendingExpressions: Expression[] | undefined; - return transformSourceFile; + return transformSourceFileOrBundle; + + function transformSourceFileOrBundle(node: SourceFile | Bundle) { + if (node.kind === SyntaxKind.Bundle) { + return transformBundle(node); + } + return transformSourceFile(node); + } + + function transformBundle(node: Bundle) { + return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => { + if (prepend.kind === SyntaxKind.InputFiles) { + return createUnparsedSourceFile(prepend.javascriptText); + } + return prepend; + })); + } /** * Transform TypeScript-specific syntax in a SourceFile. diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 13d2dff895a..f8a6a6a2795 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -25,6 +25,18 @@ namespace ts { return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default; } + export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle { + return transformSourceFileOrBundle; + + function transformSourceFileOrBundle(node: SourceFile | Bundle) { + return node.kind === SyntaxKind.SourceFile ? transformSourceFile(node) : transformBundle(node); + } + + function transformBundle(node: Bundle) { + return createBundle(map(node.sourceFiles, transformSourceFile), node.prepends); + } + } + export function getImportNeedsImportStarHelper(node: ImportDeclaration) { if (!!getNamespaceDeclarationNode(node)) { return true; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index e45a95f7989..7617fc62cb6 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -120,7 +120,7 @@ namespace ts { createWatchOfConfigFile(configParseResult, commandLineOptions); } else { - performCompilation(configParseResult.fileNames, configParseResult.options, getConfigFileParsingDiagnostics(configParseResult)); + performCompilation(configParseResult.fileNames, configParseResult.projectReferences, configParseResult.options, getConfigFileParsingDiagnostics(configParseResult)); } } else { @@ -130,7 +130,7 @@ namespace ts { createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions); } else { - performCompilation(commandLine.fileNames, commandLineOptions); + performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions); } } } @@ -142,11 +142,18 @@ namespace ts { } } - function performCompilation(rootFileNames: string[], compilerOptions: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray) { - const compilerHost = createCompilerHost(compilerOptions); - enableStatistics(compilerOptions); + function performCompilation(rootNames: string[], projectReferences: ReadonlyArray | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray) { + const host = createCompilerHost(options); + enableStatistics(options); - const program = createProgram(rootFileNames, compilerOptions, compilerHost, /*oldProgram*/ undefined, configFileParsingDiagnostics); + const programOptions: CreateProgramOptions = { + rootNames, + options, + projectReferences, + host, + configFileParsingDiagnostics + }; + const program = createProgram(programOptions); const exitStatus = emitFilesAndReportErrors(program, reportDiagnostic, s => sys.write(s + sys.newLine)); reportStatistics(program); return sys.exit(exitStatus); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4f48fe96a87..593e13a131f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -397,6 +397,8 @@ namespace ts { // Top-level nodes SourceFile, Bundle, + UnparsedSource, + InputFiles, // JSDoc nodes JSDocTypeExpression, @@ -2601,6 +2603,12 @@ namespace ts { /* @internal */ resolvedModules: Map; /* @internal */ resolvedTypeReferenceDirectiveNames: Map; /* @internal */ imports: ReadonlyArray; + /** + * When a file's references are redirected due to project reference directives, + * the original names of the references are stored in this array + */ + /* @internal*/ + redirectedReferences?: ReadonlyArray; // Identifier only if `declare global` /* @internal */ moduleAugmentations: ReadonlyArray; /* @internal */ patternAmbientModules?: PatternAmbientModule[]; @@ -2614,12 +2622,24 @@ namespace ts { export interface Bundle extends Node { kind: SyntaxKind.Bundle; + prepends: ReadonlyArray; sourceFiles: ReadonlyArray; /* @internal */ syntheticFileReferences?: ReadonlyArray; /* @internal */ syntheticTypeReferences?: ReadonlyArray; /* @internal */ hasNoDefaultLib?: boolean; } + export interface InputFiles extends Node { + kind: SyntaxKind.InputFiles; + javascriptText: string; + declarationText: string; + } + + export interface UnparsedSource extends Node { + kind: SyntaxKind.UnparsedSource; + text: string; + } + export interface JsonSourceFile extends SourceFile { statements: NodeArray; } @@ -2751,6 +2771,13 @@ namespace ts { /* @internal */ isEmittedFile(file: string): boolean; /* @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; + + getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + } + + export interface ResolvedProjectReference { + commandLine: ParsedCommandLine; + sourceFile: SourceFile; } /* @internal */ @@ -4175,7 +4202,18 @@ namespace ts { name: string; } - export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + export interface ProjectReference { + /** A normalized path on disk */ + path: string; + /** The path as the user originally wrote it */ + originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ + prepend?: boolean; + /** True if it is intended that this reference form a circularity */ + circular?: boolean; + } + + export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; export interface CompilerOptions { /*@internal*/ all?: boolean; @@ -4247,6 +4285,7 @@ namespace ts { /* @internal */ pretty?: boolean; reactNamespace?: string; jsxFactory?: string; + composite?: boolean; removeComments?: boolean; rootDir?: string; rootDirs?: string[]; @@ -4340,12 +4379,13 @@ namespace ts { ES2017 = 4, ES2018 = 5, ESNext = 6, + JSON = 100, Latest = ESNext, } export const enum LanguageVariant { Standard, - JSX, + JSX } /** Either a parsed command line or a parsed tsconfig.json */ @@ -4353,6 +4393,7 @@ namespace ts { options: CompilerOptions; typeAcquisition?: TypeAcquisition; fileNames: string[]; + projectReferences?: ReadonlyArray; raw?: any; errors: Diagnostic[]; wildcardDirectories?: MapLike; @@ -4368,6 +4409,7 @@ namespace ts { /* @internal */ export interface ConfigFileSpecs { filesSpecs: ReadonlyArray; + referencesSpecs: ReadonlyArray | undefined; /** * Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching */ @@ -4383,10 +4425,20 @@ namespace ts { export interface ExpandResult { fileNames: string[]; + projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; /* @internal */ spec: ConfigFileSpecs; } + export interface CreateProgramOptions { + rootNames: ReadonlyArray; + options: CompilerOptions; + projectReferences?: ReadonlyArray; + host?: CompilerHost; + oldProgram?: Program; + configFileParsingDiagnostics?: ReadonlyArray; + } + /* @internal */ export interface CommandLineOptionBase { name: string; @@ -4673,6 +4725,7 @@ namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; + readDirectory?(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; /* * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of @@ -4911,6 +4964,8 @@ namespace ts { isEmitBlocked(emitFileName: string): boolean; + getPrependNodes(): ReadonlyArray; + writeFile: WriteFileCallback; } @@ -5062,7 +5117,23 @@ namespace ts { /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; /*@internal*/ writeList(format: ListFormat, list: NodeArray, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void; /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; - /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void; + /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, info?: BundleInfo): void; + } + + /** + * When a bundle contains prepended content, we store a file on disk indicating where the non-prepended + * content of that file starts. On a subsequent build where there are no upstream .d.ts changes, we + * read the bundle info file and the original .js file to quickly re-use portion of the file + * that didn't originate in prepended content. + */ + /* @internal */ + export interface BundleInfo { + // The offset (in characters, i.e. suitable for .substr) at which the + // non-prepended portion of the emitted file starts. + originalOffset: number; + // The total length of this bundle. Used to ensure we're pulling from + // the same source as we originally wrote. + totalLength: number; } export interface PrintHandlers { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 22eb3d2c97c..7afc862bba4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2915,6 +2915,7 @@ namespace ts { sourceMapFilePath: string | undefined; declarationFilePath: string | undefined; declarationMapPath: string | undefined; + bundleInfoPath: string | undefined; } /** diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 6b3adfcf3a4..3c5646cc48b 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -86,13 +86,6 @@ namespace ts { }; } - /** - * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors - */ - export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { - getCurrentDirectory(): string; - } - /** Parses config file using System interface */ export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, system: System, reportDiagnostic: DiagnosticReporter) { const host: ParseConfigFileHost = system; @@ -102,30 +95,6 @@ namespace ts { return result; } - /** - * Reads the config file, reports errors if any and exits if the config file cannot be found - */ - export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined { - let configFileText: string; - try { - configFileText = host.readFile(configFileName); - } - catch (e) { - const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); - host.onUnRecoverableConfigFileDiagnostic(error); - return undefined; - } - if (!configFileText) { - const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName); - host.onUnRecoverableConfigFileDiagnostic(error); - return undefined; - } - - const result = parseJsonText(configFileName, configFileText); - const cwd = host.getCurrentDirectory(); - return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd)); - } - /** * Program structure needed to emit the files and report diagnostics */ @@ -297,7 +266,6 @@ namespace ts { } namespace ts { - export type DiagnosticReporter = (diagnostic: Diagnostic) => void; export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ export type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; @@ -382,16 +350,6 @@ namespace ts { options: CompilerOptions; } - /** - * Reports config file diagnostics - */ - export interface ConfigFileDiagnosticsReporter { - /** - * Reports unrecoverable error when parsing config file - */ - onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; - } - /** * Host to create watch with config file */ diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index c6d955e8215..3e450f90d57 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -256,6 +256,10 @@ namespace fakes { return this.sys.getDirectories(path); } + public readDirectory(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[] { + return this.sys.readDirectory(path, extensions, exclude, include, depth); + } + public readFile(path: string): string | undefined { return this.sys.readFile(path); } diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index 84225a364cb..c120bfae8f9 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -14,7 +14,7 @@ namespace ts { const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName); const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); - const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions); + const expectedCompilerOptions = JSON.stringify({ ...expectedResult.compilerOptions, configFilePath: configFileName }); assert.equal(parsedCompilerOptions, expectedCompilerOptions); const expectedErrors = expectedResult.errors; diff --git a/src/harness/unittests/projectReferences.ts b/src/harness/unittests/projectReferences.ts new file mode 100644 index 00000000000..76ddd5fc29e --- /dev/null +++ b/src/harness/unittests/projectReferences.ts @@ -0,0 +1,291 @@ +/// +/// + +namespace ts { + interface TestProjectSpecification { + configFileName?: string; + references?: ReadonlyArray; + files: { [fileName: string]: string }; + outputFiles?: { [fileName: string]: string }; + config?: object; + options?: Partial; + } + interface TestSpecification { + [path: string]: TestProjectSpecification; + } + + function assertHasError(message: string, errors: ReadonlyArray, diag: DiagnosticMessage) { + if (!errors.some(e => e.code === diag.code)) { + const errorString = errors.map(e => ` ${e.file ? e.file.fileName : "[global]"}: ${e.messageText}`).join("\r\n"); + assert(false, `${message}: Did not find any diagnostic for ${diag.message} in:\r\n${errorString}`); + } + } + + function assertNoErrors(message: string, errors: ReadonlyArray) { + if (errors && errors.length > 0) { + assert(false, `${message}: Expected no errors, but found:\r\n${errors.map(e => ` ${e.messageText}`).join("\r\n")}`); + } + } + + function combineAllPaths(...paths: string[]) { + let result = paths[0]; + for (let i = 1; i < paths.length; i++) { + result = combinePaths(result, paths[i]); + } + return result; + } + + const emptyModule = "export { };"; + + /** + * Produces the text of a source file which imports all of the + * specified module names + */ + function moduleImporting(...names: string[]) { + return names.map((n, i) => `import * as mod_${i} from ${n}`).join("\r\n"); + } + + function testProjectReferences(spec: TestSpecification, entryPointConfigFileName: string, checkResult: (prog: Program, host: fakes.CompilerHost) => void) { + const files = createMap(); + for (const key in spec) { + const sp = spec[key]; + const configFileName = combineAllPaths("/", key, sp.configFileName || "tsconfig.json"); + const options = { + compilerOptions: { + composite: true, + outDir: "bin", + ...sp.options + }, + references: (sp.references || []).map(r => { + if (typeof r === "string") { + return { path: r }; + } + return r; + }), + ...sp.config + }; + const configContent = JSON.stringify(options); + const outDir = options.compilerOptions.outDir; + files.set(configFileName, configContent); + for (const sourceFile of Object.keys(sp.files)) { + files.set(sourceFile, sp.files[sourceFile]); + } + if (sp.outputFiles) { + for (const outFile of Object.keys(sp.outputFiles)) { + files.set(combineAllPaths("/", key, outDir, outFile), sp.outputFiles[outFile]); + } + } + } + + const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content! } }); + files.forEach((v, k) => { + vfsys.mkdirpSync(getDirectoryPath(k)); + vfsys.writeFileSync(k, v); + }); + const host = new fakes.CompilerHost(new fakes.System(vfsys)); + + const { config, error } = readConfigFile(entryPointConfigFileName, name => host.readFile(name)); + + // We shouldn't have any errors about invalid tsconfig files in these tests + assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n")); + const file = parseJsonConfigFileContent(config, parseConfigHostFromCompilerHost(host), getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName); + file.options.configFilePath = entryPointConfigFileName; + const prog = createProgram({ + rootNames: file.fileNames, + options: file.options, + host, + projectReferences: file.projectReferences + }); + checkResult(prog, host); + } + + describe("project-references meta check", () => { + it("default setup was created correctly", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": emptyModule }, + references: [] + }, + "/reference": { + files: { "/secondary/b.ts": moduleImporting("../primary/a") }, + references: ["../primary"] + } + }; + testProjectReferences(spec, "/primary/tsconfig.json", prog => { + assert.isTrue(!!prog, "Program should exist"); + assertNoErrors("Sanity check should not produce errors", prog.getOptionsDiagnostics()); + }); + }); + }); + + /** + * Validate that we enforce the basic settings constraints for referenced projects + */ + describe("project-references constraint checking for settings", () => { + it("errors when declaration = false", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": emptyModule }, + references: [], + options: { + declaration: false + } + } + }; + + testProjectReferences(spec, "/primary/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about the wrong decl setting", errs, Diagnostics.Composite_projects_may_not_disable_declaration_emit); + }); + }); + + it("errors when the referenced project doesn't have composite:true", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": emptyModule }, + references: [], + options: { + composite: false + } + }, + "/reference": { + files: { "/secondary/b.ts": moduleImporting("../primary/a") }, + references: ["../primary"] + } + }; + testProjectReferences(spec, "/reference/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about 'composite' not being set", errs, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true); + }); + }); + + it("errors when the file list is not exhaustive", () => { + const spec: TestSpecification = { + "/primary": { + files: { + "/primary/a.ts": "import * as b from './b'", + "/primary/b.ts": "export {}" + }, + config: { + files: ["a.ts"] + } + } + }; + + testProjectReferences(spec, "/primary/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about b.ts not being in the list", errs, Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern); + }); + }); + + it("errors when the referenced project doesn't exist", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": emptyModule }, + references: ["../foo"] + } + }; + testProjectReferences(spec, "/primary/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about a missing file", errs, Diagnostics.File_0_does_not_exist); + }); + }); + + it("errors when a prepended project reference doesn't set outFile", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": emptyModule }, + references: [{ path: "../someProj", prepend: true }] + }, + "/someProj": { + files: { "/someProj/b.ts": "const x = 100;" } + } + }; + testProjectReferences(spec, "/primary/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about outFile not being set", errs, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set); + }); + }); + + it("errors when a prepended project reference output doesn't exist", () => { + const spec: TestSpecification = { + "/primary": { + files: { "/primary/a.ts": "const y = x;" }, + references: [{ path: "../someProj", prepend: true }] + }, + "/someProj": { + files: { "/someProj/b.ts": "const x = 100;" }, + options: { outFile: "foo.js" } + } + }; + testProjectReferences(spec, "/primary/tsconfig.json", program => { + const errs = program.getOptionsDiagnostics(); + assertHasError("Reports an error about outFile being missing", errs, Diagnostics.Output_file_0_from_project_1_does_not_exist); + }); + }); + }); + + /** + * Path mapping behavior + */ + describe("project-references path mapping", () => { + it("redirects to the output .d.ts file", () => { + const spec: TestSpecification = { + "/alpha": { + files: { "/alpha/a.ts": "export const m: number = 3;" }, + references: [], + outputFiles: { "a.d.ts": emptyModule } + }, + "/beta": { + files: { "/beta/b.ts": "import { m } from '../alpha/a'" }, + references: ["../alpha"] + } + }; + testProjectReferences(spec, "/beta/tsconfig.json", program => { + assertNoErrors("File setup should be correct", program.getOptionsDiagnostics()); + assertHasError("Found a type error", program.getSemanticDiagnostics(), Diagnostics.Module_0_has_no_exported_member_1); + }); + }); + }); + + describe("project-references nice-behavior", () => { + it("issues a nice error when the input file is missing", () => { + const spec: TestSpecification = { + "/alpha": { + files: { "/alpha/a.ts": "export const m: number = 3;" }, + references: [] + }, + "/beta": { + files: { "/beta/b.ts": "import { m } from '../alpha/a'" }, + references: ["../alpha"] + } + }; + testProjectReferences(spec, "/beta/tsconfig.json", program => { + assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1); + }); + }); + }); + + /** + * 'composite' behavior + */ + describe("project-references behavior changes under composite: true", () => { + it("doesn't infer the rootDir from source paths", () => { + const spec: TestSpecification = { + "/alpha": { + files: { "/alpha/src/a.ts": "export const m: number = 3;" }, + options: { + declaration: true, + outDir: "bin" + }, + references: [] + } + }; + testProjectReferences(spec, "/alpha/tsconfig.json", (program, host) => { + program.emit(); + assert.deepEqual(host.outputs.map(e => e.file).sort(), ["/alpha/bin/src/a.d.ts", "/alpha/bin/src/a.js"]); + }); + }); + }); + +} diff --git a/src/server/client.ts b/src/server/client.ts index 39231ae878d..a07e793dcba 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -139,6 +139,11 @@ namespace ts.server { this.processRequest(CommandNames.Change, args); } + toLineColumnOffset(fileName: string, position: number) { + const { line, offset } = this.positionToOneBasedLineOffset(fileName, position); + return { line, character: offset }; + } + getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { const args = this.createFileLocationRequestArgs(fileName, position); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 085ac1d8d73..2bc61c67210 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1331,7 +1331,8 @@ namespace ts.server { configHasExcludeProperty: parsedCommandLine.raw.exclude !== undefined, wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories), typeAcquisition: parsedCommandLine.typeAcquisition, - compileOnSave: parsedCommandLine.compileOnSave + compileOnSave: parsedCommandLine.compileOnSave, + projectReferences: parsedCommandLine.projectReferences }; return { projectOptions, configFileErrors: errors, configFileSpecs: parsedCommandLine.configFileSpecs }; @@ -1464,7 +1465,8 @@ namespace ts.server { projectOptions.compilerOptions, lastFileExceededProgramSize, projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave, - cachedDirectoryStructureHost); + cachedDirectoryStructureHost, + projectOptions.projectReferences); project.configFileSpecs = configFileSpecs; // TODO: We probably should also watch the configFiles that are extended @@ -1589,6 +1591,7 @@ namespace ts.server { // Update the project project.configFileSpecs = configFileSpecs; project.setProjectErrors(configFileErrors); + project.updateReferences(projectOptions.projectReferences); const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); if (lastFileExceededProgramSize) { project.disableLanguageService(lastFileExceededProgramSize); diff --git a/src/server/project.ts b/src/server/project.ts index a97fb9a9bf0..328d41649ca 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -265,6 +265,10 @@ namespace ts.server { return this.projectStateVersion.toString(); } + getProjectReferences(): ReadonlyArray | undefined { + return undefined; + } + getScriptFileNames() { if (!this.rootFiles) { return ts.emptyArray; @@ -1288,7 +1292,8 @@ namespace ts.server { compilerOptions: CompilerOptions, lastFileExceededProgramSize: string | undefined, public compileOnSaveEnabled: boolean, - cachedDirectoryStructureHost: CachedDirectoryStructureHost) { + cachedDirectoryStructureHost: CachedDirectoryStructureHost, + private projectReferences: ReadonlyArray | undefined) { super(configFileName, ProjectKind.Configured, projectService, @@ -1330,6 +1335,14 @@ namespace ts.server { return asNormalizedPath(this.getProjectName()); } + getProjectReferences(): ReadonlyArray | undefined { + return this.projectReferences; + } + + updateReferences(refs: ReadonlyArray | undefined) { + this.projectReferences = refs; + } + enablePlugins() { const host = this.projectService.host; const options = this.getCompilationSettings(); diff --git a/src/server/protocol.ts b/src/server/protocol.ts index d78e3f6bb0f..3eaa42bb103 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2734,6 +2734,7 @@ namespace ts.server.protocol { project?: string; reactNamespace?: string; removeComments?: boolean; + references?: ProjectReference[]; rootDir?: string; rootDirs?: string[]; skipLibCheck?: boolean; diff --git a/src/server/session.ts b/src/server/session.ts index bb635988755..8d6defa1562 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -699,12 +699,14 @@ namespace ts.server { } private toFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan { - const scriptInfo = project.getScriptInfo(fileName); + const ls = project.getLanguageService(); + const start = ls.toLineColumnOffset(fileName, textSpan.start); + const end = ls.toLineColumnOffset(fileName, textSpanEnd(textSpan)); return { file: fileName, - start: scriptInfo.positionToLineOffset(textSpan.start), - end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) + start: { line: start.line + 1, offset: start.character + 1 }, + end: { line: end.line + 1, offset: end.character + 1 } }; } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 363393d401e..5705960f3d2 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -128,6 +128,8 @@ namespace ts.server { configHasFilesProperty: boolean; configHasIncludeProperty: boolean; configHasExcludeProperty: boolean; + + projectReferences: ReadonlyArray | undefined; /** * these fields can be present in the project file */ diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 81742018fb7..d464f7a408a 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -172,9 +172,10 @@ namespace ts { const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); let entry = bucket.get(path); + const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : compilationSettings.target; if (!entry) { // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind); entry = { sourceFile, diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index a5f1c5ed4f4..d5fc94c6d62 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -45,7 +45,7 @@ namespace ts { if (checker.getSymbolAtLocation(importStringLiteral)) continue; const resolved = program.getResolvedModuleWithFailedLookupLocationsFromCache(importStringLiteral.text, sourceFile.fileName); - if (contains(resolved.failedLookupLocations, oldFilePath)) { + if (resolved && contains(resolved.failedLookupLocations, oldFilePath)) { result.push({ sourceFile, toUpdate: importStringLiteral }); } } diff --git a/src/services/services.ts b/src/services/services.ts index f17b7698a87..700b07085a0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -878,6 +878,10 @@ namespace ts { return this._compilationSettings; } + public getProjectReferences(): ReadonlyArray | undefined { + return this.host.getProjectReferences && this.host.getProjectReferences(); + } + private createEntry(fileName: string, path: Path) { let entry: CachedHostFileInformation; const scriptSnapshot = this.host.getScriptSnapshot(fileName); @@ -912,9 +916,18 @@ namespace ts { } public getRootFileNames(): string[] { - return arrayFrom(this.fileNameToEntry.values(), entry => { - return isString(entry) ? entry : entry.hostFileName; + const names: string[] = []; + this.fileNameToEntry.forEach(entry => { + if (isString(entry)) { + names.push(entry); + } + else { + if (entry.scriptKind !== ScriptKind.JSON) { + names.push(entry.hostFileName); + } + } }); + return names; } public getVersion(path: Path): string { @@ -1241,7 +1254,14 @@ namespace ts { } const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); - program = createProgram(rootFileNames, newSettings, compilerHost, program); + const options: CreateProgramOptions = { + rootNames: rootFileNames, + options: newSettings, + host: compilerHost, + oldProgram: program, + projectReferences: hostCache.getProjectReferences() + }; + program = createProgram(options); // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. // It needs to be cleared to allow all collected snapshots to be released @@ -1501,6 +1521,12 @@ namespace ts { return checker.getSymbolAtLocation(node); } + function toLineColumnOffset(fileName: string, position: number) { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); + const file = program.getSourceFile(path) || sourcemappedFileCache.get(path); + return file.getLineAndCharacterOfPosition(position); + } + // Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M]) const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)$/gm; const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/; @@ -2265,6 +2291,7 @@ namespace ts { getProgram, getApplicableRefactors, getEditsForRefactor, + toLineColumnOffset }; } diff --git a/src/services/types.ts b/src/services/types.ts index cd4a497f694..d71b315f29a 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -179,6 +179,7 @@ namespace ts { getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; + getProjectReferences?(): ReadonlyArray | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; getCurrentDirectory(): string; @@ -320,6 +321,8 @@ namespace ts { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; + getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand): Promise; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b8cb75677cb..1e2d3bbc605 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -337,32 +337,34 @@ declare namespace ts { EnumMember = 272, SourceFile = 273, Bundle = 274, - JSDocTypeExpression = 275, - JSDocAllType = 276, - JSDocUnknownType = 277, - JSDocNullableType = 278, - JSDocNonNullableType = 279, - JSDocOptionalType = 280, - JSDocFunctionType = 281, - JSDocVariadicType = 282, - JSDocComment = 283, - JSDocTypeLiteral = 284, - JSDocTag = 285, - JSDocAugmentsTag = 286, - JSDocClassTag = 287, - JSDocParameterTag = 288, - JSDocReturnTag = 289, - JSDocTypeTag = 290, - JSDocTemplateTag = 291, - JSDocTypedefTag = 292, - JSDocPropertyTag = 293, - SyntaxList = 294, - NotEmittedStatement = 295, - PartiallyEmittedExpression = 296, - CommaListExpression = 297, - MergeDeclarationMarker = 298, - EndOfDeclarationMarker = 299, - Count = 300, + UnparsedSource = 275, + InputFiles = 276, + JSDocTypeExpression = 277, + JSDocAllType = 278, + JSDocUnknownType = 279, + JSDocNullableType = 280, + JSDocNonNullableType = 281, + JSDocOptionalType = 282, + JSDocFunctionType = 283, + JSDocVariadicType = 284, + JSDocComment = 285, + JSDocTypeLiteral = 286, + JSDocTag = 287, + JSDocAugmentsTag = 288, + JSDocClassTag = 289, + JSDocParameterTag = 290, + JSDocReturnTag = 291, + JSDocTypeTag = 292, + JSDocTemplateTag = 293, + JSDocTypedefTag = 294, + JSDocPropertyTag = 295, + SyntaxList = 296, + NotEmittedStatement = 297, + PartiallyEmittedExpression = 298, + CommaListExpression = 299, + MergeDeclarationMarker = 300, + EndOfDeclarationMarker = 301, + Count = 302, FirstAssignment = 58, LastAssignment = 70, FirstCompoundAssignment = 59, @@ -388,10 +390,10 @@ declare namespace ts { FirstBinaryOperator = 27, LastBinaryOperator = 70, FirstNode = 145, - FirstJSDocNode = 275, - LastJSDocNode = 293, - FirstJSDocTagNode = 285, - LastJSDocTagNode = 293 + FirstJSDocNode = 277, + LastJSDocNode = 295, + FirstJSDocTagNode = 287, + LastJSDocTagNode = 295 } enum NodeFlags { None = 0, @@ -1645,8 +1647,18 @@ declare namespace ts { } interface Bundle extends Node { kind: SyntaxKind.Bundle; + prepends: ReadonlyArray; sourceFiles: ReadonlyArray; } + interface InputFiles extends Node { + kind: SyntaxKind.InputFiles; + javascriptText: string; + declarationText: string; + } + interface UnparsedSource extends Node { + kind: SyntaxKind.UnparsedSource; + text: string; + } interface JsonSourceFile extends SourceFile { statements: NodeArray; } @@ -1716,6 +1728,11 @@ declare namespace ts { */ getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; + getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + } + interface ResolvedProjectReference { + commandLine: ParsedCommandLine; + sourceFile: SourceFile; } interface CustomTransformers { /** Custom transformers to evaluate before built-in transformations. */ @@ -2335,7 +2352,17 @@ declare namespace ts { interface PluginImport { name: string; } - type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + interface ProjectReference { + /** A normalized path on disk */ + path: string; + /** The path as the user originally wrote it */ + originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ + prepend?: boolean; + /** True if it is intended that this reference form a circularity */ + circular?: boolean; + } + type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; @@ -2391,6 +2418,7 @@ declare namespace ts { project?: string; reactNamespace?: string; jsxFactory?: string; + composite?: boolean; removeComments?: boolean; rootDir?: string; rootDirs?: string[]; @@ -2466,6 +2494,7 @@ declare namespace ts { ES2017 = 4, ES2018 = 5, ESNext = 6, + JSON = 100, Latest = 6 } enum LanguageVariant { @@ -2477,6 +2506,7 @@ declare namespace ts { options: CompilerOptions; typeAcquisition?: TypeAcquisition; fileNames: string[]; + projectReferences?: ReadonlyArray; raw?: any; errors: Diagnostic[]; wildcardDirectories?: MapLike; @@ -2488,8 +2518,17 @@ declare namespace ts { } interface ExpandResult { fileNames: string[]; + projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; } + interface CreateProgramOptions { + rootNames: ReadonlyArray; + options: CompilerOptions; + projectReferences?: ReadonlyArray; + host?: CompilerHost; + oldProgram?: Program; + configFileParsingDiagnostics?: ReadonlyArray; + } interface ModuleResolutionHost { fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; @@ -2580,6 +2619,7 @@ declare namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; + readDirectory?(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[]; /** * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files @@ -3746,8 +3786,10 @@ declare namespace ts { function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; function createCommaList(elements: ReadonlyArray): CommaListExpression; function updateCommaList(node: CommaListExpression, elements: ReadonlyArray): CommaListExpression; - function createBundle(sourceFiles: ReadonlyArray): Bundle; - function updateBundle(node: Bundle, sourceFiles: ReadonlyArray): Bundle; + function createBundle(sourceFiles: ReadonlyArray, prepends?: ReadonlyArray): Bundle; + function createUnparsedSourceFile(text: string): UnparsedSource; + function createInputFiles(javascript: string, declaration: string): InputFiles; + function updateBundle(node: Bundle, sourceFiles: ReadonlyArray, prepends?: ReadonlyArray): Bundle; function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray): CallExpression; function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray, param: ParameterDeclaration, paramValue: Expression): CallExpression; function createImmediatelyInvokedArrowFunction(statements: ReadonlyArray): CallExpression; @@ -3954,6 +3996,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ + function createProgram(createProgramOptions: CreateProgramOptions): Program; function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { @@ -4093,7 +4136,6 @@ declare namespace ts { function createAbstractBuilder(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { - type DiagnosticReporter = (diagnostic: Diagnostic) => void; type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; @@ -4156,15 +4198,6 @@ declare namespace ts { /** Compiler options */ options: CompilerOptions; } - /** - * Reports config file diagnostics - */ - interface ConfigFileDiagnosticsReporter { - /** - * Reports unrecoverable error when parsing config file - */ - onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; - } /** * Host to create watch with config file */ @@ -4211,6 +4244,26 @@ declare namespace ts { } declare namespace ts { function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine; + type DiagnosticReporter = (diagnostic: Diagnostic) => void; + /** + * Reports config file diagnostics + */ + interface ConfigFileDiagnosticsReporter { + /** + * Reports unrecoverable error when parsing config file + */ + onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; + } + /** + * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors + */ + interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { + getCurrentDirectory(): string; + } + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ + function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -4383,6 +4436,7 @@ declare namespace ts { getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; + getProjectReferences?(): ReadonlyArray | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; getCurrentDirectory(): string; @@ -4460,6 +4514,7 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand): Promise; @@ -5383,6 +5438,7 @@ declare namespace ts.server { configHasFilesProperty: boolean; configHasIncludeProperty: boolean; configHasExcludeProperty: boolean; + projectReferences: ReadonlyArray | undefined; /** * these fields can be present in the project file */ @@ -7562,6 +7618,7 @@ declare namespace ts.server.protocol { project?: string; reactNamespace?: string; removeComments?: boolean; + references?: ProjectReference[]; rootDir?: string; rootDirs?: string[]; skipLibCheck?: boolean; @@ -7758,6 +7815,7 @@ declare namespace ts.server { getCompilerOptions(): CompilerOptions; getNewLine(): string; getProjectVersion(): string; + getProjectReferences(): ReadonlyArray | undefined; getScriptFileNames(): string[]; private getOrCreateScriptInfoAndAttachToProject; getScriptKind(fileName: string): ScriptKind; @@ -7859,6 +7917,7 @@ declare namespace ts.server { */ class ConfiguredProject extends Project { compileOnSaveEnabled: boolean; + private projectReferences; private typeAcquisition; private directoriesWatchedForWildcards; readonly canonicalConfigFilePath: NormalizedPath; @@ -7871,6 +7930,8 @@ declare namespace ts.server { */ updateGraph(): boolean; getConfigFilePath(): NormalizedPath; + getProjectReferences(): ReadonlyArray | undefined; + updateReferences(refs: ReadonlyArray | undefined): void; enablePlugins(): void; /** * Get the errors that dont have any file name associated diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ff0b1f65134..b6dbb1d54dd 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -337,32 +337,34 @@ declare namespace ts { EnumMember = 272, SourceFile = 273, Bundle = 274, - JSDocTypeExpression = 275, - JSDocAllType = 276, - JSDocUnknownType = 277, - JSDocNullableType = 278, - JSDocNonNullableType = 279, - JSDocOptionalType = 280, - JSDocFunctionType = 281, - JSDocVariadicType = 282, - JSDocComment = 283, - JSDocTypeLiteral = 284, - JSDocTag = 285, - JSDocAugmentsTag = 286, - JSDocClassTag = 287, - JSDocParameterTag = 288, - JSDocReturnTag = 289, - JSDocTypeTag = 290, - JSDocTemplateTag = 291, - JSDocTypedefTag = 292, - JSDocPropertyTag = 293, - SyntaxList = 294, - NotEmittedStatement = 295, - PartiallyEmittedExpression = 296, - CommaListExpression = 297, - MergeDeclarationMarker = 298, - EndOfDeclarationMarker = 299, - Count = 300, + UnparsedSource = 275, + InputFiles = 276, + JSDocTypeExpression = 277, + JSDocAllType = 278, + JSDocUnknownType = 279, + JSDocNullableType = 280, + JSDocNonNullableType = 281, + JSDocOptionalType = 282, + JSDocFunctionType = 283, + JSDocVariadicType = 284, + JSDocComment = 285, + JSDocTypeLiteral = 286, + JSDocTag = 287, + JSDocAugmentsTag = 288, + JSDocClassTag = 289, + JSDocParameterTag = 290, + JSDocReturnTag = 291, + JSDocTypeTag = 292, + JSDocTemplateTag = 293, + JSDocTypedefTag = 294, + JSDocPropertyTag = 295, + SyntaxList = 296, + NotEmittedStatement = 297, + PartiallyEmittedExpression = 298, + CommaListExpression = 299, + MergeDeclarationMarker = 300, + EndOfDeclarationMarker = 301, + Count = 302, FirstAssignment = 58, LastAssignment = 70, FirstCompoundAssignment = 59, @@ -388,10 +390,10 @@ declare namespace ts { FirstBinaryOperator = 27, LastBinaryOperator = 70, FirstNode = 145, - FirstJSDocNode = 275, - LastJSDocNode = 293, - FirstJSDocTagNode = 285, - LastJSDocTagNode = 293 + FirstJSDocNode = 277, + LastJSDocNode = 295, + FirstJSDocTagNode = 287, + LastJSDocTagNode = 295 } enum NodeFlags { None = 0, @@ -1645,8 +1647,18 @@ declare namespace ts { } interface Bundle extends Node { kind: SyntaxKind.Bundle; + prepends: ReadonlyArray; sourceFiles: ReadonlyArray; } + interface InputFiles extends Node { + kind: SyntaxKind.InputFiles; + javascriptText: string; + declarationText: string; + } + interface UnparsedSource extends Node { + kind: SyntaxKind.UnparsedSource; + text: string; + } interface JsonSourceFile extends SourceFile { statements: NodeArray; } @@ -1716,6 +1728,11 @@ declare namespace ts { */ getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; + getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + } + interface ResolvedProjectReference { + commandLine: ParsedCommandLine; + sourceFile: SourceFile; } interface CustomTransformers { /** Custom transformers to evaluate before built-in transformations. */ @@ -2335,7 +2352,17 @@ declare namespace ts { interface PluginImport { name: string; } - type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + interface ProjectReference { + /** A normalized path on disk */ + path: string; + /** The path as the user originally wrote it */ + originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ + prepend?: boolean; + /** True if it is intended that this reference form a circularity */ + circular?: boolean; + } + type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; @@ -2391,6 +2418,7 @@ declare namespace ts { project?: string; reactNamespace?: string; jsxFactory?: string; + composite?: boolean; removeComments?: boolean; rootDir?: string; rootDirs?: string[]; @@ -2466,6 +2494,7 @@ declare namespace ts { ES2017 = 4, ES2018 = 5, ESNext = 6, + JSON = 100, Latest = 6 } enum LanguageVariant { @@ -2477,6 +2506,7 @@ declare namespace ts { options: CompilerOptions; typeAcquisition?: TypeAcquisition; fileNames: string[]; + projectReferences?: ReadonlyArray; raw?: any; errors: Diagnostic[]; wildcardDirectories?: MapLike; @@ -2488,8 +2518,17 @@ declare namespace ts { } interface ExpandResult { fileNames: string[]; + projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; } + interface CreateProgramOptions { + rootNames: ReadonlyArray; + options: CompilerOptions; + projectReferences?: ReadonlyArray; + host?: CompilerHost; + oldProgram?: Program; + configFileParsingDiagnostics?: ReadonlyArray; + } interface ModuleResolutionHost { fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; @@ -2580,6 +2619,7 @@ declare namespace ts { getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; + readDirectory?(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[]; /** * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files @@ -3746,8 +3786,10 @@ declare namespace ts { function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; function createCommaList(elements: ReadonlyArray): CommaListExpression; function updateCommaList(node: CommaListExpression, elements: ReadonlyArray): CommaListExpression; - function createBundle(sourceFiles: ReadonlyArray): Bundle; - function updateBundle(node: Bundle, sourceFiles: ReadonlyArray): Bundle; + function createBundle(sourceFiles: ReadonlyArray, prepends?: ReadonlyArray): Bundle; + function createUnparsedSourceFile(text: string): UnparsedSource; + function createInputFiles(javascript: string, declaration: string): InputFiles; + function updateBundle(node: Bundle, sourceFiles: ReadonlyArray, prepends?: ReadonlyArray): Bundle; function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray): CallExpression; function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray, param: ParameterDeclaration, paramValue: Expression): CallExpression; function createImmediatelyInvokedArrowFunction(statements: ReadonlyArray): CallExpression; @@ -3954,6 +3996,7 @@ declare namespace ts { * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ + function createProgram(createProgramOptions: CreateProgramOptions): Program; function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; } declare namespace ts { @@ -4093,7 +4136,6 @@ declare namespace ts { function createAbstractBuilder(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { - type DiagnosticReporter = (diagnostic: Diagnostic) => void; type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; @@ -4156,15 +4198,6 @@ declare namespace ts { /** Compiler options */ options: CompilerOptions; } - /** - * Reports config file diagnostics - */ - interface ConfigFileDiagnosticsReporter { - /** - * Reports unrecoverable error when parsing config file - */ - onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; - } /** * Host to create watch with config file */ @@ -4211,6 +4244,26 @@ declare namespace ts { } declare namespace ts { function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine; + type DiagnosticReporter = (diagnostic: Diagnostic) => void; + /** + * Reports config file diagnostics + */ + interface ConfigFileDiagnosticsReporter { + /** + * Reports unrecoverable error when parsing config file + */ + onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; + } + /** + * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors + */ + interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { + getCurrentDirectory(): string; + } + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ + function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -4383,6 +4436,7 @@ declare namespace ts { getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; + getProjectReferences?(): ReadonlyArray | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; getCurrentDirectory(): string; @@ -4460,6 +4514,7 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray; getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand): Promise; diff --git a/tests/baselines/reference/declarationMapsOutFile.js.map b/tests/baselines/reference/declarationMapsOutFile.js.map index 051318f8064..0018f3f9f31 100644 --- a/tests/baselines/reference/declarationMapsOutFile.js.map +++ b/tests/baselines/reference/declarationMapsOutFile.js.map @@ -1,2 +1,2 @@ //// [bundle.d.ts.map] -{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":";IAAA,MAAM;QACF,OAAO,CAAC,CAAC,EAAE;YAAC,CAAC,EAAE,MAAM,CAAA;SAAC;;;QAGtB,MAAM,CAAC,IAAI;KAGd;;;ICPD,OAAO,EAAC,GAAG,EAAC,UAAY;IAExB,MAAM,CAAC,KAAY,CAAC;IAGpB,MAAM,CAAC,IAAI,CAAC;;KAAqB,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":";IAAA,MAAM;QACF,OAAO,CAAC,GAAG;YAAC,CAAC,EAAE,MAAM,CAAA;SAAC;;;QAGtB,MAAM,CAAC,IAAI;KAGd;;;ICPD,OAAO,EAAC,GAAG,EAAC,UAAY;IAExB,MAAM,CAAC,KAAY,CAAC;IAGpB,MAAM,CAAC,IAAI,CAAC;;KAAqB,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/declarationMapsOutFile.sourcemap.txt b/tests/baselines/reference/declarationMapsOutFile.sourcemap.txt index 39d83719b20..f1090c4f765 100644 --- a/tests/baselines/reference/declarationMapsOutFile.sourcemap.txt +++ b/tests/baselines/reference/declarationMapsOutFile.sourcemap.txt @@ -22,20 +22,17 @@ sourceFile:tests/cases/compiler/a.ts 1->^^^^^^^^ 2 > ^^^^^^^ 3 > ^ -4 > ^ -5 > ^^ -6 > ^^^^-> +4 > ^^^ +5 > ^^^^-> 1-> class Foo { > 2 > doThing 3 > ( -4 > x -5 > : +4 > x: 1->Emitted(3, 9) Source(2, 5) + SourceIndex(0) 2 >Emitted(3, 16) Source(2, 12) + SourceIndex(0) 3 >Emitted(3, 17) Source(2, 13) + SourceIndex(0) -4 >Emitted(3, 18) Source(2, 14) + SourceIndex(0) -5 >Emitted(3, 20) Source(2, 16) + SourceIndex(0) +4 >Emitted(3, 20) Source(2, 16) + SourceIndex(0) --- >>> a: number; 1->^^^^^^^^^^^^ diff --git a/tests/baselines/reference/declarationMapsOutFile2.js.map b/tests/baselines/reference/declarationMapsOutFile2.js.map index 22845f90fb2..579077e0679 100644 --- a/tests/baselines/reference/declarationMapsOutFile2.js.map +++ b/tests/baselines/reference/declarationMapsOutFile2.js.map @@ -1,2 +1,2 @@ //// [bundle.d.ts.map] -{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"} \ No newline at end of file +{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,GAAG;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/declarationMapsOutFile2.sourcemap.txt b/tests/baselines/reference/declarationMapsOutFile2.sourcemap.txt index d7a829917e6..469e5ff2bd9 100644 --- a/tests/baselines/reference/declarationMapsOutFile2.sourcemap.txt +++ b/tests/baselines/reference/declarationMapsOutFile2.sourcemap.txt @@ -18,20 +18,17 @@ sourceFile:tests/cases/compiler/a.ts 1->^^^^ 2 > ^^^^^^^ 3 > ^ -4 > ^ -5 > ^^ -6 > ^^^^-> +4 > ^^^ +5 > ^^^^-> 1->class Foo { > 2 > doThing 3 > ( -4 > x -5 > : +4 > x: 1->Emitted(2, 5) Source(2, 5) + SourceIndex(0) 2 >Emitted(2, 12) Source(2, 12) + SourceIndex(0) 3 >Emitted(2, 13) Source(2, 13) + SourceIndex(0) -4 >Emitted(2, 14) Source(2, 14) + SourceIndex(0) -5 >Emitted(2, 16) Source(2, 16) + SourceIndex(0) +4 >Emitted(2, 16) Source(2, 16) + SourceIndex(0) --- >>> a: number; 1->^^^^^^^^ diff --git a/tests/baselines/reference/declarationMapsWithSourceMap.js.map b/tests/baselines/reference/declarationMapsWithSourceMap.js.map index 17ef6a6004c..9e27f440818 100644 --- a/tests/baselines/reference/declarationMapsWithSourceMap.js.map +++ b/tests/baselines/reference/declarationMapsWithSourceMap.js.map @@ -1,3 +1,3 @@ //// [bundle.js.map] {"version":3,"file":"bundle.js","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IAAA;IAOA,CAAC;IANG,qBAAO,GAAP,UAAQ,CAAc;QAClB,OAAO,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC,CAAC;IACpB,CAAC;IACM,QAAI,GAAX;QACI,OAAO,IAAI,GAAG,EAAE,CAAC;IACrB,CAAC;IACL,UAAC;AAAD,CAAC,AAPD,IAOC;ACPD,IAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AACpB,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC;AAEnB,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC"}//// [bundle.d.ts.map] -{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"} \ No newline at end of file +{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,GAAG;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/declarationMapsWithSourceMap.sourcemap.txt b/tests/baselines/reference/declarationMapsWithSourceMap.sourcemap.txt index 0f9df308ef6..86d306d00fb 100644 --- a/tests/baselines/reference/declarationMapsWithSourceMap.sourcemap.txt +++ b/tests/baselines/reference/declarationMapsWithSourceMap.sourcemap.txt @@ -312,20 +312,17 @@ sourceFile:tests/cases/compiler/a.ts 1->^^^^ 2 > ^^^^^^^ 3 > ^ -4 > ^ -5 > ^^ -6 > ^^^^-> +4 > ^^^ +5 > ^^^^-> 1->class Foo { > 2 > doThing 3 > ( -4 > x -5 > : +4 > x: 1->Emitted(2, 5) Source(2, 5) + SourceIndex(0) 2 >Emitted(2, 12) Source(2, 12) + SourceIndex(0) 3 >Emitted(2, 13) Source(2, 13) + SourceIndex(0) -4 >Emitted(2, 14) Source(2, 14) + SourceIndex(0) -5 >Emitted(2, 16) Source(2, 16) + SourceIndex(0) +4 >Emitted(2, 16) Source(2, 16) + SourceIndex(0) --- >>> a: number; 1->^^^^^^^^ diff --git a/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts b/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts new file mode 100644 index 00000000000..289bf129119 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.d.ts @@ -0,0 +1,4 @@ +/// +declare class B { + c: C; +} diff --git a/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.js b/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.js new file mode 100644 index 00000000000..e3580f23910 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/amd/FolderA/FolderB/fileB.js @@ -0,0 +1,6 @@ +/// +var B = /** @class */ (function () { + function B() { + } + return B; +}()); diff --git a/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.d.ts b/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.d.ts new file mode 100644 index 00000000000..8147620b211 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.d.ts @@ -0,0 +1,2 @@ +declare class C { +} diff --git a/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.js b/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.js new file mode 100644 index 00000000000..35b4a697f30 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/amd/outdir/simple/fileC.js @@ -0,0 +1,5 @@ +var C = /** @class */ (function () { + function C() { + } + return C; +}()); diff --git a/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts b/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts new file mode 100644 index 00000000000..289bf129119 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.d.ts @@ -0,0 +1,4 @@ +/// +declare class B { + c: C; +} diff --git a/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.js b/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.js new file mode 100644 index 00000000000..e3580f23910 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/node/FolderA/FolderB/fileB.js @@ -0,0 +1,6 @@ +/// +var B = /** @class */ (function () { + function B() { + } + return B; +}()); diff --git a/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.d.ts b/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.d.ts new file mode 100644 index 00000000000..8147620b211 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.d.ts @@ -0,0 +1,2 @@ +declare class C { +} diff --git a/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.js b/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.js new file mode 100644 index 00000000000..35b4a697f30 --- /dev/null +++ b/tests/baselines/reference/project/rootDirectoryErrors/node/outdir/simple/fileC.js @@ -0,0 +1,5 @@ +var C = /** @class */ (function () { + function C() { + } + return C; +}()); diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 28ccc78540c..0b72c3fd8a7 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index c75fe3c9dc6..4d5c6053bcc 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 25c75a4b556..f84c7f3abf3 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 168fcc6dfe6..b65582c7841 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index e87936a34fc..86d25e2362a 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index c00426a373b..b623b1198c2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 28ccc78540c..0b72c3fd8a7 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index a4d7d4ffc2c..ea9df560138 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index d01ba76d822..bab4947a8e5 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -13,6 +13,7 @@ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ From 10f2eb5ff1bdbf655fa7e51fcc7ef8adbe713118 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 7 May 2018 15:39:00 -0700 Subject: [PATCH 32/64] Pass setParentNodes through to parseJsonText --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9db66792a7a..4b55bba412c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -505,7 +505,7 @@ namespace ts { performance.mark("beforeParse"); let result: SourceFile; if (languageVersion === ScriptTarget.JSON) { - result = Parser.parseJsonText(fileName, sourceText); + result = Parser.parseJsonText(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); } else { result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); From a50001c9daa103334a5b13791850b4cd9a6fb197 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 15:42:36 -0700 Subject: [PATCH 33/64] Treat 'import("")' as a module reference (#23949) --- src/services/findAllReferences.ts | 3 ++- tests/cases/fourslash/findAllRefsImportTypeOfModule.ts | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 9995bc858a0..bedb657a66d 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -272,6 +272,8 @@ namespace ts.FindAllReferences.Core { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: return true; + case SyntaxKind.LiteralType: + return isImportTypeNode(node.parent.parent); case SyntaxKind.CallExpression: return isRequireCall(node.parent as CallExpression, /*checkArgumentIsStringLiteralLike*/ false) || isImportCall(node.parent as CallExpression); default: @@ -407,7 +409,6 @@ namespace ts.FindAllReferences.Core { return firstDefined(symbol.declarations, decl => { if (!decl.parent) { // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. - Debug.assert(decl.kind === SyntaxKind.SourceFile); Debug.fail(`Unexpected symbol at ${Debug.showSyntaxKind(node)}: ${Debug.showSymbol(symbol)}`); } return isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent) diff --git a/tests/cases/fourslash/findAllRefsImportTypeOfModule.ts b/tests/cases/fourslash/findAllRefsImportTypeOfModule.ts index 4c672c69548..7267a816eeb 100644 --- a/tests/cases/fourslash/findAllRefsImportTypeOfModule.ts +++ b/tests/cases/fourslash/findAllRefsImportTypeOfModule.ts @@ -1,11 +1,13 @@ /// +// @Filename: /b.ts ////type [|{| "isWriteAccess": true, "isDefinition": true |}T|] = number; ////export = [|T|]; -////const x: [|import("./b")|] = 0; +// @Filename: /a.ts +////const x: import("[|./b|]") = 0; -// TODO: GH#23879 should just verify.rangesReferenceEachOther(); +// TODO: GH#23879 Should be `verify.singleReferenceGroup("type T = number") const [r0, r1, r2] = test.ranges(); verify.referenceGroups([r0, r1], [{ definition: "type T = number", ranges: [r0, r1] }]); -verify.referenceGroups(r2, undefined); +verify.referenceGroups(r2, [{ definition: 'module "/b"', ranges: [r2] }]); From 123ae530a7fae6ce56a5d6808177f53f9413124b Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 7 May 2018 15:45:43 -0700 Subject: [PATCH 34/64] convertToEs6Module: Replace 'module.exports =' with 'export default' without replacing nodes (#23948) --- src/services/codefixes/convertToEs6Module.ts | 46 ++++++------------- ...vertToEs6Module_export_moduleDotExports.ts | 10 ++-- .../refactorConvertToEs6Module_foo.ts | 23 ++++++++++ 3 files changed, 40 insertions(+), 39 deletions(-) create mode 100644 tests/cases/fourslash/refactorConvertToEs6Module_foo.ts diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index a8df21dc96d..b496697d541 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -192,13 +192,17 @@ namespace ts.codefix { changes.deleteNode(sourceFile, assignment.parent); } else { - let newNodes = isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right) : undefined; - let changedToDefaultExport = false; - if (!newNodes) { - ([newNodes, changedToDefaultExport] = convertModuleExportsToExportDefault(right, checker)); + const replacement = isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right) + : isRequireCall(right, /*checkArgumentIsStringLiteralLike*/ true) ? convertReExportAll(right.arguments[0], checker) + : undefined; + if (replacement) { + changes.replaceNodeWithNodes(sourceFile, assignment.parent, replacement[0]); + return replacement[1]; + } + else { + changes.replaceRangeWithText(sourceFile, createTextRange(left.getStart(sourceFile), right.pos), "export default"); + return true; } - changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes); - return changedToDefaultExport; } } else if (isExportsOrModuleExportsOrAlias(sourceFile, left.expression)) { @@ -212,8 +216,8 @@ namespace ts.codefix { * Convert `module.exports = { ... }` to individual exports.. * We can't always do this if the module has interesting members -- then it will be a default export instead. */ - function tryChangeModuleExportsObject(object: ObjectLiteralExpression): ReadonlyArray | undefined { - return mapAllOrFail(object.properties, prop => { + function tryChangeModuleExportsObject(object: ObjectLiteralExpression): [ReadonlyArray, ModuleExportsChanged] | undefined { + const statements = mapAllOrFail(object.properties, prop => { switch (prop.kind) { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: @@ -229,6 +233,7 @@ namespace ts.codefix { Debug.assertNever(prop); } }); + return statements && [statements, true]; } function convertNamedExport( @@ -256,31 +261,6 @@ namespace ts.codefix { } } - function convertModuleExportsToExportDefault(exported: Expression, checker: TypeChecker): [ReadonlyArray, ModuleExportsChanged] { - const modifiers = [createToken(SyntaxKind.ExportKeyword), createToken(SyntaxKind.DefaultKeyword)]; - switch (exported.kind) { - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: { - // `module.exports = function f() {}` --> `export default function f() {}` - const fn = exported as FunctionExpression | ArrowFunction; - return [[functionExpressionToDeclaration(fn.name && fn.name.text, modifiers, fn)], true]; - } - case SyntaxKind.ClassExpression: { - // `module.exports = class C {}` --> `export default class C {}` - const cls = exported as ClassExpression; - return [[classExpressionToDeclaration(cls.name && cls.name.text, modifiers, cls)], true]; - } - case SyntaxKind.CallExpression: - if (isRequireCall(exported, /*checkArgumentIsStringLiteralLike*/ true)) { - return convertReExportAll(exported.arguments[0], checker); - } - // falls through - default: - // `module.exports = 0;` --> `export default 0;` - return [[createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, exported)], true]; - } - } - function convertReExportAll(reExported: StringLiteralLike, checker: TypeChecker): [ReadonlyArray, ModuleExportsChanged] { // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` const moduleSpecifier = reExported.text; diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_export_moduleDotExports.ts b/tests/cases/fourslash/refactorConvertToEs6Module_export_moduleDotExports.ts index 327f7b480a9..e88e3e2f173 100644 --- a/tests/cases/fourslash/refactorConvertToEs6Module_export_moduleDotExports.ts +++ b/tests/cases/fourslash/refactorConvertToEs6Module_export_moduleDotExports.ts @@ -15,11 +15,9 @@ verify.codeFix({ description: "Convert to ES6 module", newFileContent: -`export default function() { } -export default function f() { } -export default class { -} -export default class C { -} +`export default function() {} +export default function f() {} +export default class {} +export default class C {} export default 0;`, }); diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_foo.ts b/tests/cases/fourslash/refactorConvertToEs6Module_foo.ts new file mode 100644 index 00000000000..2abff8c95df --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToEs6Module_foo.ts @@ -0,0 +1,23 @@ +/// + +// @allowJs: true +// @target: esnext + +// @Filename: /a.js +////const b = require("./b"); +////module.exports = class C { +//// m() { +//// b.x; +//// } +////}; + +verify.codeFix({ + description: "Convert to ES6 module", + newFileContent: +`import { x } from "./b"; +export default class C { + m() { + x; + } +};`, +}); From 7b888906f7aba50f7bbd5a0c519c22c4ef04af4c Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 8 May 2018 04:10:32 +0000 Subject: [PATCH 35/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 24 +++++++++++ .../diagnosticMessages.generated.json.lcl | 42 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 42 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 24 +++++++++++ .../diagnosticMessages.generated.json.lcl | 24 +++++++++++ 5 files changed, 156 insertions(+) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index c57179896e8..0772c6551d1 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2523,6 +2523,9 @@ + + + @@ -2556,6 +2559,9 @@ + + + @@ -4296,6 +4302,12 @@ + + + + + + @@ -5592,6 +5604,12 @@ + + + + + + @@ -7443,6 +7461,9 @@ + + + @@ -9387,6 +9408,9 @@ + + + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index fef4c0bf1b9..b6d30cd95f8 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2529,6 +2529,15 @@ + + + + + + + + + @@ -2556,6 +2565,15 @@ + + + + + + + + + @@ -4293,6 +4311,12 @@ + + + + + + @@ -5589,6 +5613,12 @@ + + + + + + @@ -7440,6 +7470,9 @@ + + + @@ -9381,6 +9414,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 42785ba47cb..83c9542ac40 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2529,6 +2529,15 @@ + + + + + + + + + @@ -2556,6 +2565,15 @@ + + + + + + + + + @@ -4293,6 +4311,12 @@ + + + + + + @@ -5589,6 +5613,12 @@ + + + + + + @@ -7440,6 +7470,9 @@ + + + @@ -9381,6 +9414,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index e2a8c44ad2a..4b662f5b9c3 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2523,6 +2523,9 @@ + + + @@ -2556,6 +2559,9 @@ + + + @@ -4296,6 +4302,12 @@ + + + + + + @@ -5592,6 +5604,12 @@ + + + + + + @@ -7443,6 +7461,9 @@ + + + @@ -9387,6 +9408,9 @@ + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 4da1437d75c..19679bd8c21 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2516,6 +2516,9 @@ + + + @@ -2549,6 +2552,9 @@ + + + @@ -4289,6 +4295,12 @@ + + + + + + @@ -5585,6 +5597,12 @@ + + + + + + @@ -7436,6 +7454,9 @@ + + + @@ -9380,6 +9401,9 @@ + + + From ba360cfc4ff16d3bc0bfd5771eca0e524bea2280 Mon Sep 17 00:00:00 2001 From: Paul Koerbitz Date: Tue, 8 May 2018 07:45:48 +0200 Subject: [PATCH 36/64] Make error message for dynamic imports when module is ES2015 more helpful --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a34f073df3e..64f7e746dae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28103,7 +28103,7 @@ namespace ts { function checkGrammarImportCallExpression(node: ImportCall): boolean { if (moduleKind === ModuleKind.ES2015) { - return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules); + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules_Please_use_esnext_or_commonjs_as_module_compiler_option); } if (node.typeArguments) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c12e0a9931b..a92b701380b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -895,7 +895,7 @@ "category": "Error", "code": 1322 }, - "Dynamic import cannot be used when targeting ECMAScript 2015 modules.": { + "Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option.": { "category": "Error", "code": 1323 }, From 5b846856c20abbee79eb467d6fa87e26463f4012 Mon Sep 17 00:00:00 2001 From: Paul Koerbitz Date: Tue, 8 May 2018 07:51:29 +0200 Subject: [PATCH 37/64] Accept baselines for new import call expression error in ES2015 --- .../importCallExpressionErrorInES2015.errors.txt | 12 ++++++------ .../importCallExpressionNestedES2015.errors.txt | 8 ++++---- .../importCallExpressionNestedES20152.errors.txt | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt b/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt index d47980d1312..0a642ff9857 100644 --- a/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt +++ b/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/dynamicImport/1.ts(1,1): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. -tests/cases/conformance/dynamicImport/1.ts(2,10): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. -tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +tests/cases/conformance/dynamicImport/1.ts(1,1): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/1.ts(2,10): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. ==== tests/cases/conformance/dynamicImport/0.ts (0 errors) ==== @@ -9,10 +9,10 @@ tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import c ==== tests/cases/conformance/dynamicImport/1.ts (3 errors) ==== import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. var p1 = import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. p1.then(zero => { return zero.foo(); }) @@ -20,5 +20,5 @@ tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import c function foo() { const p2 = import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt index 1208dd0c709..530cd0d1b1d 100644 --- a/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt +++ b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. -tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. ==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic impo async function foo() { return await import((await import("./foo")).default); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. ~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt index 1208dd0c709..530cd0d1b1d 100644 --- a/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt +++ b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. -tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. ==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic impo async function foo() { return await import((await import("./foo")).default); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. ~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. } \ No newline at end of file From 4d37c44b92ea53129bf3d682ffff2dc9f9736a4b Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Tue, 8 May 2018 08:21:08 +0200 Subject: [PATCH 38/64] Apply transformation to await expression --- src/compiler/transformers/esnext.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 109025c375d..f0bd43a4659 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -147,7 +147,9 @@ namespace ts { return setOriginalNode( setTextRange( createYield( - createDownlevelAwait(node.expression) + createDownlevelAwait( + visitNode(node.expression, visitor, isExpression) + ) ), node ), From ec974a599aeda4117e07702d1b4a8553a0be1f9a Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 8 May 2018 10:10:40 +0000 Subject: [PATCH 39/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 48 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 48 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index fa924a9d856..1a9638ca02d 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2520,6 +2520,15 @@ + + + + + + + + + @@ -2547,6 +2556,15 @@ + + + + + + + + + @@ -4284,6 +4302,12 @@ + + + + + + @@ -5580,6 +5604,12 @@ + + + + + + @@ -7428,6 +7458,15 @@ + + + + + + + + + @@ -9366,6 +9405,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index f7c9f90e59e..6f596916ae7 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2510,6 +2510,15 @@ + + + + + + + + + @@ -2537,6 +2546,15 @@ + + + + + + + + + @@ -4274,6 +4292,12 @@ + + + + + + @@ -5570,6 +5594,12 @@ + + + + + + @@ -7415,6 +7445,15 @@ + + + + + + + + + @@ -9353,6 +9392,15 @@ + + + + + + + + + From a930b571f9430c1b4328b89920637c4e29f1cacf Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 8 May 2018 16:10:28 +0000 Subject: [PATCH 40/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 48 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 42 ++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2690ba4fe89..1a0f4433a62 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2529,6 +2529,15 @@ + + + + + + + + + @@ -2556,6 +2565,15 @@ + + + + + + + + + @@ -4293,6 +4311,12 @@ + + + + + + @@ -5589,6 +5613,12 @@ + + + + + + @@ -7437,6 +7467,15 @@ + + + + + + + + + @@ -9375,6 +9414,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 72d1e44d2d4..5d69f25ad5d 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2510,6 +2510,15 @@ + + + + + + + + + @@ -2537,6 +2546,15 @@ + + + + + + + + + @@ -4274,6 +4292,12 @@ + + + + + + @@ -5570,6 +5594,12 @@ + + + + + + @@ -7418,6 +7448,9 @@ + + + @@ -9359,6 +9392,15 @@ + + + + + + + + + From ce6fd5eeaaede51caa79bc9becbc8f5bf58ecc3e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 May 2018 09:42:03 -0700 Subject: [PATCH 41/64] Exception for 'any' constraint only applies to type parameters --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a34f073df3e..1c9de743e9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10740,7 +10740,7 @@ namespace ts { } } const constraint = getConstraintForRelation(source); - if (!constraint || constraint.flags & TypeFlags.Any) { + if (!constraint || (source.flags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) { // A type variable with no constraint is not related to the non-primitive object type. if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) { errorInfo = saveErrorInfo; From 238177657fcd10526010d525093eb3b58d128b0d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 May 2018 09:42:21 -0700 Subject: [PATCH 42/64] Add regression test --- .../conformance/types/keyof/keyofAndIndexedAccess.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index 83687e8c872..07aa3c1994f 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -629,3 +629,11 @@ class Unbounded { let y: {} | undefined | null = x; } } + +// Repro from #23940 + +interface I7 { + x: any; +} +type Foo7 = T; +declare function f7(type: K): Foo7; From 14e3e3923707b225041bdced33b8a06dbcfe6c2d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 May 2018 09:42:26 -0700 Subject: [PATCH 43/64] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 13 +++++++++++ .../reference/keyofAndIndexedAccess.symbols | 23 +++++++++++++++++++ .../reference/keyofAndIndexedAccess.types | 23 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index 3d222583ffd..c23f10f3e68 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -627,6 +627,14 @@ class Unbounded { let y: {} | undefined | null = x; } } + +// Repro from #23940 + +interface I7 { + x: any; +} +type Foo7 = T; +declare function f7(type: K): Foo7; //// [keyofAndIndexedAccess.js] @@ -1368,3 +1376,8 @@ declare function fn(o: T, k: K): void; declare class Unbounded { foo(x: T[keyof T]): void; } +interface I7 { + x: any; +} +declare type Foo7 = T; +declare function f7(type: K): Foo7; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index a40a2347d91..ef43a711264 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -2235,3 +2235,26 @@ class Unbounded { } } +// Repro from #23940 + +interface I7 { +>I7 : Symbol(I7, Decl(keyofAndIndexedAccess.ts, 627, 1)) + + x: any; +>x : Symbol(I7.x, Decl(keyofAndIndexedAccess.ts, 631, 14)) +} +type Foo7 = T; +>Foo7 : Symbol(Foo7, Decl(keyofAndIndexedAccess.ts, 633, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 634, 10)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 634, 10)) + +declare function f7(type: K): Foo7; +>f7 : Symbol(f7, Decl(keyofAndIndexedAccess.ts, 634, 32)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 635, 20)) +>I7 : Symbol(I7, Decl(keyofAndIndexedAccess.ts, 627, 1)) +>type : Symbol(type, Decl(keyofAndIndexedAccess.ts, 635, 40)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 635, 20)) +>Foo7 : Symbol(Foo7, Decl(keyofAndIndexedAccess.ts, 633, 1)) +>I7 : Symbol(I7, Decl(keyofAndIndexedAccess.ts, 627, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 635, 20)) + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 0d6a350bd3c..a85b34d707b 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -2591,3 +2591,26 @@ class Unbounded { } } +// Repro from #23940 + +interface I7 { +>I7 : I7 + + x: any; +>x : any +} +type Foo7 = T; +>Foo7 : T +>T : T +>T : T + +declare function f7(type: K): Foo7; +>f7 : (type: K) => I7[K] +>K : K +>I7 : I7 +>type : K +>K : K +>Foo7 : T +>I7 : I7 +>K : K + From ddf20ecd6db0d47c3a0efffcc1f17e5e2e50472b Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 May 2018 09:52:46 -0700 Subject: [PATCH 44/64] Support '.' as a trigger character (#23890) * Support '.' as a trigger character * Add a CompletionsTriggerCharacter type * Add more trigger characters * Add another type CompletionsTriggerCharacter * Update API baselines --- src/harness/fourslash.ts | 15 +++++++++++---- src/server/protocol.ts | 4 +++- src/services/completions.ts | 10 +++++++--- src/services/types.ts | 4 +++- .../baselines/reference/api/tsserverlibrary.d.ts | 6 ++++-- tests/baselines/reference/api/typescript.d.ts | 3 ++- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ff14e5b770b..5e7dede93ee 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -957,7 +957,14 @@ namespace FourSlash { } public verifyCompletionsAt(markerName: string | ReadonlyArray, expected: ReadonlyArray, options?: FourSlashInterface.CompletionsAtOptions) { - this.verifyCompletions({ marker: markerName, exact: expected, isNewIdentifierLocation: options && options.isNewIdentifierLocation, preferences: options, triggerCharacter: options && options.triggerCharacter }); + this.verifyCompletions({ + marker: markerName, + exact: expected, + isNewIdentifierLocation: options && options.isNewIdentifierLocation, + preferences: options, + // TODO: GH#20090 + triggerCharacter: (options && options.triggerCharacter) as ts.CompletionsTriggerCharacter | undefined, + }); } public verifyCompletionListContains(entryId: ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string | { kind?: string, kindModifiers?: string }, spanIndex?: number, hasAction?: boolean, options?: FourSlashInterface.VerifyCompletionListContainsOptions) { @@ -4719,7 +4726,7 @@ namespace FourSlashInterface { readonly sourceDisplay?: string; }; export interface CompletionsAtOptions extends Partial { - triggerCharacter?: string; + triggerCharacter?: ts.CompletionsTriggerCharacter; isNewIdentifierLocation?: boolean; } @@ -4730,13 +4737,13 @@ namespace FourSlashInterface { readonly includes?: Many; readonly excludes?: Many; readonly preferences: ts.UserPreferences; - readonly triggerCharacter?: string; + readonly triggerCharacter?: ts.CompletionsTriggerCharacter; } export type Many = T | ReadonlyArray; export interface VerifyCompletionListContainsOptions extends ts.UserPreferences { - triggerCharacter?: string; + triggerCharacter?: ts.CompletionsTriggerCharacter; sourceDisplay: string; isRecommended?: true; insertText?: string; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 3eaa42bb103..289478e7453 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1765,6 +1765,8 @@ namespace ts.server.protocol { arguments: FormatOnKeyRequestArgs; } + export type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; + /** * Arguments for completions messages. */ @@ -1773,7 +1775,7 @@ namespace ts.server.protocol { * Optional prefix to apply to possible completions. */ prefix?: string; - triggerCharacter?: string; + triggerCharacter?: CompletionsTriggerCharacter; /** * @deprecated Use UserPreferences.includeCompletionsForModuleExports */ diff --git a/src/services/completions.ts b/src/services/completions.ts index ef1bd5ebd3c..4950d1370e1 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -25,7 +25,7 @@ namespace ts.Completions { const enum GlobalsSearch { Continue, Success, Fail } - export function getCompletionsAtPosition(host: LanguageServiceHost, program: Program, log: Log, sourceFile: SourceFile, position: number, preferences: UserPreferences, triggerCharacter: string | undefined): CompletionInfo | undefined { + export function getCompletionsAtPosition(host: LanguageServiceHost, program: Program, log: Log, sourceFile: SourceFile, position: number, preferences: UserPreferences, triggerCharacter: CompletionsTriggerCharacter | undefined): CompletionInfo | undefined { const typeChecker = program.getTypeChecker(); const compilerOptions = program.getCompilerOptions(); if (isInReferenceComment(sourceFile, position)) { @@ -2208,8 +2208,12 @@ namespace ts.Completions { return !!type.getStringIndexType() || !!type.getNumberIndexType(); } - function isValidTrigger(sourceFile: SourceFile, triggerCharacter: string, contextToken: Node, position: number): boolean { + function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node, position: number): boolean { switch (triggerCharacter) { + case ".": + case "/": + case "@": + return true; case '"': case "'": case "`": @@ -2219,7 +2223,7 @@ namespace ts.Completions { // Opening JSX tag return contextToken.kind === SyntaxKind.LessThanToken && contextToken.parent.kind !== SyntaxKind.BinaryExpression; default: - return Debug.fail(triggerCharacter); + return Debug.assertNever(triggerCharacter); } } diff --git a/src/services/types.ts b/src/services/types.ts index d71b315f29a..c103d2f4ba0 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -358,9 +358,11 @@ namespace ts { export type OrganizeImportsScope = CombinedCodeFixScope; + export type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; + export interface GetCompletionsAtPositionOptions extends UserPreferences { /** If the editor is asking for completions because a certain character was typed, and not because the user explicitly requested them, this should be set. */ - triggerCharacter?: string; + triggerCharacter?: CompletionsTriggerCharacter; /** @deprecated Use includeCompletionsForModuleExports */ includeExternalModuleExports?: boolean; /** @deprecated Use includeCompletionsWithInsertText */ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1e2d3bbc605..5f86c40a919 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4539,9 +4539,10 @@ declare namespace ts { fileName: string; } type OrganizeImportsScope = CombinedCodeFixScope; + type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; interface GetCompletionsAtPositionOptions extends UserPreferences { /** If the editor is asking for completions because a certain character was typed, and not because the user explicitly requested them, this should be set. */ - triggerCharacter?: string; + triggerCharacter?: CompletionsTriggerCharacter; /** @deprecated Use includeCompletionsForModuleExports */ includeExternalModuleExports?: boolean; /** @deprecated Use includeCompletionsWithInsertText */ @@ -6777,6 +6778,7 @@ declare namespace ts.server.protocol { command: CommandTypes.Formatonkey; arguments: FormatOnKeyRequestArgs; } + type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; /** * Arguments for completions messages. */ @@ -6785,7 +6787,7 @@ declare namespace ts.server.protocol { * Optional prefix to apply to possible completions. */ prefix?: string; - triggerCharacter?: string; + triggerCharacter?: CompletionsTriggerCharacter; /** * @deprecated Use UserPreferences.includeCompletionsForModuleExports */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b6dbb1d54dd..342d609d060 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4539,9 +4539,10 @@ declare namespace ts { fileName: string; } type OrganizeImportsScope = CombinedCodeFixScope; + type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; interface GetCompletionsAtPositionOptions extends UserPreferences { /** If the editor is asking for completions because a certain character was typed, and not because the user explicitly requested them, this should be set. */ - triggerCharacter?: string; + triggerCharacter?: CompletionsTriggerCharacter; /** @deprecated Use includeCompletionsForModuleExports */ includeExternalModuleExports?: boolean; /** @deprecated Use includeCompletionsWithInsertText */ From 8ab5be9a86b0838568916de8608ecd2af3999584 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 May 2018 11:20:48 -0700 Subject: [PATCH 45/64] Add hook for adding transforms into the declaration emit pipeline after the main one (#23946) * Add hook for adding transforms into the declaration emit pipeline after the main one * Fix lint --- src/compiler/emitter.ts | 4 ++-- src/compiler/program.ts | 4 +++- src/compiler/types.ts | 6 ++++-- src/harness/unittests/transform.ts | 20 +++++++++++++++++++ .../reference/api/tsserverlibrary.d.ts | 6 ++++-- tests/baselines/reference/api/typescript.d.ts | 6 ++++-- ...formsCorrectly.transformDeclarationFile.js | 1 + 7 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.transformDeclarationFile.js diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 20bc916faf4..b4ff2617a0d 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -95,7 +95,7 @@ namespace ts { /*@internal*/ // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature - export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[]): EmitResult { + export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory[], declarationTransformers?: TransformerFactory[]): EmitResult { const compilerOptions = host.getCompilerOptions(); const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; @@ -192,7 +192,7 @@ namespace ts { // Setup and perform the transformation to retrieve declarations from the input files const nonJsFiles = filter(sourceFiles, isSourceFileNotJavaScript); const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; - const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, [transformDeclarations], /*allowDtsFiles*/ false); + const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, concatenate([transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false); if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics) { emitterDiagnostics.add(diagnostic); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 3da1da2b018..d353aa6dae3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1296,7 +1296,9 @@ namespace ts { getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles, - transformers); + transformers, + customTransformers && customTransformers.afterDeclarations + ); performance.mark("afterEmit"); performance.measure("Emit", "beforeEmit", "afterEmit"); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 593e13a131f..4e879e035e2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2788,10 +2788,12 @@ namespace ts { } export interface CustomTransformers { - /** Custom transformers to evaluate before built-in transformations. */ + /** Custom transformers to evaluate before built-in .js transformations. */ before?: TransformerFactory[]; - /** Custom transformers to evaluate after built-in transformations. */ + /** Custom transformers to evaluate after built-in .js transformations. */ after?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .d.ts transformations. */ + afterDeclarations?: TransformerFactory[]; } export interface SourceMapSpan { diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 3cca8f6210c..14b9ccdbfb8 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -250,6 +250,26 @@ namespace ts { } } }); + + testBaseline("transformDeclarationFile", () => { + return baselineDeclarationTransform(`var oldName = undefined;`, { + transformers: { + afterDeclarations: [replaceIdentifiersNamedOldNameWithNewName] + }, + compilerOptions: { + newLine: NewLineKind.CarriageReturnLineFeed, + declaration: true + } + }); + }); + + function baselineDeclarationTransform(text: string, opts: TranspileOptions) { + const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true, { documents: [new documents.TextDocument("/.src/index.ts", text)] }); + const host = new fakes.CompilerHost(fs, opts.compilerOptions); + const program = createProgram(["/.src/index.ts"], opts.compilerOptions, host); + program.emit(program.getSourceFiles()[1], (p, s, bom) => host.writeFile(p, s, bom), /*cancellationToken*/ undefined, /*onlyDts*/ true, opts.transformers); + return fs.readFileSync("/.src/index.d.ts").toString(); + } }); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5f86c40a919..6f62203f0b7 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1735,10 +1735,12 @@ declare namespace ts { sourceFile: SourceFile; } interface CustomTransformers { - /** Custom transformers to evaluate before built-in transformations. */ + /** Custom transformers to evaluate before built-in .js transformations. */ before?: TransformerFactory[]; - /** Custom transformers to evaluate after built-in transformations. */ + /** Custom transformers to evaluate after built-in .js transformations. */ after?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .d.ts transformations. */ + afterDeclarations?: TransformerFactory[]; } interface SourceMapSpan { /** Line number in the .js file. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 342d609d060..d154440d0d9 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1735,10 +1735,12 @@ declare namespace ts { sourceFile: SourceFile; } interface CustomTransformers { - /** Custom transformers to evaluate before built-in transformations. */ + /** Custom transformers to evaluate before built-in .js transformations. */ before?: TransformerFactory[]; - /** Custom transformers to evaluate after built-in transformations. */ + /** Custom transformers to evaluate after built-in .js transformations. */ after?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .d.ts transformations. */ + afterDeclarations?: TransformerFactory[]; } interface SourceMapSpan { /** Line number in the .js file. */ diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.transformDeclarationFile.js b/tests/baselines/reference/transformApi/transformsCorrectly.transformDeclarationFile.js new file mode 100644 index 00000000000..18afd15ab56 --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.transformDeclarationFile.js @@ -0,0 +1 @@ +declare var newName: any; From ccfd3bf6038981cdc103c1a2c15f56096942341c Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 May 2018 11:23:01 -0700 Subject: [PATCH 46/64] Handle BindingElement in fixUnusedIdentifier (#23819) * Handle BindingElement in fixUnusedIdentifier * Add array destructure tests --- src/services/codefixes/fixUnusedIdentifier.ts | 15 ++++ src/services/formatting/smartIndenter.ts | 20 +++-- ...usedIdentifier_destructure_partlyUnused.ts | 75 +++++++++++++++++++ 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_destructure_partlyUnused.ts diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index fd360c73ea1..9cb1f457862 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -171,6 +171,21 @@ namespace ts.codefix { } break; + case SyntaxKind.BindingElement: { + const pattern = (parent as BindingElement).parent; + switch (pattern.kind) { + case SyntaxKind.ArrayBindingPattern: + changes.deleteNode(sourceFile, parent); // Don't delete ',' + break; + case SyntaxKind.ObjectBindingPattern: + changes.deleteNodeInList(sourceFile, parent); + break; + default: + return Debug.assertNever(pattern); + } + break; + } + // handle case where 'import a = A;' case SyntaxKind.ImportEqualsDeclaration: const importEquals = getAncestor(identifier, SyntaxKind.ImportEqualsDeclaration); diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index a82f11f239b..0e89be42532 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -327,9 +327,10 @@ namespace ts.formatting { export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray { if (node.parent) { + const { end } = node; switch (node.parent.kind) { case SyntaxKind.TypeReference: - return getListIfStartEndIsInListRange((node.parent).typeArguments, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeArguments, node.getStart(sourceFile), end); case SyntaxKind.ObjectLiteralExpression: return (node.parent).properties; case SyntaxKind.ArrayLiteralExpression: @@ -344,22 +345,25 @@ namespace ts.formatting { case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: { const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeParameters, start, node.getEnd()) || - getListIfStartEndIsInListRange((node.parent).parameters, start, node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeParameters, start, end) || + getListIfStartEndIsInListRange((node.parent).parameters, start, end); } case SyntaxKind.ClassDeclaration: - return getListIfStartEndIsInListRange((node.parent).typeParameters, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeParameters, node.getStart(sourceFile), end); case SyntaxKind.NewExpression: case SyntaxKind.CallExpression: { const start = node.getStart(sourceFile); - return getListIfStartEndIsInListRange((node.parent).typeArguments, start, node.getEnd()) || - getListIfStartEndIsInListRange((node.parent).arguments, start, node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).typeArguments, start, end) || + getListIfStartEndIsInListRange((node.parent).arguments, start, end); } case SyntaxKind.VariableDeclarationList: - return getListIfStartEndIsInListRange((node.parent).declarations, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).declarations, node.getStart(sourceFile), end); case SyntaxKind.NamedImports: case SyntaxKind.NamedExports: - return getListIfStartEndIsInListRange((node.parent).elements, node.getStart(sourceFile), node.getEnd()); + return getListIfStartEndIsInListRange((node.parent).elements, node.getStart(sourceFile), end); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return getListIfStartEndIsInListRange((node.parent).elements, node.getStart(sourceFile), end); } } return undefined; diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_partlyUnused.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_partlyUnused.ts new file mode 100644 index 00000000000..6ed5973d400 --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_partlyUnused.ts @@ -0,0 +1,75 @@ +/// + +// @noUnusedLocals: true + +////{ +//// const { x, y } = o; +//// x; +////} +////{ +//// const { x, y } = o; +//// y; +////} +////{ +//// const { x, y, z } = o; +//// y; +////} +////{ +//// const { x, y, z } = o; +//// x; z; +////} +////{ +//// const [x, y] = o; +//// x; +////} +////{ +//// const [x, y] = o; +//// y; +////} +////{ +//// const [x, y, z] = o; +//// y; +////} +////{ +//// const [x, y, z] = o; +//// x; z; +////} + + +verify.codeFixAll({ + fixId: "unusedIdentifier_delete", + fixAllDescription: "Delete all unused declarations", + newFileContent: +`{ + const { x } = o; + x; +} +{ + const { y } = o; + y; +} +{ + const { y } = o; + y; +} +{ + const { x, z } = o; + x; z; +} +{ + const [x,] = o; + x; +} +{ + const [, y] = o; + y; +} +{ + const [, y,] = o; + y; +} +{ + const [x,, z] = o; + x; z; +}`, +}); From 556c316fedee6b88b0b192f5c40db99f76577929 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 May 2018 12:46:33 -0700 Subject: [PATCH 47/64] Make new harness fake host more performant in large complications (#23951) * Make new harness fake host more performant in large complications * Use sortedmap --- src/compiler/core.ts | 1 + src/compiler/moduleNameResolver.ts | 7 ++++++- src/harness/fakes.ts | 14 ++++++-------- src/harness/utils.ts | 25 ------------------------- 4 files changed, 13 insertions(+), 34 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 20c3562271c..9cc7d0680e6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2227,6 +2227,7 @@ namespace ts { const reduced = [components[0]]; for (let i = 1; i < components.length; i++) { const component = components[i]; + if (!component) continue; if (component === ".") continue; if (component === "..") { if (reduced.length > 1) { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index ca282da18b8..8bb65e57616 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -119,7 +119,12 @@ namespace ts { export function readJson(path: string, host: { readFile(fileName: string): string | undefined }): object { try { const jsonText = host.readFile(path); - return jsonText ? JSON.parse(jsonText) : {}; + if (!jsonText) return {}; + const result = parseConfigFileTextToJson(path, jsonText); + if (result.error) { + return {}; + } + return result.config; } catch (e) { // gracefully handle if readFile fails or returns not JSON diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index 3e450f90d57..79d3503cb80 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -39,9 +39,7 @@ namespace fakes { public readFile(path: string) { try { const content = this.vfs.readFileSync(path, "utf8"); - return content === undefined ? undefined : - vpath.extname(path) === ".json" ? utils.removeComments(utils.removeByteOrderMark(content), utils.CommentRemoval.leadingAndTrailing) : - utils.removeByteOrderMark(content); + return content === undefined ? undefined : utils.removeByteOrderMark(content); } catch { return undefined; @@ -203,6 +201,7 @@ namespace fakes { public readonly sys: System; public readonly defaultLibLocation: string; public readonly outputs: documents.TextDocument[] = []; + private readonly _outputsMap: collections.SortedMap; public readonly traces: string[] = []; public readonly shouldAssertInvariants = !Harness.lightMode; @@ -218,6 +217,7 @@ namespace fakes { this._newLine = ts.getNewLineCharacter(options, () => this.sys.newLine); this._sourceFiles = new collections.SortedMap({ comparer: sys.vfs.stringComparer, sort: "insertion" }); this._setParentNodes = setParentNodes; + this._outputsMap = new collections.SortedMap(this.vfs.stringComparer); } public get vfs() { @@ -271,13 +271,11 @@ namespace fakes { const document = new documents.TextDocument(fileName, content); document.meta.set("fileName", fileName); this.vfs.filemeta(fileName).set("document", document); - const index = this.outputs.findIndex(output => this.vfs.stringComparer(document.file, output.file) === 0); - if (index < 0) { + if (!this._outputsMap.has(document.file)) { + this._outputsMap.set(document.file, this.outputs.length); this.outputs.push(document); } - else { - this.outputs[index] = document; - } + this.outputs[this._outputsMap.get(document.file)] = document; } public trace(s: string): void { diff --git a/src/harness/utils.ts b/src/harness/utils.ts index 03e9e56169b..83e51a065a0 100644 --- a/src/harness/utils.ts +++ b/src/harness/utils.ts @@ -2,31 +2,6 @@ * Common utilities */ namespace utils { - const leadingCommentRegExp = /^(\s*\/\*[^]*?\*\/\s*|\s*\/\/[^\r\n\u2028\u2029]*[\r\n\u2028\u2029]*)+/; - const trailingCommentRegExp = /(\s*\/\*[^]*?\*\/\s*|\s*\/\/[^\r\n\u2028\u2029]*[\r\n\u2028\u2029]*)+$/; - const leadingAndTrailingCommentRegExp = /^(\s*\/\*[^]*?\*\/\s*|\s*\/\/[^\r\n\u2028\u2029]*[\r\n\u2028\u2029]*)+|(\s*\/\*[^]*?\*\/\s*|\s*\/\/[^\r\n\u2028\u2029]*[\r\n\u2028\u2029]*)+$/g; - const allCommentRegExp = /(['"])(?:(?!\1).|\\[^])*\1|(\/\*[^]*?\*\/|\/\/[^\r\n\u2028\u2029]*[\r\n\u2028\u2029]*)/g; - - export const enum CommentRemoval { - leading, - trailing, - leadingAndTrailing, - all - } - - export function removeComments(text: string, removal: CommentRemoval) { - switch (removal) { - case CommentRemoval.leading: - return text.replace(leadingCommentRegExp, ""); - case CommentRemoval.trailing: - return text.replace(trailingCommentRegExp, ""); - case CommentRemoval.leadingAndTrailing: - return text.replace(leadingAndTrailingCommentRegExp, ""); - case CommentRemoval.all: - return text.replace(allCommentRegExp, (match, quote) => quote ? match : ""); - } - } - const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(ts|lib|src)\//g; export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean) { return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined; From 5725428f2d6a50e41477be22db5ed9bd07cd598e Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 May 2018 13:33:55 -0700 Subject: [PATCH 48/64] fixUnusedIdentifier: Handle destructure with all bindings unused (#23805) * fixUnusedIdentifier: Handle destructure with all bindings unused * Add parameters test * Add test for 'for' loop --- src/compiler/checker.ts | 145 ++++++++++-------- src/compiler/diagnosticMessages.json | 9 ++ src/services/codefixes/fixUnusedIdentifier.ts | 29 +++- .../reference/unusedDestructuring.errors.txt | 35 +++++ .../reference/unusedDestructuring.js | 26 ++++ .../reference/unusedDestructuring.symbols | 34 ++++ .../reference/unusedDestructuring.types | 34 ++++ .../unusedDestructuringParameters.errors.txt | 4 +- .../unusedLocalsAndObjectSpread.errors.txt | 8 +- .../unusedLocalsAndObjectSpread2.errors.txt | 8 +- .../unusedParametersWithUnderscore.errors.txt | 5 +- tests/cases/compiler/unusedDestructuring.ts | 13 ++ ...xUnusedIdentifier_destructure_allUnused.ts | 14 ++ ...sedIdentifier_destructure_allUnused_all.ts | 22 +++ ...sedIdentifier_destructure_allUnused_for.ts | 12 ++ ...Identifier_destructure_allUnused_nested.ts | 14 ++ 16 files changed, 332 insertions(+), 80 deletions(-) create mode 100644 tests/baselines/reference/unusedDestructuring.errors.txt create mode 100644 tests/baselines/reference/unusedDestructuring.js create mode 100644 tests/baselines/reference/unusedDestructuring.symbols create mode 100644 tests/baselines/reference/unusedDestructuring.types create mode 100644 tests/cases/compiler/unusedDestructuring.ts create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused.ts create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_all.ts create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_for.ts create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_nested.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce0db1f91dc..a368a6a8f64 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22352,10 +22352,6 @@ namespace ts { function checkUnusedIdentifiers(potentiallyUnusedIdentifiers: ReadonlyArray, addDiagnostic: AddUnusedDiagnostic) { for (const node of potentiallyUnusedIdentifiers) { switch (node.kind) { - case SyntaxKind.SourceFile: - case SyntaxKind.ModuleDeclaration: - checkUnusedModuleMembers(node, addDiagnostic); - break; case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: checkUnusedClassMembers(node, addDiagnostic); @@ -22364,6 +22360,8 @@ namespace ts { case SyntaxKind.InterfaceDeclaration: checkUnusedTypeParameters(node, addDiagnostic); break; + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: case SyntaxKind.Block: case SyntaxKind.CaseBlock: case SyntaxKind.ForStatement: @@ -22397,35 +22395,6 @@ namespace ts { } } - function checkUnusedLocalsAndParameters(node: Node, addDiagnostic: AddUnusedDiagnostic): void { - if (!(node.flags & NodeFlags.Ambient)) { - node.locals.forEach(local => { - // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. - // If it's a type parameter merged with a parameter, check if the parameter-side is used. - if (local.flags & SymbolFlags.TypeParameter ? (local.flags & SymbolFlags.Variable && !(local.isReferenced & SymbolFlags.Variable)) : !local.isReferenced) { - if (local.valueDeclaration && getRootDeclaration(local.valueDeclaration).kind === SyntaxKind.Parameter) { - const parameter = getRootDeclaration(local.valueDeclaration); - const name = getNameOfDeclaration(local.valueDeclaration); - if (!isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { - addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local))); - } - } - else { - forEach(local.declarations, d => errorUnusedLocal(d, symbolName(local), addDiagnostic)); - } - } - }); - } - } - - function isRemovedPropertyFromObjectSpread(node: Node) { - if (isBindingElement(node) && isObjectBindingPattern(node.parent)) { - const lastElement = lastOrUndefined(node.parent.elements); - return lastElement !== node && !!lastElement.dotDotDotToken; - } - return false; - } - function errorUnusedLocal(declaration: Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) { const node = getNameOfDeclaration(declaration) || declaration; if (isIdentifierThatStartsWithUnderScore(node)) { @@ -22436,10 +22405,8 @@ namespace ts { } } - if (!isRemovedPropertyFromObjectSpread(node.kind === SyntaxKind.Identifier ? node.parent : node)) { - const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read; - addDiagnostic(UnusedKind.Local, createDiagnosticForNodeSpan(getSourceFileOfNode(declaration), declaration, node, message, name)); - } + const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read; + addDiagnostic(UnusedKind.Local, createDiagnosticForNodeSpan(getSourceFileOfNode(declaration), declaration, node, message, name)); } function parameterNameStartsWithUnderscore(parameterName: DeclarationName) { @@ -22501,44 +22468,86 @@ namespace ts { } } - function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile, addDiagnostic: AddUnusedDiagnostic): void { - if (!(node.flags & NodeFlags.Ambient)) { - // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. - const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>(); - node.locals.forEach(local => { - if (local.isReferenced || local.exportSymbol) return; - for (const declaration of local.declarations) { - if (isAmbientModule(declaration)) continue; - if (isImportedDeclaration(declaration)) { - const importClause = importClauseFromImported(declaration); - const key = String(getNodeId(importClause)); - const group = unusedImports.get(key); - if (group) { - group[1].push(declaration); - } - else { - unusedImports.set(key, [importClause, [declaration]]); + function addToGroup(map: Map<[K, V[]]>, key: K, value: V, getKey: (key: K) => number | string): void { + const keyString = String(getKey(key)); + const group = map.get(keyString); + if (group) { + group[1].push(value); + } + else { + map.set(keyString, [key, [value]]); + } + } + + function tryGetRootParameterDeclaration(node: Node): ParameterDeclaration | undefined { + return tryCast(getRootDeclaration(node), isParameter); + } + + function checkUnusedLocalsAndParameters(nodeWithLocals: Node, addDiagnostic: AddUnusedDiagnostic): void { + if (nodeWithLocals.flags & NodeFlags.Ambient) return; + + // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. + const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>(); + const unusedDestructures = createMap<[ObjectBindingPattern, BindingElement[]]>(); + nodeWithLocals.locals.forEach(local => { + // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. + // If it's a type parameter merged with a parameter, check if the parameter-side is used. + if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { + return; + } + + for (const declaration of local.declarations) { + if (isAmbientModule(declaration)) continue; + if (isImportedDeclaration(declaration)) { + addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId); + } + else if (isBindingElement(declaration) && isObjectBindingPattern(declaration.parent)) { + // In `{ a, ...b }, `a` is considered used since it removes a property from `b`. `b` may still be unused though. + const lastElement = last(declaration.parent.elements); + if (declaration === lastElement || !last(declaration.parent.elements).dotDotDotToken) { + addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); + } + } + else { + const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); + if (parameter) { + const name = getNameOfDeclaration(local.valueDeclaration); + if (!isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { + addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local))); } } else { errorUnusedLocal(declaration, symbolName(local), addDiagnostic); } } - }); - - unusedImports.forEach(([importClause, unuseds]) => { - const importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, d => !contains(unuseds, d))) { - for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name), addDiagnostic); + } + }); + unusedImports.forEach(([importClause, unuseds]) => { + const importDecl = importClause.parent; + if (forEachImportedDeclaration(importClause, d => !contains(unuseds, d))) { + for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name), addDiagnostic); + } + else if (unuseds.length === 1) { + addDiagnostic(UnusedKind.Local, createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name))); + } + else { + addDiagnostic(UnusedKind.Local, createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused)); + } + }); + unusedDestructures.forEach(([bindingPattern, bindingElements]) => { + const kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? UnusedKind.Parameter : UnusedKind.Local; + if (!bindingPattern.elements.every(e => contains(bindingElements, e))) { + for (const e of bindingElements) { + addDiagnostic(kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, getBindingElementNameText(e))); } - else if (unuseds.length === 1) { - addDiagnostic(UnusedKind.Local, createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name))); - } - else { - addDiagnostic(UnusedKind.Local, createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused, showModuleSpecifier(importDecl))); - } - }); - } + } + else if (bindingElements.length === 1) { + addDiagnostic(kind, createDiagnosticForNode(bindingPattern, Diagnostics._0_is_declared_but_its_value_is_never_read, getBindingElementNameText(first(bindingElements)))); + } + else { + addDiagnostic(kind, createDiagnosticForNode(bindingPattern, Diagnostics.All_destructured_elements_are_unused)); + } + }); } type ImportedDeclaration = ImportClause | ImportSpecifier | NamespaceImport; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1e101ce6e76..f96c950d8a9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3551,6 +3551,11 @@ "category": "Message", "code": 6197 }, + "All destructured elements are unused.": { + "category": "Error", + "code": 6198, + "reportsUnnecessary": true + }, "Projects to reference": { "category": "Message", @@ -3985,6 +3990,10 @@ "category": "Message", "code": 90008 }, + "Remove destructuring": { + "category": "Message", + "code": 90009 + }, "Import '{0}' from module \"{1}\"": { "category": "Message", "code": 90013 diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index 9cb1f457862..5b411bedde4 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -8,6 +8,7 @@ namespace ts.codefix { Diagnostics._0_is_declared_but_never_used.code, Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code, Diagnostics.All_imports_in_import_declaration_are_unused.code, + Diagnostics.All_destructured_elements_are_unused.code, ]; registerCodeFix({ errorCodes, @@ -18,6 +19,10 @@ namespace ts.codefix { const changes = textChanges.ChangeTracker.with(context, t => t.deleteNode(sourceFile, importDecl)); return [createCodeFixAction(fixName, changes, [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)], fixIdDelete, Diagnostics.Delete_all_unused_declarations)]; } + const delDestructure = textChanges.ChangeTracker.with(context, t => tryDeleteFullDestructure(t, sourceFile, context.span.start)); + if (delDestructure.length) { + return [createCodeFixAction(fixName, delDestructure, Diagnostics.Remove_destructuring, fixIdDelete, Diagnostics.Delete_all_unused_declarations)]; + } const token = getToken(sourceFile, textSpanEnd(context.span)); const result: CodeFixAction[] = []; @@ -50,7 +55,9 @@ namespace ts.codefix { changes.deleteNode(sourceFile, importDecl); } else { - tryDeleteDeclaration(changes, sourceFile, token); + if (!tryDeleteFullDestructure(changes, sourceFile, diag.start!)) { + tryDeleteDeclaration(changes, sourceFile, token); + } } break; default: @@ -65,6 +72,26 @@ namespace ts.codefix { return startToken.kind === SyntaxKind.ImportKeyword ? tryCast(startToken.parent, isImportDeclaration) : undefined; } + function tryDeleteFullDestructure(changes: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number): boolean { + const startToken = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + if (startToken.kind !== SyntaxKind.OpenBraceToken || !isObjectBindingPattern(startToken.parent)) return false; + const decl = startToken.parent.parent; + switch (decl.kind) { + case SyntaxKind.VariableDeclaration: + tryDeleteVariableDeclaration(changes, sourceFile, decl); + break; + case SyntaxKind.Parameter: + changes.deleteNodeInList(sourceFile, decl); + break; + case SyntaxKind.BindingElement: + changes.deleteNode(sourceFile, decl); + break; + default: + return Debug.assertNever(decl); + } + return true; + } + function getToken(sourceFile: SourceFile, pos: number): Node { const token = findPrecedingToken(pos, sourceFile); // this handles var ["computed"] = 12; diff --git a/tests/baselines/reference/unusedDestructuring.errors.txt b/tests/baselines/reference/unusedDestructuring.errors.txt new file mode 100644 index 00000000000..6f6bb82d9d0 --- /dev/null +++ b/tests/baselines/reference/unusedDestructuring.errors.txt @@ -0,0 +1,35 @@ +tests/cases/compiler/unusedDestructuring.ts(3,7): error TS6198: All destructured elements are unused. +tests/cases/compiler/unusedDestructuring.ts(4,9): error TS6133: 'c' is declared but its value is never read. +tests/cases/compiler/unusedDestructuring.ts(6,7): error TS6133: 'e' is declared but its value is never read. +tests/cases/compiler/unusedDestructuring.ts(8,1): error TS6133: 'f' is declared but its value is never read. +tests/cases/compiler/unusedDestructuring.ts(8,12): error TS6198: All destructured elements are unused. +tests/cases/compiler/unusedDestructuring.ts(8,24): error TS6133: 'c' is declared but its value is never read. +tests/cases/compiler/unusedDestructuring.ts(8,32): error TS6133: 'e' is declared but its value is never read. + + +==== tests/cases/compiler/unusedDestructuring.ts (7 errors) ==== + export {}; + declare const o: any; + const { a, b } = o; + ~~~~~~~~ +!!! error TS6198: All destructured elements are unused. + const { c, d } = o; + ~ +!!! error TS6133: 'c' is declared but its value is never read. + d; + const { e } = o; + ~~~~~ +!!! error TS6133: 'e' is declared but its value is never read. + + function f({ a, b }, { c, d }, { e }) { + ~~~~~~~~~~ +!!! error TS6133: 'f' is declared but its value is never read. + ~~~~~~~~ +!!! error TS6198: All destructured elements are unused. + ~ +!!! error TS6133: 'c' is declared but its value is never read. + ~~~~~ +!!! error TS6133: 'e' is declared but its value is never read. + d; + } + \ No newline at end of file diff --git a/tests/baselines/reference/unusedDestructuring.js b/tests/baselines/reference/unusedDestructuring.js new file mode 100644 index 00000000000..d025b226542 --- /dev/null +++ b/tests/baselines/reference/unusedDestructuring.js @@ -0,0 +1,26 @@ +//// [unusedDestructuring.ts] +export {}; +declare const o: any; +const { a, b } = o; +const { c, d } = o; +d; +const { e } = o; + +function f({ a, b }, { c, d }, { e }) { + d; +} + + +//// [unusedDestructuring.js] +"use strict"; +exports.__esModule = true; +var a = o.a, b = o.b; +var c = o.c, d = o.d; +d; +var e = o.e; +function f(_a, _b, _c) { + var a = _a.a, b = _a.b; + var c = _b.c, d = _b.d; + var e = _c.e; + d; +} diff --git a/tests/baselines/reference/unusedDestructuring.symbols b/tests/baselines/reference/unusedDestructuring.symbols new file mode 100644 index 00000000000..0490774919b --- /dev/null +++ b/tests/baselines/reference/unusedDestructuring.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/unusedDestructuring.ts === +export {}; +declare const o: any; +>o : Symbol(o, Decl(unusedDestructuring.ts, 1, 13)) + +const { a, b } = o; +>a : Symbol(a, Decl(unusedDestructuring.ts, 2, 7)) +>b : Symbol(b, Decl(unusedDestructuring.ts, 2, 10)) +>o : Symbol(o, Decl(unusedDestructuring.ts, 1, 13)) + +const { c, d } = o; +>c : Symbol(c, Decl(unusedDestructuring.ts, 3, 7)) +>d : Symbol(d, Decl(unusedDestructuring.ts, 3, 10)) +>o : Symbol(o, Decl(unusedDestructuring.ts, 1, 13)) + +d; +>d : Symbol(d, Decl(unusedDestructuring.ts, 3, 10)) + +const { e } = o; +>e : Symbol(e, Decl(unusedDestructuring.ts, 5, 7)) +>o : Symbol(o, Decl(unusedDestructuring.ts, 1, 13)) + +function f({ a, b }, { c, d }, { e }) { +>f : Symbol(f, Decl(unusedDestructuring.ts, 5, 16)) +>a : Symbol(a, Decl(unusedDestructuring.ts, 7, 12)) +>b : Symbol(b, Decl(unusedDestructuring.ts, 7, 15)) +>c : Symbol(c, Decl(unusedDestructuring.ts, 7, 22)) +>d : Symbol(d, Decl(unusedDestructuring.ts, 7, 25)) +>e : Symbol(e, Decl(unusedDestructuring.ts, 7, 32)) + + d; +>d : Symbol(d, Decl(unusedDestructuring.ts, 7, 25)) +} + diff --git a/tests/baselines/reference/unusedDestructuring.types b/tests/baselines/reference/unusedDestructuring.types new file mode 100644 index 00000000000..605f08c3bbd --- /dev/null +++ b/tests/baselines/reference/unusedDestructuring.types @@ -0,0 +1,34 @@ +=== tests/cases/compiler/unusedDestructuring.ts === +export {}; +declare const o: any; +>o : any + +const { a, b } = o; +>a : any +>b : any +>o : any + +const { c, d } = o; +>c : any +>d : any +>o : any + +d; +>d : any + +const { e } = o; +>e : any +>o : any + +function f({ a, b }, { c, d }, { e }) { +>f : ({ a, b }: { a: any; b: any; }, { c, d }: { c: any; d: any; }, { e }: { e: any; }) => void +>a : any +>b : any +>c : any +>d : any +>e : any + + d; +>d : any +} + diff --git a/tests/baselines/reference/unusedDestructuringParameters.errors.txt b/tests/baselines/reference/unusedDestructuringParameters.errors.txt index 24a7b3838cd..a9423145cbe 100644 --- a/tests/baselines/reference/unusedDestructuringParameters.errors.txt +++ b/tests/baselines/reference/unusedDestructuringParameters.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/unusedDestructuringParameters.ts(1,13): error TS6133: 'a' is declared but its value is never read. -tests/cases/compiler/unusedDestructuringParameters.ts(3,14): error TS6133: 'a' is declared but its value is never read. +tests/cases/compiler/unusedDestructuringParameters.ts(3,13): error TS6133: 'a' is declared but its value is never read. ==== tests/cases/compiler/unusedDestructuringParameters.ts (2 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/unusedDestructuringParameters.ts(3,14): error TS6133: 'a' i !!! error TS6133: 'a' is declared but its value is never read. f([1]); const f2 = ({a}) => { }; - ~ + ~~~ !!! error TS6133: 'a' is declared but its value is never read. f2({ a: 10 }); const f3 = ([_]) => { }; diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt index e590de2989c..c3f89f32488 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/unusedLocalsAndObjectSpread.ts(20,15): error TS6133: 'bar' is declared but its value is never read. -tests/cases/compiler/unusedLocalsAndObjectSpread.ts(27,18): error TS6133: 'bar' is declared but its value is never read. +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(20,18): error TS6133: 'bar' is declared but its value is never read. +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(27,21): error TS6133: 'bar' is declared but its value is never read. ==== tests/cases/compiler/unusedLocalsAndObjectSpread.ts (2 errors) ==== @@ -23,7 +23,7 @@ tests/cases/compiler/unusedLocalsAndObjectSpread.ts(27,18): error TS6133: 'bar' const foo = { a: 1, b: 2 }; // 'a' is declared but never used const {a, ...bar} = foo; // bar should be unused - ~~~~~~ + ~~~ !!! error TS6133: 'bar' is declared but its value is never read. //console.log(bar); } @@ -32,7 +32,7 @@ tests/cases/compiler/unusedLocalsAndObjectSpread.ts(27,18): error TS6133: 'bar' const foo = { a: 1, b: 2 }; // '_' is declared but never used const {a: _, ...bar} = foo; // bar should be unused - ~~~~~~ + ~~~ !!! error TS6133: 'bar' is declared but its value is never read. //console.log(bar); } diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread2.errors.txt b/tests/baselines/reference/unusedLocalsAndObjectSpread2.errors.txt index b980b86a61d..100f86468ad 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread2.errors.txt +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread2.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(5,3): error TS6133: 'rest' is declared but its value is never read. +tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(5,6): error TS6133: 'rest' is declared but its value is never read. tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(8,1): error TS6133: 'foo' is declared but its value is never read. -tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(12,9): error TS6133: 'rest' is declared but its value is never read. +tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(12,12): error TS6133: 'rest' is declared but its value is never read. ==== tests/cases/compiler/unusedLocalsAndObjectSpread2.ts (3 errors) ==== @@ -9,7 +9,7 @@ tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(12,9): error TS6133: 'rest' children, // here! active: _a, // here! ...rest - ~~~~~~~ + ~~~~ !!! error TS6133: 'rest' is declared but its value is never read. } = props; @@ -20,7 +20,7 @@ tests/cases/compiler/unusedLocalsAndObjectSpread2.ts(12,9): error TS6133: 'rest' children, active: _a, ...rest - ~~~~~~~ + ~~~~ !!! error TS6133: 'rest' is declared but its value is never read. } = props; } diff --git a/tests/baselines/reference/unusedParametersWithUnderscore.errors.txt b/tests/baselines/reference/unusedParametersWithUnderscore.errors.txt index 841e8ec95fd..60213c2227d 100644 --- a/tests/baselines/reference/unusedParametersWithUnderscore.errors.txt +++ b/tests/baselines/reference/unusedParametersWithUnderscore.errors.txt @@ -2,11 +2,12 @@ tests/cases/compiler/unusedParametersWithUnderscore.ts(1,12): error TS6133: 'a' tests/cases/compiler/unusedParametersWithUnderscore.ts(1,19): error TS6133: 'c' is declared but its value is never read. tests/cases/compiler/unusedParametersWithUnderscore.ts(1,27): error TS6133: 'd' is declared but its value is never read. tests/cases/compiler/unusedParametersWithUnderscore.ts(1,29): error TS6133: 'e___' is declared but its value is never read. +tests/cases/compiler/unusedParametersWithUnderscore.ts(5,13): error TS6198: All destructured elements are unused. tests/cases/compiler/unusedParametersWithUnderscore.ts(11,16): error TS6133: 'arg' is declared but its value is never read. tests/cases/compiler/unusedParametersWithUnderscore.ts(17,13): error TS6133: 'arg' is declared but its value is never read. -==== tests/cases/compiler/unusedParametersWithUnderscore.ts (6 errors) ==== +==== tests/cases/compiler/unusedParametersWithUnderscore.ts (7 errors) ==== function f(a, _b, c, ___, d,e___, _f) { ~ !!! error TS6133: 'a' is declared but its value is never read. @@ -20,6 +21,8 @@ tests/cases/compiler/unusedParametersWithUnderscore.ts(17,13): error TS6133: 'ar function f2({_a, __b}) { + ~~~~~~~~~ +!!! error TS6198: All destructured elements are unused. } function f3([_a, ,__b]) { diff --git a/tests/cases/compiler/unusedDestructuring.ts b/tests/cases/compiler/unusedDestructuring.ts new file mode 100644 index 00000000000..9e2bb443ade --- /dev/null +++ b/tests/cases/compiler/unusedDestructuring.ts @@ -0,0 +1,13 @@ +// @noUnusedLocals: true +// @noUnusedParameters: true + +export {}; +declare const o: any; +const { a, b } = o; +const { c, d } = o; +d; +const { e } = o; + +function f({ a, b }, { c, d }, { e }) { + d; +} diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused.ts new file mode 100644 index 00000000000..4f3f9a3e61e --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused.ts @@ -0,0 +1,14 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true + +////export {}; +////const { x, y } = o; + +verify.codeFix({ + description: "Remove destructuring", + newFileContent: +`export {}; +`, +}); diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_all.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_all.ts new file mode 100644 index 00000000000..af27091788d --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_all.ts @@ -0,0 +1,22 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true + +////const { x, y } = o; +////const { a, b } = o; +////a; +////export function f({ x, y }, { a, b }) { +//// a; +////} + +verify.codeFixAll({ + fixId: "unusedIdentifier_delete", + fixAllDescription: "Delete all unused declarations", + newFileContent: +`const { a } = o; +a; +export function f({ a }) { + a; +}`, +}); diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_for.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_for.ts new file mode 100644 index 00000000000..27103357d3d --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_for.ts @@ -0,0 +1,12 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true + +////for (const { x } of o) {} + +verify.codeFix({ + description: "Remove destructuring", + newFileContent: +`for (const {} of o) {}`, +}); diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_nested.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_nested.ts new file mode 100644 index 00000000000..73fca113928 --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_destructure_allUnused_nested.ts @@ -0,0 +1,14 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true + +////export {}; +////const { x: { a, b } } = o; + +verify.codeFix({ + description: "Remove destructuring", + newFileContent: +`export {}; +const { } = o;`, +}); From 211b09b46c9746519e6c918cb88e1497e03cad1f Mon Sep 17 00:00:00 2001 From: Alex Ryan Date: Tue, 8 May 2018 14:20:26 -0700 Subject: [PATCH 49/64] Fix typo in parser.ts --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4b55bba412c..ad3f80710db 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3572,7 +3572,7 @@ namespace ts { // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] if (token() === SyntaxKind.AsyncKeyword) { nextToken(); - // If the "async" is followed by "=>" token then it is not a begining of an async arrow-function + // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher" if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) { return Tristate.False; From 4fb2add9a139926870c3b9c5acc831b76ad20de9 Mon Sep 17 00:00:00 2001 From: Alex Ryan Date: Tue, 8 May 2018 14:27:40 -0700 Subject: [PATCH 50/64] Fix comment typo in resolutionCache.ts Another comment-only fix. --- src/compiler/resolutionCache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index d94bc6d4ae7..9e0f3712ab9 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -539,7 +539,7 @@ namespace ts { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { - // Since the file existance changed, update the sourceFiles cache + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } @@ -690,7 +690,7 @@ namespace ts { return resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { - // Since the file existance changed, update the sourceFiles cache + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } From 01351d43e4bfc6474e04534d3a467dfbc75e4b6c Mon Sep 17 00:00:00 2001 From: Alex Ryan Date: Tue, 8 May 2018 14:36:32 -0700 Subject: [PATCH 51/64] Fix comment typo in program.ts --- src/compiler/program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d353aa6dae3..365e948f749 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -783,7 +783,7 @@ namespace ts { // We only set `file.resolvedModules` via work from the current function, // so it is defined iff we already called the current function on `file`. // That call happened no later than the creation of the `file` object, - // which per above occured during the current program creation. + // which per above occurred during the current program creation. // Since we assume the filesystem does not change during program creation, // it is safe to reuse resolutions from the earlier call. const result: ResolvedModuleFull[] = []; From f9bd3afb8fe6436d48bb03f1be5fa96e695df55f Mon Sep 17 00:00:00 2001 From: Alex Ryan Date: Tue, 8 May 2018 14:51:49 -0700 Subject: [PATCH 52/64] Fix comment typo in types.ts --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4e879e035e2..1ac84792152 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1879,7 +1879,7 @@ namespace ts { } /** - * A list of comma-seperated expressions. This node is only created by transformations. + * A list of comma-separated expressions. This node is only created by transformations. */ export interface CommaListExpression extends Expression { kind: SyntaxKind.CommaListExpression; From 4cc345e4e0684a3f59e17232c7ddd313f3997429 Mon Sep 17 00:00:00 2001 From: Alex Ryan Date: Tue, 8 May 2018 14:58:18 -0700 Subject: [PATCH 53/64] Fix comment typos in utilities.ts --- src/services/utilities.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index d5694c936de..3d50ded1886 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -940,22 +940,22 @@ namespace ts { break; case SyntaxKind.CloseBraceToken: - // This can be object type, skip untill we find the matching open brace token - // Skip untill the matching open brace token + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token token = findPrecedingMatchingToken(token, SyntaxKind.OpenBraceToken, sourceFile); if (!token) return false; break; case SyntaxKind.CloseParenToken: - // This can be object type, skip untill we find the matching open brace token - // Skip untill the matching open brace token + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token token = findPrecedingMatchingToken(token, SyntaxKind.OpenParenToken, sourceFile); if (!token) return false; break; case SyntaxKind.CloseBracketToken: - // This can be object type, skip untill we find the matching open brace token - // Skip untill the matching open brace token + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token token = findPrecedingMatchingToken(token, SyntaxKind.OpenBracketToken, sourceFile); if (!token) return false; break; From ea953b5dd084516b83f0b6e94a04d07907292c11 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 8 May 2018 15:05:11 -0700 Subject: [PATCH 54/64] Reduce number of 'caught exceptions' raised by vfs --- src/harness/vfs.ts | 67 +++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/harness/vfs.ts b/src/harness/vfs.ts index 698c8abd477..4972dd08925 100644 --- a/src/harness/vfs.ts +++ b/src/harness/vfs.ts @@ -332,35 +332,20 @@ namespace vfs { } } - private _depth: string[] = []; - /** * Make a directory and all of its parent paths (if they don't exist). */ public mkdirpSync(path: string) { - try { - this._depth.push(path); - path = this._resolve(path); - this.mkdirSync(path); - } - catch (e) { - if (e.code === "ENOENT") { - if (this._depth.length > 10) { - console.log(`path: ${path}`); - console.log(`dirname: ${vpath.dirname(path)}`); - console.log(this._depth); - throw e; - } - this.mkdirpSync(vpath.dirname(path)); - this.mkdirSync(path); + path = this._resolve(path); + const result = this._walk(path, /*noFollow*/ true, (error, result) => { + if (error.code === "ENOENT") { + this._mkdir(result); + return "retry"; } - else if (e.code !== "EEXIST") { - throw e; - } - } - finally { - this._depth.pop(); - } + return "throw"; + }); + + if (!result.node) this._mkdir(result); } /** @@ -464,9 +449,11 @@ namespace vfs { public mkdirSync(path: string) { if (this.isReadonly) throw createIOError("EROFS"); - const { parent, links, node: existingNode, basename } = this._walk(this._resolve(path), /*noFollow*/ true); - if (existingNode) throw createIOError("EEXIST"); + this._mkdir(this._walk(this._resolve(path), /*noFollow*/ true)); + } + private _mkdir({ parent, links, node: existingNode, basename }: WalkResult) { + if (existingNode) throw createIOError("EEXIST"); const time = this.time(); const node = this._mknod(parent ? parent.dev : ++devCount, S_IFDIR, /*mode*/ 0o777, time); this._addLink(parent, links, basename, node, time); @@ -810,17 +797,18 @@ namespace vfs { * @param path The path to follow. * @param noFollow A value indicating whether to *not* dereference a symbolic link at the * end of a path. - * @param allowPartial A value indicating whether to return a partial result if the node - * at the end of the path cannot be found. * * @link http://man7.org/linux/man-pages/man7/path_resolution.7.html */ - private _walk(path: string, noFollow?: boolean): WalkResult { + private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "retry" | "throw"): WalkResult; + private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw"): WalkResult | undefined; + private _walk(path: string, noFollow?: boolean, onError?: (error: NodeJS.ErrnoException, fragment: WalkResult) => "stop" | "retry" | "throw"): WalkResult | undefined { let links = this._getRootLinks(); let parent: DirectoryInode | undefined; let components = vpath.parse(path); let step = 0; let depth = 0; + let retry = false; while (true) { if (depth >= 40) throw createIOError("ELOOP"); const lastStep = step === components.length - 1; @@ -830,7 +818,8 @@ namespace vfs { return { realpath: vpath.format(components), basename, parent, links, node }; } if (node === undefined) { - throw createIOError("ENOENT"); + if (trapError(createIOError("ENOENT"), node)) continue; + return undefined; } if (isSymlink(node)) { const dirname = vpath.format(components.slice(0, step)); @@ -840,15 +829,30 @@ namespace vfs { components = vpath.parse(symlink).concat(components.slice(step + 1)); step = 0; depth++; + retry = false; continue; } if (isDirectory(node)) { links = this._getLinks(node); parent = node; step++; + retry = false; continue; } - throw createIOError("ENOTDIR"); + if (trapError(createIOError("ENOTDIR"), node)) continue; + return undefined; + } + + function trapError(error: NodeJS.ErrnoException, node?: Inode) { + const realpath = vpath.format(components.slice(0, step + 1)); + const basename = components[step]; + const result = !retry && onError ? onError(error, { realpath, basename, parent, links, node }) : "throw"; + if (result === "stop") return false; + if (result === "retry") { + retry = true; + return true; + } + throw error; } } @@ -1118,6 +1122,7 @@ namespace vfs { export function createIOError(code: keyof typeof IOErrorMessages) { const err: NodeJS.ErrnoException = new Error(`${code}: ${IOErrorMessages[code]}`); err.code = code; + if (Error.captureStackTrace) Error.captureStackTrace(err, createIOError); return err; } From 01ae7f1798fa6437b54d895f7625420dd99a0af4 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 8 May 2018 15:07:55 -0700 Subject: [PATCH 55/64] Rename test (#23978) --- ...ule_foo.ts => refactorConvertToEs6Module_exportEqualsClass.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/cases/fourslash/{refactorConvertToEs6Module_foo.ts => refactorConvertToEs6Module_exportEqualsClass.ts} (100%) diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_foo.ts b/tests/cases/fourslash/refactorConvertToEs6Module_exportEqualsClass.ts similarity index 100% rename from tests/cases/fourslash/refactorConvertToEs6Module_foo.ts rename to tests/cases/fourslash/refactorConvertToEs6Module_exportEqualsClass.ts From 1d7dc6aeb835fa8fabe8b0cfc6cc4365b9722a1a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 May 2018 15:49:35 -0700 Subject: [PATCH 56/64] Accept typo fix (#23983) --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 6f62203f0b7..f6bc5e75781 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1152,7 +1152,7 @@ declare namespace ts { kind: SyntaxKind.NotEmittedStatement; } /** - * A list of comma-seperated expressions. This node is only created by transformations. + * A list of comma-separated expressions. This node is only created by transformations. */ interface CommaListExpression extends Expression { kind: SyntaxKind.CommaListExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index d154440d0d9..de20defcdcb 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1152,7 +1152,7 @@ declare namespace ts { kind: SyntaxKind.NotEmittedStatement; } /** - * A list of comma-seperated expressions. This node is only created by transformations. + * A list of comma-separated expressions. This node is only created by transformations. */ interface CommaListExpression extends Expression { kind: SyntaxKind.CommaListExpression; From cb42086babf7020a826f3f2c6ad818e2888b812a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 8 May 2018 17:07:54 -0700 Subject: [PATCH 57/64] Fix RWC tsconfig and lib paths (#23979) * Fix RWC tsconfig paths * Fix lints * move helper from utils into vpath --- src/harness/compiler.ts | 3 +- src/harness/rwcRunner.ts | 74 +++++++++++++++------------------------- src/harness/vpath.ts | 4 +++ 3 files changed, 32 insertions(+), 49 deletions(-) diff --git a/src/harness/compiler.ts b/src/harness/compiler.ts index 59d636303f9..2900c8edbc8 100644 --- a/src/harness/compiler.ts +++ b/src/harness/compiler.ts @@ -10,8 +10,7 @@ namespace compiler { export function readProject(host: fakes.ParseConfigHost, project: string | undefined, existingOptions?: ts.CompilerOptions): Project | undefined { if (project) { - project = host.vfs.stringComparer(vpath.basename(project), "tsconfig.json") === 0 ? project : - vpath.combine(project, "tsconfig.json"); + project = vpath.isTsConfigFile(project) ? project : vpath.combine(project, "tsconfig.json"); } else { [project] = host.vfs.scanSync(".", "ancestors-or-self", { diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index bfd0153466c..cc1e5466115 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -21,10 +21,6 @@ namespace RWC { } } - function isTsConfigFile(file: { path: string }): boolean { - return file.path.indexOf("tsconfig") !== -1 && file.path.indexOf("json") !== -1; - } - export function runRWCTest(jsonPath: string) { describe("Testing a rwc project: " + jsonPath, () => { let inputFiles: Harness.Compiler.TestFile[] = []; @@ -69,11 +65,10 @@ namespace RWC { // we will set noEmitOnError flag to be false. opts.options.noEmitOnError = false; }); + let fileNames = opts.fileNames; - runWithIOLog(ioLog, oldIO => { - let fileNames = opts.fileNames; - - const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined); + runWithIOLog(ioLog, () => { + const tsconfigFile = ts.forEach(ioLog.filesRead, f => vpath.isTsConfigFile(f.path) ? f : undefined); if (tsconfigFile) { const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path); tsconfigFiles.push({ unitName: tsconfigFile.path, content: tsconfigFileContents.content }); @@ -103,55 +98,40 @@ namespace RWC { } // Add files to compilation - const isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath; for (const fileRead of ioLog.filesRead) { - // Check if the file is already added into the set of input files. - const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)); - const inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath)); - - if (isTsConfigFile(fileRead)) { - continue; - } - - if (!Harness.isDefaultLibraryFile(fileRead.path)) { - if (inInputList) { - continue; - } + const normalized = ts.normalizeSlashes(fileRead.path); + if (!uniqueNames.has(normalized) && !Harness.isDefaultLibraryFile(fileRead.path)) { + uniqueNames.set(normalized, true); otherFiles.push(getHarnessCompilerInputUnit(fileRead.path)); } - else if (!opts.options.noLib && Harness.isDefaultLibraryFile(fileRead.path)) { - if (!inInputList) { - // If useCustomLibraryFile is true, we will use lib.d.ts from json object - // otherwise use the lib.d.ts from built/local - // Majority of RWC code will be using built/local/lib.d.ts instead of - // lib.d.ts inside json file. However, some RWC cases will still use - // their own version of lib.d.ts because they have customized lib.d.ts - if (useCustomLibraryFile) { - inputFiles.push(getHarnessCompilerInputUnit(fileRead.path)); - } - else { - // set the flag to put default library to the beginning of the list - inputFiles.unshift(Harness.getDefaultLibraryFile(fileRead.path, oldIO)); - } - } + else if (!opts.options.noLib && Harness.isDefaultLibraryFile(fileRead.path) && !uniqueNames.has(normalized) && useCustomLibraryFile) { + // If useCustomLibraryFile is true, we will use lib.d.ts from json object + // otherwise use the lib.d.ts from built/local + // Majority of RWC code will be using built/local/lib.d.ts instead of + // lib.d.ts inside json file. However, some RWC cases will still use + // their own version of lib.d.ts because they have customized lib.d.ts + uniqueNames.set(normalized, true); + inputFiles.push(getHarnessCompilerInputUnit(fileRead.path)); } } + }); + if (useCustomLibraryFile) { // do not use lib since we already read it in above opts.options.lib = undefined; opts.options.noLib = true; + } - // Emit the results - compilerResult = Harness.Compiler.compileFiles( - inputFiles, - otherFiles, - /* harnessOptions */ undefined, - opts.options, - // Since each RWC json file specifies its current directory in its json file, we need - // to pass this information in explicitly instead of acquiring it from the process. - currentDirectory); - compilerOptions = compilerResult.options; - }); + // Emit the results + compilerResult = Harness.Compiler.compileFiles( + inputFiles, + otherFiles, + /* harnessOptions */ undefined, + opts.options, + // Since each RWC json file specifies its current directory in its json file, we need + // to pass this information in explicitly instead of acquiring it from the process. + currentDirectory); + compilerOptions = compilerResult.options; function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile { const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)); diff --git a/src/harness/vpath.ts b/src/harness/vpath.ts index 9b42ba2a28d..31430b50e2b 100644 --- a/src/harness/vpath.ts +++ b/src/harness/vpath.ts @@ -124,4 +124,8 @@ namespace vpath { return isDeclaration(path) && basename(path).startsWith("lib."); } + + export function isTsConfigFile(path: string): boolean { + return path.indexOf("tsconfig") !== -1 && path.indexOf("json") !== -1; + } } \ No newline at end of file From 67ebb6c751738c28e495b57819b21142dcc6336a Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 9 May 2018 04:10:24 +0000 Subject: [PATCH 58/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1675ab764eb..9d3620e29e4 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2520,6 +2520,9 @@ + + + @@ -2553,6 +2556,9 @@ + + + @@ -4293,6 +4299,12 @@ + + + + + + @@ -5589,6 +5601,12 @@ + + + + + + @@ -7437,6 +7455,9 @@ + + + @@ -9381,6 +9402,9 @@ + + + From d88210b27057966bec7e4322c95eda6c6424a314 Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Wed, 9 May 2018 09:09:49 +0200 Subject: [PATCH 59/64] Do not check for await expression and always output yield await --- src/compiler/transformers/esnext.ts | 22 +++++++++---------- ...ter.asyncGenerators.classMethods.es2015.js | 2 +- ...mitter.asyncGenerators.classMethods.es5.js | 5 +++-- ...cGenerators.functionDeclarations.es2015.js | 2 +- ...syncGenerators.functionDeclarations.es5.js | 5 +++-- ...ncGenerators.functionExpressions.es2015.js | 2 +- ...asyncGenerators.functionExpressions.es5.js | 5 +++-- ...cGenerators.objectLiteralMethods.es2015.js | 2 +- ...syncGenerators.objectLiteralMethods.es5.js | 5 +++-- 9 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index f0bd43a4659..28366d4fce8 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -143,19 +143,19 @@ namespace ts { ); } - if (node.expression && node.expression.kind !== SyntaxKind.AwaitExpression) { - return setOriginalNode( - setTextRange( - createYield( - createDownlevelAwait( - visitNode(node.expression, visitor, isExpression) - ) - ), - node + return setOriginalNode( + setTextRange( + createYield( + createDownlevelAwait( + node.expression + ? visitNode(node.expression, visitor, isExpression) + : createVoidZero() + ) ), node - ); - } + ), + node + ); } return visitEachChild(node, visitor, context); diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js index 15bab8b98ae..58dbe061d18 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js @@ -95,7 +95,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar class C2 { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield; + const x = yield yield __await(void 0); }); } } diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js index 85357291a6b..0387225261c 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.js @@ -160,8 +160,9 @@ var C2 = /** @class */ (function () { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/]; - case 1: + case 0: return [4 /*yield*/, __await(void 0)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js index 31b0fb24a56..1d242f4ce6b 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.js @@ -61,7 +61,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; function f2() { return __asyncGenerator(this, arguments, function* f2_1() { - const x = yield; + const x = yield yield __await(void 0); }); } //// [F3.js] diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js index ef965090196..88a39d18cd0 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.js @@ -121,8 +121,9 @@ function f2() { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/]; - case 1: + case 0: return [4 /*yield*/, __await(void 0)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js index f460d91bc8b..9c964275ff3 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.js @@ -61,7 +61,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar }; const f2 = function () { return __asyncGenerator(this, arguments, function* () { - const x = yield; + const x = yield yield __await(void 0); }); }; //// [F3.js] diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js index e175f32278c..969036e96af 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.js @@ -121,8 +121,9 @@ var f2 = function () { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/]; - case 1: + case 0: return [4 /*yield*/, __await(void 0)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js index 9a0a9a42b36..0f64e788b29 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.js @@ -78,7 +78,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar const o2 = { f() { return __asyncGenerator(this, arguments, function* f_1() { - const x = yield; + const x = yield yield __await(void 0); }); } }; diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js index 608d57e5eb7..ae217449715 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.js @@ -138,8 +138,9 @@ var o2 = { var x; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/]; - case 1: + case 0: return [4 /*yield*/, __await(void 0)]; + case 1: return [4 /*yield*/, _a.sent()]; + case 2: x = _a.sent(); return [2 /*return*/]; } From 89d2baede768f254c768019982820e1f67191dee Mon Sep 17 00:00:00 2001 From: Paul Koerbitz Date: Wed, 9 May 2018 10:53:27 +0200 Subject: [PATCH 60/64] Adress review comments --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- .../importCallExpressionErrorInES2015.errors.txt | 12 ++++++------ .../importCallExpressionNestedES2015.errors.txt | 8 ++++---- .../importCallExpressionNestedES20152.errors.txt | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 64f7e746dae..05b88abafd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28103,7 +28103,7 @@ namespace ts { function checkGrammarImportCallExpression(node: ImportCall): boolean { if (moduleKind === ModuleKind.ES2015) { - return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules_Please_use_esnext_or_commonjs_as_module_compiler_option); + return grammarErrorOnNode(node, Diagnostics.Dynamic_import_is_only_supported_when_module_flag_is_commonjs_or_esNext); } if (node.typeArguments) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a92b701380b..a58091e70fb 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -895,7 +895,7 @@ "category": "Error", "code": 1322 }, - "Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option.": { + "Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'.": { "category": "Error", "code": 1323 }, diff --git a/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt b/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt index 0a642ff9857..b2000f9319e 100644 --- a/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt +++ b/tests/baselines/reference/importCallExpressionErrorInES2015.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/dynamicImport/1.ts(1,1): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. -tests/cases/conformance/dynamicImport/1.ts(2,10): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. -tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/1.ts(1,1): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. +tests/cases/conformance/dynamicImport/1.ts(2,10): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. +tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. ==== tests/cases/conformance/dynamicImport/0.ts (0 errors) ==== @@ -9,10 +9,10 @@ tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import c ==== tests/cases/conformance/dynamicImport/1.ts (3 errors) ==== import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. var p1 = import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. p1.then(zero => { return zero.foo(); }) @@ -20,5 +20,5 @@ tests/cases/conformance/dynamicImport/1.ts(8,16): error TS1323: Dynamic import c function foo() { const p2 = import("./0"); ~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt index 530cd0d1b1d..ef1a96ee913 100644 --- a/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt +++ b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. -tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. ==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic impo async function foo() { return await import((await import("./foo")).default); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. ~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt index 530cd0d1b1d..ef1a96ee913 100644 --- a/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt +++ b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. -tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. ==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic impo async function foo() { return await import((await import("./foo")).default); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. ~~~~~~~~~~~~~~~ -!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. Please use 'esnext' or 'commonjs' as module compiler option. +!!! error TS1323: Dynamic import is only supported when '--module' flag is 'commonjs' or 'esNext'. } \ No newline at end of file From 7bcbe7c193b9ba6a5843d27195aef6ac948ccc83 Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 9 May 2018 10:10:29 +0000 Subject: [PATCH 61/64] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9d97508babb..e159b01229e 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1107,6 +1107,12 @@ + + + + + + @@ -2043,6 +2049,12 @@ + + + + + + @@ -2421,6 +2433,12 @@ + + + + + + @@ -2523,6 +2541,9 @@ + + + @@ -2556,6 +2577,9 @@ + + + @@ -3138,6 +3162,12 @@ + + + + + + @@ -3693,6 +3723,12 @@ + + + + + + @@ -4296,6 +4332,12 @@ + + + + + + @@ -5592,6 +5634,12 @@ + + + + + + @@ -5610,6 +5658,18 @@ + + + + + + + + + + + + @@ -6006,6 +6066,18 @@ + + + + + + + + + + + + @@ -6432,6 +6504,12 @@ + + + + + + @@ -6444,6 +6522,12 @@ + + + + + + @@ -7443,6 +7527,9 @@ + + + @@ -9387,6 +9474,9 @@ + + + From 91a15dc6095227c4a01ce984f4d33e7cdb86efde Mon Sep 17 00:00:00 2001 From: Zen <843968788@qq.com> Date: Wed, 9 May 2018 22:42:44 +0800 Subject: [PATCH 62/64] improve performance --- src/services/documentHighlights.ts | 2 +- tests/cases/fourslash/getOccurrencesAsyncAwait.ts | 5 +++++ tests/cases/fourslash/getOccurrencesAsyncAwait3.ts | 2 -- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 3c898551ac9..65653483d07 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -395,7 +395,7 @@ namespace ts.DocumentHighlights { pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.AwaitKeyword); } // Do not cross function boundaries. - if (!isFunctionLike(node)) { + if (!isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) && !isTypeAliasDeclaration(node) && !isTypeNode(node)) { forEachChild(node, aggregate); } } diff --git a/tests/cases/fourslash/getOccurrencesAsyncAwait.ts b/tests/cases/fourslash/getOccurrencesAsyncAwait.ts index f2224255d14..f337e755096 100644 --- a/tests/cases/fourslash/getOccurrencesAsyncAwait.ts +++ b/tests/cases/fourslash/getOccurrencesAsyncAwait.ts @@ -3,6 +3,11 @@ ////[|async|] function f() { //// [|await|] 100; //// [|a/**/wait|] [|await|] 200; +////class Foo { +//// async memberFunction() { +//// await 1; +//// } +////} //// return [|await|] async function () { //// await 300; //// } diff --git a/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts b/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts index 67d56167b82..972b6b8b07d 100644 --- a/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts +++ b/tests/cases/fourslash/getOccurrencesAsyncAwait3.ts @@ -7,7 +7,5 @@ //// await 300; ////} -verify.rangesAreOccurrences(false); - goTo.marker(); verify.occurrencesAtPositionCount(0); \ No newline at end of file From 7fb7eecf2cac44b8d57e03606b0f5e331807d9ba Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 9 May 2018 07:51:46 -0700 Subject: [PATCH 63/64] Add telemetry for open JS files (#23833) * Add telemetry for open JS files * Send event every time * Keep stats even for closed files * Remove tsCheckCountForOpenFilesTelemetry * Use 'info.path' * Update API --- src/harness/unittests/telemetry.ts | 39 ++++++++++++++++++- .../unittests/tsserverProjectSystem.ts | 19 ++++++--- src/server/editorServices.ts | 34 +++++++++++++++- src/server/project.ts | 5 ++- src/server/typingsCache.ts | 2 +- src/services/preProcess.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 22 ++++++++++- 7 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index 2e3e299ac3b..e3649ae1c79 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -42,7 +42,7 @@ namespace ts.projectSystem { const et = new TestServerEventManager([...files, notIncludedFile, tsconfig]); et.service.openClientFile(files[0].path); et.assertProjectInfoTelemetryEvent({ - fileStats: { ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 }, + fileStats: fileStats({ ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 }), compilerOptions, include: true, }); @@ -234,9 +234,44 @@ namespace ts.projectSystem { languageServiceEnabled: false, }); }); + + describe("open files telemetry", () => { + it("sends event for inferred project", () => { + const ajs = makeFile("/a.js", "// @ts-check\nconst x = 0;"); + const bjs = makeFile("/b.js"); + const et = new TestServerEventManager([ajs, bjs]); + + et.service.openClientFile(ajs.path); + et.assertOpenFileTelemetryEvent({ checkJs: true }); + + et.service.openClientFile(bjs.path); + et.assertOpenFileTelemetryEvent({ checkJs: false }); + + // No repeated send for opening a file seen before. + et.service.openClientFile(bjs.path); + et.assertNoOpenFilesTelemetryEvent(); + }); + + it("not for '.ts' file", () => { + const ats = makeFile("/a.ts", ""); + const et = new TestServerEventManager([ats]); + + et.service.openClientFile(ats.path); + et.assertNoOpenFilesTelemetryEvent(); + }); + + it("even for project with 'ts-check' in config", () => { + const file = makeFile("/a.js"); + const compilerOptions: CompilerOptions = { checkJs: true }; + const jsconfig = makeFile("/jsconfig.json", { compilerOptions }); + const et = new TestServerEventManager([jsconfig, file]); + et.service.openClientFile(file.path); + et.assertOpenFileTelemetryEvent({ checkJs: false }); + }); + }); }); function makeFile(path: string, content: {} = ""): File { - return { path, content: isString(content) ? "" : JSON.stringify(content) }; + return { path, content: isString(content) ? content : JSON.stringify(content) }; } } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index f54bd56f1ba..f26170ef6ae 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -215,7 +215,7 @@ namespace ts.projectSystem { } assertProjectInfoTelemetryEvent(partial: Partial, configFile?: string): void { - assert.deepEqual(this.getEvent(server.ProjectInfoTelemetryEvent), { + assert.deepEqual(this.getEvent(server.ProjectInfoTelemetryEvent), { projectId: Harness.mockHash(configFile || "/tsconfig.json"), fileStats: fileStats({ ts: 1 }), compilerOptions: {}, @@ -236,6 +236,13 @@ namespace ts.projectSystem { ...partial, }); } + + assertOpenFileTelemetryEvent(info: server.OpenFileInfo): void { + assert.deepEqual(this.getEvent(server.OpenFileInfoTelemetryEvent), { info }); + } + assertNoOpenFilesTelemetryEvent(): void { + this.hasZeroEvent(server.OpenFileInfoTelemetryEvent); + } } class TestSession extends server.Session { @@ -2755,7 +2762,7 @@ namespace ts.projectSystem { const session = createSession(host, { canUseEvents: true, eventHandler: e => { - if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent) { + if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent) { return; } assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent); @@ -2807,7 +2814,7 @@ namespace ts.projectSystem { const session = createSession(host, { canUseEvents: true, eventHandler: e => { - if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) { + if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent) { return; } assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent); @@ -6241,14 +6248,14 @@ namespace ts.projectSystem { function verifyNoCall(callback: CalledMaps) { const calledMap = calledMaps[callback]; - assert.equal(calledMap.size, 0, `${callback} shouldnt be called: ${arrayFrom(calledMap.keys())}`); + assert.equal(calledMap.size, 0, `${callback} shouldn't be called: ${arrayFrom(calledMap.keys())}`); } function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: Map) { TestFSWithWatch.checkMultiMapKeyCount(callback, calledMaps[callback], expectedKeys); } - function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: string[], nTimes: number) { + function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: ReadonlyArray, nTimes: number) { TestFSWithWatch.checkMultiMapEachKeyWithCount(callback, calledMaps[callback], expectedKeys, nTimes); } @@ -6256,7 +6263,7 @@ namespace ts.projectSystem { iterateOnCalledMaps(key => verifyNoCall(key)); } - function verifyNoHostCallsExceptFileExistsOnce(expectedKeys: string[]) { + function verifyNoHostCallsExceptFileExistsOnce(expectedKeys: ReadonlyArray) { verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, expectedKeys, 1); verifyNoCall(CalledMapsWithSingleArg.directoryExists); verifyNoCall(CalledMapsWithSingleArg.getDirectories); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2bc61c67210..9de36f0687f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -6,6 +6,7 @@ namespace ts.server { export const ConfigFileDiagEvent = "configFileDiag"; export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState"; export const ProjectInfoTelemetryEvent = "projectInfo"; + export const OpenFileInfoTelemetryEvent = "openFileInfo"; // tslint:enable variable-name export interface ProjectsUpdatedInBackgroundEvent { @@ -55,6 +56,20 @@ namespace ts.server { readonly version: string; } + /** + * Info that we may send about a file that was just opened. + * Info about a file will only be sent once per session, even if the file changes in ways that might affect the info. + * Currently this is only sent for '.js' files. + */ + export interface OpenFileInfoTelemetryEvent { + readonly eventName: typeof OpenFileInfoTelemetryEvent; + readonly data: OpenFileInfoTelemetryEventData; + } + + export interface OpenFileInfoTelemetryEventData { + readonly info: OpenFileInfo; + } + export interface ProjectInfoTypeAcquisitionData { readonly enable: boolean; // Actual values of include/exclude entries are scrubbed. @@ -70,7 +85,11 @@ namespace ts.server { readonly dts: number; } - export type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent; + export interface OpenFileInfo { + readonly checkJs: boolean; + } + + export type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void; @@ -325,6 +344,9 @@ namespace ts.server { * Container of all known scripts */ private readonly filenameToScriptInfo = createMap(); + // Set of all '.js' files ever opened. + private readonly allJsFilesForOpenFileTelemetry = createMap(); + /** * Map to the real path of the infos */ @@ -2095,9 +2117,19 @@ namespace ts.server { this.printProjects(); + this.telemetryOnOpenFile(info); return { configFileName, configFileErrors }; } + private telemetryOnOpenFile(scriptInfo: ScriptInfo): void { + if (!this.eventHandler || !scriptInfo.isJavaScript() || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) { + return; + } + + const info: OpenFileInfo = { checkJs: !!scriptInfo.getDefaultProject().getSourceFile(scriptInfo.path).checkJsDirective }; + this.eventHandler({ eventName: OpenFileInfoTelemetryEvent, data: { info } }); + } + /** * Close file whose contents is managed by the client * @param filename is absolute pathname diff --git a/src/server/project.ts b/src/server/project.ts index 328d41649ca..a19739d2ba1 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -6,9 +6,12 @@ namespace ts.server { External } + /* @internal */ + export type Mutable = { -readonly [K in keyof T]: T[K]; }; + /* @internal */ export function countEachFileTypes(infos: ScriptInfo[]): FileStats { - const result = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 }; + const result: Mutable = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0 }; for (const info of infos) { switch (info.scriptKind) { case ScriptKind.JS: diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index c255757481f..7440735ecb2 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -11,7 +11,7 @@ namespace ts.server { enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; - readonly globalTypingsCacheLocation: string; + readonly globalTypingsCacheLocation: string | undefined; } export const nullTypingsInstaller: ITypingsInstaller = { diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 6c5f6c1b2ff..5f1378ddbb7 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -1,7 +1,7 @@ namespace ts { export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { const pragmaContext: PragmaContext = { - languageVersion: ScriptTarget.ES5, // controls weather the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia + languageVersion: ScriptTarget.ES5, // controls whether the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia pragmas: undefined, checkJsDirective: undefined, referencedFiles: [], diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index f6bc5e75781..845ce42b5dc 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7734,7 +7734,7 @@ declare namespace ts.server { enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; - readonly globalTypingsCacheLocation: string; + readonly globalTypingsCacheLocation: string | undefined; } const nullTypingsInstaller: ITypingsInstaller; } @@ -7971,6 +7971,7 @@ declare namespace ts.server { const ConfigFileDiagEvent = "configFileDiag"; const ProjectLanguageServiceStateEvent = "projectLanguageServiceState"; const ProjectInfoTelemetryEvent = "projectInfo"; + const OpenFileInfoTelemetryEvent = "openFileInfo"; interface ProjectsUpdatedInBackgroundEvent { eventName: typeof ProjectsUpdatedInBackgroundEvent; data: { @@ -8019,6 +8020,18 @@ declare namespace ts.server { /** TypeScript version used by the server. */ readonly version: string; } + /** + * Info that we may send about a file that was just opened. + * Info about a file will only be sent once per session, even if the file changes in ways that might affect the info. + * Currently this is only sent for '.js' files. + */ + interface OpenFileInfoTelemetryEvent { + readonly eventName: typeof OpenFileInfoTelemetryEvent; + readonly data: OpenFileInfoTelemetryEventData; + } + interface OpenFileInfoTelemetryEventData { + readonly info: OpenFileInfo; + } interface ProjectInfoTypeAcquisitionData { readonly enable: boolean; readonly include: boolean; @@ -8031,7 +8044,10 @@ declare namespace ts.server { readonly tsx: number; readonly dts: number; } - type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent; + interface OpenFileInfo { + readonly checkJs: boolean; + } + type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent; type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void; interface SafeList { [name: string]: { @@ -8082,6 +8098,7 @@ declare namespace ts.server { * Container of all known scripts */ private readonly filenameToScriptInfo; + private readonly allJsFilesForOpenFileTelemetry; /** * maps external project file name to list of config files that were the part of this project */ @@ -8286,6 +8303,7 @@ declare namespace ts.server { openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult; private findExternalProjectContainingOpenScriptInfo; openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult; + private telemetryOnOpenFile; /** * Close file whose contents is managed by the client * @param filename is absolute pathname From e27fb0651b5c3e3baa4f873386d32b8bd4bb0fb7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 May 2018 09:25:00 -0700 Subject: [PATCH 64/64] Fix crash in recursive declared type resolution (#23950) When one type has a type parameter with a default --- src/compiler/checker.ts | 6 +++++- .../recursiveResolveDeclaredMembers.symbols | 18 ++++++++++++++++++ .../recursiveResolveDeclaredMembers.types | 18 ++++++++++++++++++ .../recursiveResolveDeclaredMembers.ts | 12 ++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/recursiveResolveDeclaredMembers.symbols create mode 100644 tests/baselines/reference/recursiveResolveDeclaredMembers.types create mode 100644 tests/cases/compiler/recursiveResolveDeclaredMembers.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a368a6a8f64..542ef7347ed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5656,6 +5656,10 @@ namespace ts { const symbol = type.symbol; const members = getMembersOfSymbol(symbol); (type).declaredProperties = getNamedMembers(members); + // Start with signatures at empty array in case of recursive types + (type).declaredCallSignatures = emptyArray; + (type).declaredConstructSignatures = emptyArray; + (type).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); (type).declaredConstructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New)); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); @@ -7048,7 +7052,7 @@ namespace ts { for (let i = numTypeArguments; i < numTypeParameters; i++) { const mapper = createTypeMapper(typeParameters, typeArguments); let defaultType = getDefaultFromTypeParameter(typeParameters[i]); - if (defaultType && isTypeIdenticalTo(defaultType, emptyObjectType) && isJavaScriptImplicitAny) { + if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) { defaultType = anyType; } typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); diff --git a/tests/baselines/reference/recursiveResolveDeclaredMembers.symbols b/tests/baselines/reference/recursiveResolveDeclaredMembers.symbols new file mode 100644 index 00000000000..b531073f705 --- /dev/null +++ b/tests/baselines/reference/recursiveResolveDeclaredMembers.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/types.ts === +// #23025 +export interface F { +>F : Symbol(F, Decl(types.ts, 0, 0)) + + (): E; +>E : Symbol(E, Decl(other.js, 0, 4)) +} +export interface D {} +>D : Symbol(D, Decl(types.ts, 3, 1)) +>T : Symbol(T, Decl(types.ts, 4, 19)) +>F : Symbol(F, Decl(types.ts, 0, 0)) +>F : Symbol(F, Decl(types.ts, 0, 0)) + +=== tests/cases/compiler/other.js === +/** @typedef {import("./types").D} E */ +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/recursiveResolveDeclaredMembers.types b/tests/baselines/reference/recursiveResolveDeclaredMembers.types new file mode 100644 index 00000000000..9a1aac95224 --- /dev/null +++ b/tests/baselines/reference/recursiveResolveDeclaredMembers.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/types.ts === +// #23025 +export interface F { +>F : F + + (): E; +>E : D +} +export interface D {} +>D : D +>T : T +>F : F +>F : F + +=== tests/cases/compiler/other.js === +/** @typedef {import("./types").D} E */ +No type information for this code. +No type information for this code. \ No newline at end of file diff --git a/tests/cases/compiler/recursiveResolveDeclaredMembers.ts b/tests/cases/compiler/recursiveResolveDeclaredMembers.ts new file mode 100644 index 00000000000..39e5f05849b --- /dev/null +++ b/tests/cases/compiler/recursiveResolveDeclaredMembers.ts @@ -0,0 +1,12 @@ +// #23025 +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: types.ts +export interface F { + (): E; +} +export interface D {} + +// @Filename: other.js +/** @typedef {import("./types").D} E */