Merge branch 'master' of github.com:Microsoft/TypeScript into multiple-prologue-directives

This commit is contained in:
Klaus Meinhardt
2018-07-11 18:47:23 +02:00
103 changed files with 3508 additions and 7430 deletions
+19 -2
View File
@@ -163,7 +163,7 @@ Rostislav Galimsky <rostgal@gmail.com>
Richard Knoll <riknoll@users.noreply.github.com> Richard Knoll <riknoll@microsoft.com>
Richard Karmazín <richard@karmazin.cz>
Rowan Wyborn <rwyborn@internode.on.net>
Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com> Ryan Cavanaugh <ryan.cavanaugh@microsoft.com> Ryan Cavanaugh <ryanca@microsoft.com>
Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com> Ryan Cavanaugh <ryan.cavanaugh@microsoft.com> Ryan Cavanaugh <ryanca@microsoft.com> Ryan Cavanaugh <the.ryan.cavanaugh@gmail.com>
Ryohei Ikegami <iofg2100@gmail.com>
Sarangan Rajamanickam <sarajama@microsoft.com>
Sébastien Arod <sebastien.arod@gmail.com>
@@ -340,4 +340,21 @@ EcoleKeine <Ecole_k@qq.com> # Ecole Keine
Khải <hvksmr1996@gmail.com>
rhysd <lin90162@yahoo.co.jp> # @rhysd
Zen <843968788@qq.com> Zzzen <843968788@qq.com> # @Zzzen
bluelovers <codelovers@users.sourceforge.net> # @bluelovers
bluelovers <codelovers@users.sourceforge.net> # @bluelovers
Dan Freeman <dfreeman@salsify.com>
David Sherret <dsherret@gmail.com>
David Staheli <dastahel@microsoft.com>
Elizabeth Dinella <elizabeth.a.dinella@gmail.com>
John Doe <github.john.doe@outlook.com>
Kevin Gibbons <kevin@shapesecurity.com>
Markus Johnsson <markus.johnsson@infviz.com>
Martin Probst <martin@probst.io>
Mateusz Burzyński <mateuszburzynski@gmail.com>
Steven <steven@ceriously.com> # @styfle
Pi Lanningham <pi.lanningham@gmail.com>
Sam Bostock <sam.bostock@shopify.com>
Vimal Raghubir <vraghubir0418@gmail.com>
Vyacheslav Pukhanov <vyacheslav.pukhanov@gmail.com>
dangoo <daniel.gooss@sinnerschrader.com> # Daniel Gooss
krk <keremkat@gmail.com> # Kerem Kat
micnic <micnic90@gmail.com> # Nicu Micleușanu
+1
View File
@@ -19,6 +19,7 @@ branches:
- release-2.7
- release-2.8
- release-2.9
- release-3.0
install:
- npm uninstall typescript --no-save
+17 -1
View File
@@ -74,7 +74,9 @@ TypeScript is authored by:
* Dafrok Zhang
* Dahan Gong
* Dan Corder
* Dan Freeman
* Dan Quirk
* Daniel Gooss
* Daniel Hollocher
* Daniel Król
* Daniel Lehenbauer
@@ -82,7 +84,9 @@ TypeScript is authored by:
* David Kmenta
* David Li
* David Sheldrick
* David Sherret
* David Souther
* David Staheli
* Denis Nedelyaev
* Derek P Sifford
* Dhruv Rajvanshi
@@ -96,6 +100,7 @@ TypeScript is authored by:
* @e-cloud
* Ecole Keine
* Elisée Maurer
* Elizabeth Dinella
* Emilio García-Pumarino
* Eric Grube
* Eric Tsang
@@ -161,6 +166,7 @@ TypeScript is authored by:
* Joel Day
* Joey Wilson
* Johannes Rieken
* John Doe
* John Vilk
* Jonathan Bond-Caron
* Jonathan Park
@@ -184,7 +190,9 @@ TypeScript is authored by:
* Keith Mashinter
* Ken Howard
* Kenji Imamula
* Kerem Kat
* Kevin Donnelly
* Kevin Gibbons
* Kevin Lang
* Khải
* Kitson Kelly
@@ -201,10 +209,13 @@ TypeScript is authored by:
* Manish Giri
* Marin Marinov
* Marius Schulz
* Markus Johnsson
* Martin Hiller
* Martin Probst
* Martin Vseticka
* Martyn Janes
* Masahiro Wakame
* Mateusz Burzyński
* Matt Bierner
* Matt McCutchen
* Matt Mitchell
@@ -223,10 +234,10 @@ TypeScript is authored by:
* Mohamed Hegazy
* Mohsen Azimi
* Myles Megyesi
* Natalie Coley
* Nathan Shively-Sanders
* Nathan Yee
* Nicolas Henry
* Nicu Micleușanu
* @nieltg
* Nima Zahedi
* Noah Chen
@@ -248,6 +259,7 @@ TypeScript is authored by:
* Peter Burns
* Philip Bulley
* Philippe Voinov
* Pi Lanningham
* Piero Cangianiello
* @piloopin
* Prayag Verma
@@ -270,6 +282,7 @@ TypeScript is authored by:
* Rowan Wyborn
* Ryan Cavanaugh
* Ryohei Ikegami
* Sam Bostock
* Sam El-Husseini
* Sarangan Rajamanickam
* Sean Barag
@@ -290,6 +303,7 @@ TypeScript is authored by:
* Stas Vilchik
* Stephan Ginthör
* Steve Lucco
* @styfle
* Sudheesh Singanamalla
* Sébastien Arod
* @T18970237136
@@ -316,8 +330,10 @@ TypeScript is authored by:
* Vidar Tonaas Fauske
* Viktor Zozulyak
* Vilic Vane
* Vimal Raghubir
* Vladimir Kurchatkin
* Vladimir Matveev
* Vyacheslav Pukhanov
* Wenlu Wang
* Wesley Wigham
* William Orr
+139 -57
View File
@@ -24,6 +24,10 @@ const baselineAccept = require("./scripts/build/baselineAccept");
const cmdLineOptions = require("./scripts/build/options");
const exec = require("./scripts/build/exec");
const browserify = require("./scripts/build/browserify");
const debounce = require("./scripts/build/debounce");
const prepend = require("./scripts/build/prepend");
const { removeSourceMaps } = require("./scripts/build/sourcemaps");
const { CancelSource, CancelError } = require("./scripts/build/cancellation");
const { libraryTargets, generateLibs } = require("./scripts/build/lib");
const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests");
@@ -44,17 +48,9 @@ const generateLocalizedDiagnosticMessagesJs = "scripts/generateLocalizedDiagnost
const buildProtocolJs = "scripts/buildProtocol.js";
const produceLKGJs = "scripts/produceLKG.js";
const word2mdJs = "scripts/word2md.js";
gulp.task("scripts", /*help*/ false, () => project.compile(scriptsProject), {
aliases: [
configurePrereleaseJs,
processDiagnosticMessagesJs,
generateLocalizedDiagnosticMessagesJs,
produceLKGJs,
buildProtocolJs,
word2mdJs
]
});
gulp.task("clean-scripts", /*help*/ false, () => project.clean(scriptsProject));
const scriptsTaskAliases = [configurePrereleaseJs, processDiagnosticMessagesJs, generateLocalizedDiagnosticMessagesJs, produceLKGJs, buildProtocolJs, word2mdJs];
gulp.task("scripts", /*help*/ false, () => project.compile(scriptsProject), { aliases: scriptsTaskAliases });
gulp.task("clean:scripts", /*help*/ false, () => project.clean(scriptsProject), { aliases: scriptsTaskAliases.map(alias => `clean:${alias}`)});
// Nightly management tasks
gulp.task(
@@ -73,7 +69,7 @@ gulp.task(
const importDefinitelyTypedTestsProject = "scripts/importDefinitelyTypedTests/tsconfig.json";
const importDefinitelyTypedTestsJs = "scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js";
gulp.task(importDefinitelyTypedTestsJs, /*help*/ false, () => project.compile(importDefinitelyTypedTestsProject));
gulp.task("clean:" + importDefinitelyTypedTestsJs, /*help*/ false, () => project.clean(importDefinitelyTypedTestsProject));
gulp.task(`clean:${importDefinitelyTypedTestsJs}`, /*help*/ false, () => project.clean(importDefinitelyTypedTestsProject));
gulp.task(
"importDefinitelyTypedTests",
@@ -95,7 +91,7 @@ gulp.task(diagnosticInformationMapTs, /*help*/ false, [processDiagnosticMessages
return exec(host, [processDiagnosticMessagesJs, diagnosticMessagesJson]);
}
});
gulp.task("clean:" + diagnosticInformationMapTs, /*help*/ false, () => del([diagnosticInformationMapTs, diagnosticMessagesGeneratedJson]));
gulp.task(`clean:${diagnosticInformationMapTs}`, /*help*/ false, () => del([diagnosticInformationMapTs, diagnosticMessagesGeneratedJson]));
const builtGeneratedDiagnosticMessagesJson = "built/local/diagnosticMessages.generated.json";
gulp.task(builtGeneratedDiagnosticMessagesJson, /*help*/ false, [diagnosticInformationMapTs], () =>
@@ -140,9 +136,10 @@ gulp.task(typescriptServicesProject, /*help*/ false, () => {
// NOTE: flatten services so that we can properly strip @internal
project.flatten(servicesProject, typescriptServicesProject, {
compilerOptions: {
"removeComments": true,
"removeComments": false,
"stripInternal": true,
"outFile": "typescriptServices.js"
"declarationMap": false,
"outFile": "typescriptServices.out.js" // must align with same task in jakefile. We fix this name below.
}
});
});
@@ -150,7 +147,16 @@ gulp.task(typescriptServicesProject, /*help*/ false, () => {
const typescriptServicesJs = "built/local/typescriptServices.js";
const typescriptServicesDts = "built/local/typescriptServices.d.ts";
gulp.task(typescriptServicesJs, /*help*/ false, ["lib", "generate-diagnostics", typescriptServicesProject], () =>
project.compile(typescriptServicesProject, { dts: files => files.pipe(convertConstEnums()) }),
project.compile(typescriptServicesProject, {
js: files => files
.pipe(prepend.file(copyright))
.pipe(rename("typescriptServices.js")),
dts: files => files
.pipe(removeSourceMaps())
.pipe(prepend.file(copyright))
.pipe(convertConstEnums())
.pipe(rename("typescriptServices.d.ts"))
}),
{ aliases: [typescriptServicesDts] });
const typescriptJs = "built/local/typescript.js";
@@ -179,29 +185,39 @@ gulp.task(typescriptStandaloneDts, /*help*/ false, [typescriptServicesDts], () =
// build all 'typescriptServices'-related outputs
gulp.task("services", /*help*/ false, [typescriptServicesJs, typescriptServicesDts, typescriptJs, typescriptDts, typescriptStandaloneDts]);
const useCompiler = cmdLineOptions.lkg ? "lkg" : "built";
const useCompilerDeps = cmdLineOptions.lkg ? ["lib", "generate-diagnostics"] : [typescriptServicesJs];
const tscProject = "src/tsc/tsconfig.json";
const tscJs = "built/local/tsc.js";
gulp.task(tscJs, /*help*/ false, [typescriptServicesJs], () => project.compile(tscProject, { typescript: "built" }));
gulp.task(tscJs, /*help*/ false, useCompilerDeps, () =>
project.compile(tscProject, {
typescript: useCompiler,
js: files => files.pipe(prepend.file(copyright))
}));
const tscReleaseProject = "src/tsc/tsconfig.release.json";
const tscReleaseJs = "built/local/tsc.release.js";
gulp.task(tscReleaseJs, /*help*/ false, () => project.compile(tscReleaseProject));
gulp.task(tscReleaseJs, /*help*/ false, () =>
project.compile(tscReleaseProject, {
js: files => files.pipe(prepend.file(copyright))
}));
const cancellationTokenProject = "src/cancellationToken/tsconfig.json";
const cancellationTokenJs = "built/local/cancellationToken.js";
gulp.task(cancellationTokenJs, /*help*/ false, [typescriptServicesJs], () => project.compile(cancellationTokenProject, { typescript: "built" }));
gulp.task(cancellationTokenJs, /*help*/ false, useCompilerDeps, () => project.compile(cancellationTokenProject, { typescript: useCompiler }));
const typingsInstallerProject = "src/typingsInstaller/tsconfig.json";
const typingsInstallerJs = "built/local/typingsInstaller.js";
gulp.task(typingsInstallerJs, /*help*/ false, [typescriptServicesJs], () => project.compile(typingsInstallerProject, { typescript: "built" }));
gulp.task(typingsInstallerJs, /*help*/ false, useCompilerDeps, () => project.compile(typingsInstallerProject, { typescript: useCompiler }));
const tsserverProject = "src/tsserver/tsconfig.json";
const tsserverJs = "built/local/tsserver.js";
gulp.task(tsserverJs, /*help*/ false, [typescriptServicesJs], () => project.compile(tsserverProject, { typescript: "built" }));
gulp.task(tsserverJs, /*help*/ false, useCompilerDeps, () => project.compile(tsserverProject, { typescript: useCompiler }));
const watchGuardProject = "src/watchGuard/tsconfig.json";
const watchGuardJs = "built/local/watchGuard.js";
gulp.task(watchGuardJs, /*help*/ false, [typescriptServicesJs], () => project.compile(watchGuardProject, { typescript: "built" }));
gulp.task(watchGuardJs, /*help*/ false, useCompilerDeps, () => project.compile(watchGuardProject, { typescript: useCompiler }));
const typesMapJson = "built/local/typesMap.json";
gulp.task(typesMapJson, /*help*/ false, [], () =>
@@ -216,21 +232,28 @@ gulp.task(tsserverlibraryProject, /*help*/ false, () => {
project.flatten("src/tsserver/tsconfig.json", tsserverlibraryProject, {
exclude: ["src/tsserver/server.ts"],
compilerOptions: {
"removeComments": true,
"removeComments": false,
"stripInternal": true,
"outFile": "tsserverlibrary.js"
"declarationMap": false,
"outFile": "tsserverlibrary.out.js" // must align with same task in jakefile. We fix this name below.
}
});
});
const tsserverlibraryJs = "built/local/tsserverlibrary.js";
const tsserverlibraryDts = "built/local/tsserverlibrary.d.ts";
gulp.task(tsserverlibraryJs, /*help*/ false, [typescriptServicesJs, tsserverlibraryProject], () =>
gulp.task(tsserverlibraryJs, /*help*/ false, useCompilerDeps.concat([tsserverlibraryProject]), () =>
project.compile(tsserverlibraryProject, {
js: files => files
.pipe(prepend.file(copyright))
.pipe(rename("tsserverlibrary.js")),
dts: files => files
.pipe(removeSourceMaps())
.pipe(prepend.file(copyright))
.pipe(convertConstEnums())
.pipe(append("\nexport = ts;\nexport as namespace ts;")),
typescript: "built"
.pipe(append("\nexport = ts;\nexport as namespace ts;"))
.pipe(rename("tsserverlibrary.d.ts")),
typescript: useCompiler
}), { aliases: [tsserverlibraryDts] });
gulp.task(
@@ -294,29 +317,29 @@ gulp.task(
// Task to build the tests infrastructure using the built compiler
const testRunnerProject = "src/testRunner/tsconfig.json";
const runJs = "built/local/run.js";
gulp.task(runJs, /*help*/ false, [typescriptServicesJs, tsserverlibraryDts], () => project.compile(testRunnerProject, { typescript: "built" }));
gulp.task(runJs, /*help*/ false, useCompilerDeps, () => project.compile(testRunnerProject, { typescript: useCompiler }));
gulp.task(
"tests",
"Builds the test infrastructure using the built compiler",
[runJs]);
[runJs, tsserverlibraryDts]);
gulp.task(
"runtests-parallel",
"Runs all the tests in parallel using the built run.js file. Optional arguments are: --t[ests]=category1|category2|... --d[ebug]=true.",
["build-rules", "tests"],
() => runConsoleTests(runJs, "min", /*runInParallel*/ true));
["build-rules", "tests", "services", tsserverlibraryDts],
() => runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ false));
gulp.task(
"runtests",
"Runs the tests using the built run.js file. Optional arguments are: --t[ests]=regex --r[eporter]=[list|spec|json|<more>] --d[ebug]=true --color[s]=false --lint=true.",
["build-rules", "tests"],
() => runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false));
["build-rules", "tests", "services", tsserverlibraryDts],
() => runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ false));
const webTestServerProject = "tests/webTestServer.tsconfig.json";
const webTestServerJs = "tests/webTestServer.js";
gulp.task(webTestServerJs, /*help*/ false, [typescriptServicesJs], () => project.compile(webTestServerProject, { typescript: "built" }));
gulp.task("clean:" + webTestServerJs, /*help*/ false, () => project.clean(webTestServerProject));
gulp.task(webTestServerJs, /*help*/ false, useCompilerDeps, () => project.compile(webTestServerProject, { typescript: useCompiler }));
gulp.task(`clean:${webTestServerJs}`, /*help*/ false, () => project.clean(webTestServerProject));
const bundlePath = path.resolve("built/local/bundle.js");
@@ -392,8 +415,8 @@ gulp.task(
// Webhost
const webtscProject = "tests/webhost/webtsc.tsconfig.json";
const webtscJs = "tests/webhost/webtsc.js";
gulp.task(webtscJs, /*help*/ false, [typescriptServicesJs], () => project.compile(webtscProject, { typescript: "built" }));
gulp.task("clean:" + webtscJs, /*help*/ false, () => project.clean(webtscProject));
gulp.task(webtscJs, /*help*/ false, useCompilerDeps, () => project.compile(webtscProject, { typescript: useCompiler }));
gulp.task(`clean:${webtscJs}`, /*help*/ false, () => project.clean(webtscProject));
gulp.task("webhost", "Builds the tsc web host", [webtscJs], () =>
gulp.src("built/local/lib.d.ts")
@@ -402,8 +425,8 @@ gulp.task("webhost", "Builds the tsc web host", [webtscJs], () =>
// Perf compiler
const perftscProject = "tests/perftsc.tsconfig.json";
const perftscJs = "built/local/perftsc.js";
gulp.task(perftscJs, /*help*/ false, [typescriptServicesJs], () => project.compile(perftscProject, { typescript: "built" }));
gulp.task("clean:" + perftscJs, /*help*/ false, () => project.clean(perftscProject));
gulp.task(perftscJs, /*help*/ false, useCompilerDeps, () => project.compile(perftscProject, { typescript: useCompiler }));
gulp.task(`clean:${perftscJs}`, /*help*/ false, () => project.clean(perftscProject));
gulp.task(
"perftsc",
@@ -423,7 +446,7 @@ gulp.task(loggedIOJs, /*help*/ false, [], (done) => {
const instrumenterProject = "src/instrumenter/tsconfig.json";
const instrumenterJs = "built/local/instrumenter.js";
gulp.task(instrumenterJs, /*help*/ false, () => project.compile(instrumenterProject));
gulp.task("clean:" + instrumenterJs, /*help*/ false, () => project.clean(instrumenterProject));
gulp.task(`clean:${instrumenterJs}`, /*help*/ false, () => project.clean(instrumenterProject));
gulp.task(
"tsc-instrumented",
@@ -479,20 +502,37 @@ gulp.task(
gulp.task(
"watch-tsc",
/*help*/ false,
["watch-diagnostics", "watch-lib", typescriptServicesJs],
() => project.watch(tscProject, { typescript: "built" }));
["watch-diagnostics", "watch-lib"].concat(useCompilerDeps),
() => project.watch(tscProject, { typescript: useCompiler }));
const watchServicesPatterns = [
"src/compiler/**/*",
"src/jsTypings/**/*",
"src/services/**/*"
];
gulp.task(
"watch-services",
/*help*/ false,
["watch-diagnostics", "watch-lib", typescriptServicesJs],
() => project.watch(servicesProject, { typescript: "built" }));
["watch-diagnostics", "watch-lib"],
() => gulp.watch(watchServicesPatterns, ["services"]));
const watchLsslPatterns = [
...watchServicesPatterns,
"src/server/**/*",
"src/tsserver/tsconfig.json"
];
gulp.task(
"watch-lssl",
/*help*/ false,
() => gulp.watch(watchLsslPatterns, ["lssl"]));
gulp.task(
"watch-server",
/*help*/ false,
["watch-diagnostics", "watch-lib", typescriptServicesJs],
() => project.watch(tsserverProject, { typescript: "built" }));
["watch-diagnostics", "watch-lib"].concat(useCompilerDeps),
() => project.watch(tsserverProject, { typescript: useCompiler }));
gulp.task(
"watch-local",
@@ -500,22 +540,64 @@ gulp.task(
["watch-lib", "watch-tsc", "watch-services", "watch-server"]);
gulp.task(
"watch",
"Watches for changes to the build inputs for built/local/run.js executes runtests-parallel.",
[typescriptServicesJs],
() => project.watch(testRunnerProject, { typescript: "built" }, ["runtests-parallel"]));
"watch-runner",
/*help*/ false,
useCompilerDeps,
() => project.watch(testRunnerProject, { typescript: useCompiler }));
gulp.task("clean-built", /*help*/ false, ["clean:" + diagnosticInformationMapTs], () => del(["built"]));
const watchPatterns = [
runJs,
typescriptDts,
tsserverlibraryDts
];
gulp.task(
"watch",
"Watches for changes to the build inputs for built/local/run.js, then executes runtests-parallel.",
["build-rules", "watch-runner", "watch-services", "watch-lssl"],
() => {
/** @type {CancelSource | undefined} */
let runTestsSource;
const fn = debounce(() => {
runTests().catch(error => {
if (error instanceof CancelError) {
log.warn("Operation was canceled");
}
else {
log.error(error);
}
});
}, /*timeout*/ 100, { max: 500 });
gulp.watch(watchPatterns, () => project.wait().then(fn));
// NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file
const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/;
fs.watch("tests/cases", { recursive: true }, (_, file) => {
if (testFilePattern.test(file)) project.wait().then(fn);
});
function runTests() {
if (runTestsSource) runTestsSource.cancel();
runTestsSource = new CancelSource();
return cmdLineOptions.tests || cmdLineOptions.failed
? runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, runTestsSource.token)
: runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, runTestsSource.token);
}
});
gulp.task("clean-built", /*help*/ false, [`clean:${diagnosticInformationMapTs}`], () => del(["built"]));
gulp.task(
"clean",
"Cleans the compiler output, declare files, and tests",
[
"clean:" + importDefinitelyTypedTestsJs,
"clean:" + webtscJs,
"clean:" + perftscJs,
"clean:" + instrumenterJs,
"clean:" + webTestServerJs,
"clean-scripts",
`clean:${importDefinitelyTypedTestsJs}`,
`clean:${webtscJs}`,
`clean:${perftscJs}`,
`clean:${instrumenterJs}`,
`clean:${webTestServerJs}`,
"clean:scripts",
"clean-rules",
"clean-built"
]);
+150 -50
View File
@@ -9,6 +9,9 @@ const fold = require("travis-fold");
const ts = require("./lib/typescript");
const del = require("del");
const getDirSize = require("./scripts/build/getDirSize");
const { base64VLQFormatEncode } = require("./scripts/build/sourcemaps");
const needsUpdate = require("./scripts/build/needsUpdate");
const { flatten } = require("./scripts/build/project");
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
@@ -64,9 +67,14 @@ Paths.typesMapOutput = "built/local/typesMap.json";
Paths.typescriptFile = "built/local/typescript.js";
Paths.servicesFile = "built/local/typescriptServices.js";
Paths.servicesDefinitionFile = "built/local/typescriptServices.d.ts";
Paths.servicesOutFile = "built/local/typescriptServices.out.js";
Paths.servicesDefinitionOutFile = "built/local/typescriptServices.out.d.ts";
Paths.typescriptDefinitionFile = "built/local/typescript.d.ts";
Paths.typescriptStandaloneDefinitionFile = "built/local/typescript_standalone.d.ts";
Paths.tsserverLibraryFile = "built/local/tsserverlibrary.js";
Paths.tsserverLibraryDefinitionFile = "built/local/tsserverlibrary.d.ts";
Paths.tsserverLibraryOutFile = "built/local/tsserverlibrary.out.js";
Paths.tsserverLibraryDefinitionOutFile = "built/local/tsserverlibrary.out.d.ts";
Paths.baselines = {};
Paths.baselines.local = "tests/baselines/local";
Paths.baselines.localTest262 = "tests/baselines/test262/local";
@@ -101,7 +109,9 @@ const ConfigFileFor = {
runjs: "src/testRunner",
lint: "scripts/tslint",
scripts: "scripts",
all: "src"
all: "src",
typescriptServices: "built/local/typescriptServices.tsconfig.json",
tsserverLibrary: "built/local/tsserverlibrary.tsconfig.json",
};
const ExpectedLKGFiles = [
@@ -124,13 +134,18 @@ desc("Builds the full compiler and services");
task(TaskNames.local, [
TaskNames.buildFoldStart,
TaskNames.coreBuild,
Paths.servicesDefinitionFile,
Paths.typescriptFile,
Paths.typescriptDefinitionFile,
Paths.typescriptStandaloneDefinitionFile,
Paths.tsserverLibraryDefinitionFile,
TaskNames.localize,
TaskNames.buildFoldEnd
]);
task("default", [TaskNames.local]);
const RunTestsPrereqs = [TaskNames.lib, Paths.servicesDefinitionFile, Paths.tsserverLibraryDefinitionFile];
const RunTestsPrereqs = [TaskNames.lib, Paths.servicesDefinitionFile, Paths.typescriptDefinitionFile, Paths.tsserverLibraryDefinitionFile];
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
task(TaskNames.runtestsParallel, RunTestsPrereqs, function () {
tsbuild([ConfigFileFor.runjs], true, () => {
@@ -172,6 +187,9 @@ task(TaskNames.lkg, [
TaskNames.release,
TaskNames.local,
Paths.servicesDefinitionFile,
Paths.typescriptFile,
Paths.typescriptDefinitionFile,
Paths.typescriptStandaloneDefinitionFile,
Paths.tsserverLibraryDefinitionFile,
Paths.releaseCompiler,
...libraryTargets
@@ -333,64 +351,146 @@ file(Paths.diagnosticInformationMap, [Paths.diagnosticMessagesJson], function ()
});
}, { async: true });
// tsserverlibrary.d.ts
file(Paths.tsserverLibraryDefinitionFile, [TaskNames.coreBuild], function() {
const sources = ["compiler.d.ts", "jsTyping.d.ts", "services.d.ts", "server.d.ts"].map(f => path.join(Paths.builtLocal, f));
let output = "";
for (const f of sources) {
output = output + "\n" + removeConstModifierFromEnumDeclarations(readFileSync(f));
}
output = output + "\nexport = ts;\nexport as namespace ts;";
fs.writeFileSync(Paths.tsserverLibraryDefinitionFile, output, { encoding: "utf-8" });
file(ConfigFileFor.tsserverLibrary, [], function () {
flatten("src/tsserver/tsconfig.json", ConfigFileFor.tsserverLibrary, {
exclude: ["src/tsserver/server.ts"],
compilerOptions: {
"removeComments": false,
"stripInternal": true,
"declarationMap": false,
"outFile": "tsserverlibrary.out.js"
}
})
});
// typescriptservices.d.ts
file(Paths.servicesDefinitionFile, [TaskNames.coreBuild], function() {
// Generate a config file
const files = [];
recur(`src/services/tsconfig.json`);
// tsserverlibrary.js
// tsserverlibrary.d.ts
file(Paths.tsserverLibraryFile, [TaskNames.coreBuild, ConfigFileFor.tsserverLibrary], function() {
tsbuild(ConfigFileFor.tsserverLibrary, false, () => {
if (needsUpdate([Paths.tsserverLibraryOutFile, Paths.tsserverLibraryDefinitionOutFile], [Paths.tsserverLibraryFile, Paths.tsserverLibraryDefinitionFile])) {
const copyright = readFileSync(Paths.copyright);
const config = {
extends: "../../src/tsconfig-base",
let libraryDefinitionContent = readFileSync(Paths.tsserverLibraryDefinitionOutFile);
libraryDefinitionContent = copyright + removeConstModifierFromEnumDeclarations(libraryDefinitionContent);
libraryDefinitionContent += "\nexport = ts;\nexport as namespace ts;";
fs.writeFileSync(Paths.tsserverLibraryDefinitionFile, libraryDefinitionContent, "utf8");
let libraryContent = readFileSync(Paths.tsserverLibraryOutFile);
libraryContent = copyright + libraryContent;
fs.writeFileSync(Paths.tsserverLibraryFile, libraryContent, "utf8");
// adjust source map for tsserverlibrary.js
let libraryMapContent = readFileSync(Paths.tsserverLibraryOutFile + ".map");
const map = JSON.parse(libraryMapContent);
const lineStarts = /**@type {*}*/(ts).computeLineStarts(copyright);
let prependMappings = "";
for (let i = 1; i < lineStarts.length; i++) {
prependMappings += ";";
}
const offset = copyright.length - lineStarts[lineStarts.length - 1];
if (offset > 0) {
prependMappings += base64VLQFormatEncode(offset) + ",";
}
const outputMap = {
version: map.version,
file: map.file,
sources: map.sources,
sourceRoot: map.sourceRoot,
mappings: prependMappings + map.mappings,
names: map.names,
sourcesContent: map.sourcesContent
};
libraryMapContent = JSON.stringify(outputMap);
fs.writeFileSync(Paths.tsserverLibraryFile + ".map", libraryMapContent);
}
complete();
});
}, { async: true });
task(Paths.tsserverLibraryDefinitionFile, [Paths.tsserverLibraryFile]);
file(ConfigFileFor.typescriptServices, [], function () {
flatten("src/services/tsconfig.json", ConfigFileFor.typescriptServices, {
compilerOptions: {
"removeComments": false,
"stripInternal": true,
"outFile": "typescriptServices.js"
},
files
};
"declarationMap": false,
"outFile": "typescriptServices.out.js"
}
});
});
const configFilePath = `built/local/typescriptServices.tsconfig.json`;
fs.writeFileSync(configFilePath, JSON.stringify(config, undefined, 2));
tsbuild(configFilePath, false, () => {
const servicesContent = readFileSync(Paths.servicesDefinitionFile);
const servicesContentWithoutConstEnums = removeConstModifierFromEnumDeclarations(servicesContent);
fs.writeFileSync(Paths.servicesDefinitionFile, servicesContentWithoutConstEnums);
// Also build typescript.js, typescript.js.map, and typescript.d.ts
// typescriptServices.js
// typescriptServices.d.ts
file(Paths.servicesFile, [TaskNames.coreBuild, ConfigFileFor.typescriptServices], function() {
tsbuild(ConfigFileFor.typescriptServices, false, () => {
if (needsUpdate([Paths.servicesOutFile, Paths.servicesDefinitionOutFile], [Paths.servicesFile, Paths.servicesDefinitionFile])) {
const copyright = readFileSync(Paths.copyright);
let servicesDefinitionContent = readFileSync(Paths.servicesDefinitionOutFile);
servicesDefinitionContent = copyright + removeConstModifierFromEnumDeclarations(servicesDefinitionContent);
fs.writeFileSync(Paths.servicesDefinitionFile, servicesDefinitionContent, "utf8");
let servicesContent = readFileSync(Paths.servicesOutFile);
servicesContent = copyright + servicesContent;
fs.writeFileSync(Paths.servicesFile, servicesContent, "utf8");
// adjust source map for typescriptServices.js
let servicesMapContent = readFileSync(Paths.servicesOutFile + ".map");
const map = JSON.parse(servicesMapContent);
const lineStarts = /**@type {*}*/(ts).computeLineStarts(copyright);
let prependMappings = "";
for (let i = 1; i < lineStarts.length; i++) {
prependMappings += ";";
}
const offset = copyright.length - lineStarts[lineStarts.length - 1];
if (offset > 0) {
prependMappings += base64VLQFormatEncode(offset) + ",";
}
const outputMap = {
version: map.version,
file: map.file,
sources: map.sources,
sourceRoot: map.sourceRoot,
mappings: prependMappings + map.mappings,
names: map.names,
sourcesContent: map.sourcesContent
};
servicesMapContent = JSON.stringify(outputMap);
fs.writeFileSync(Paths.servicesFile + ".map", servicesMapContent);
}
complete();
});
}, { async: true });
task(Paths.servicesDefinitionFile, [Paths.servicesFile]);
// typescript.js
// typescript.d.ts
file(Paths.typescriptFile, [Paths.servicesFile], function() {
if (needsUpdate([Paths.servicesFile, Paths.servicesDefinitionFile], [Paths.typescriptFile, Paths.typescriptDefinitionFile])) {
jake.cpR(Paths.servicesFile, Paths.typescriptFile);
if (fs.existsSync(Paths.servicesFile + ".map")) {
jake.cpR(Paths.servicesFile + ".map", Paths.typescriptFile + ".map");
}
fs.writeFileSync(Paths.typescriptDefinitionFile, servicesContentWithoutConstEnums + "\r\nexport = ts", { encoding: "utf-8" });
// And typescript_standalone.d.ts
fs.writeFileSync(Paths.typescriptStandaloneDefinitionFile, servicesContentWithoutConstEnums.replace(/declare (namespace|module) ts(\..+)? \{/g, 'declare module "typescript" {'), { encoding: "utf-8"});
complete();
});
function recur(configPath) {
const cfgFile = readJson(configPath);
if (cfgFile.references) {
for (const ref of cfgFile.references) {
recur(path.join(path.dirname(configPath), ref.path, "tsconfig.json"));
}
}
for (const file of cfgFile.files) {
files.push(path.join(`../../`, path.dirname(configPath), file));
}
const content = readFileSync(Paths.servicesDefinitionFile);
fs.writeFileSync(Paths.typescriptDefinitionFile, content + "\r\nexport = ts;", { encoding: "utf-8" });
}
}, { async: true });
});
task(Paths.typescriptDefinitionFile, [Paths.typescriptFile]);
// typescript_standalone.d.ts
file(Paths.typescriptStandaloneDefinitionFile, [Paths.servicesDefinitionFile], function() {
if (needsUpdate(Paths.servicesDefinitionFile, Paths.typescriptStandaloneDefinitionFile)) {
const content = readFileSync(Paths.servicesDefinitionFile);
fs.writeFileSync(Paths.typescriptStandaloneDefinitionFile, content.replace(/declare (namespace|module) ts(\..+)? \{/g, 'declare module "typescript" {'), { encoding: "utf-8"});
}
});
function getLibraryTargets() {
/** @type {{ libs: string[], paths?: Record<string, string>, sources?: Record<string, string[]> }} */
@@ -765,4 +865,4 @@ function getDiffTool() {
*/
function removeConstModifierFromEnumDeclarations(text) {
return text.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
}
}
+15 -101
View File
@@ -1,120 +1,34 @@
// @ts-check
const Browserify = require("browserify");
const Vinyl = require("vinyl");
const fs = require("fs");
const path = require("path");
const convertMap = require("convert-source-map");
const applySourceMap = require("vinyl-sourcemaps-apply");
const { Transform, Readable } = require("stream");
const browserify = require("browserify");
const Vinyl = require("./vinyl");
const { Transform } = require("stream");
const { streamFromFile } = require("./utils");
const { replaceContents } = require("./sourcemaps");
module.exports = browserify;
module.exports = browserifyFile;
/**
* @param {import("browserify").Options} [opts]
*/
function browserify(opts) {
function browserifyFile(opts) {
return new Transform({
objectMode: true,
/**
* @param {string | Buffer | File} input
* @param {string | Buffer | Vinyl} input
*/
transform(input, _, cb) {
if (typeof input === "string" || Buffer.isBuffer(input)) return cb(new Error("Only Vinyl files are supported."));
try {
const sourceMap = input.sourceMap;
const cwd = input.cwd || process.cwd();
const base = input.base || cwd;
const output = /**@type {File}*/(new Vinyl({ path: input.path, base: input.base }));
const stream = streamFromFile(input);
const b = new Browserify(Object.assign({}, opts, { debug: !!sourceMap, basedir: input.base }));
b.add(stream, { file: input.path, basedir: input.base });
b.bundle((err, contents) => {
if (err) return cb(err);
output.contents = contents;
if (sourceMap) {
output.sourceMap = typeof sourceMap === "string" ? JSON.parse(sourceMap) : sourceMap;
const sourceRoot = output.sourceMap.sourceRoot;
makeAbsoluteSourceMap(cwd, base, output.sourceMap);
const stringContents = contents.toString("utf8");
const newSourceMapConverter = convertMap.fromSource(stringContents);
if (newSourceMapConverter) {
const newSourceMap = newSourceMapConverter.toObject();
makeAbsoluteSourceMap(cwd, base, newSourceMap);
applySourceMap(output, newSourceMap);
makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap);
output.contents = new Buffer(convertMap.removeComments(stringContents), "utf8");
}
}
cb(null, output);
});
browserify(Object.assign({}, opts, { debug: !!input.sourceMap, basedir: input.base }))
.add(streamFromFile(input), { file: input.path, basedir: input.base })
.bundle((err, contents) => {
if (err) return cb(err);
cb(null, replaceContents(input, contents));
});
}
catch (e) {
cb(e);
}
}
});
}
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {RawSourceMap} sourceMap
*
* @typedef RawSourceMap
* @property {string} version
* @property {string} file
* @property {string} [sourceRoot]
* @property {string[]} sources
* @property {string[]} [sourcesContents]
* @property {string} mappings
* @property {string[]} [names]
*/
function makeAbsoluteSourceMap(cwd = process.cwd(), base = "", sourceMap) {
const sourceRoot = sourceMap.sourceRoot || "";
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.resolve(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.resolve(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = "";
}
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {string} sourceRoot
* @param {RawSourceMap} sourceMap
*/
function makeRelativeSourceMap(cwd = process.cwd(), base = "", sourceRoot, sourceMap) {
makeAbsoluteSourceMap(cwd, base, sourceMap);
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.relative(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.relative(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = sourceRoot;
}
/**
* @param {File} file
*/
function streamFromFile(file) {
return file.isBuffer() ? streamFromBuffer(file.contents) :
file.isStream() ? file.contents :
fs.createReadStream(file.path, { autoClose: true });
}
/**
* @param {Buffer} buffer
*/
function streamFromBuffer(buffer) {
return new Readable({
read() {
this.push(buffer);
this.push(null);
}
});
}
/**
* @typedef {import("vinyl") & { sourceMap?: any }} File
*/
void 0;
}
+71
View File
@@ -0,0 +1,71 @@
// @ts-check
const symSource = Symbol("CancelToken.source");
const symToken = Symbol("CancelSource.token");
const symCancellationRequested = Symbol("CancelSource.cancellationRequested");
const symCancellationCallbacks = Symbol("CancelSource.cancellationCallbacks");
class CancelSource {
constructor() {
this[symCancellationRequested] = false;
this[symCancellationCallbacks] = [];
}
/** @type {CancelToken} */
get token() {
return this[symToken] || (this[symToken] = new CancelToken(this));
}
cancel() {
if (!this[symCancellationRequested]) {
this[symCancellationRequested] = true;
for (const callback of this[symCancellationCallbacks]) {
callback();
}
}
}
}
exports.CancelSource = CancelSource;
class CancelToken {
/**
* @param {CancelSource} source
*/
constructor(source) {
if (source[symToken]) return source[symToken];
this[symSource] = source;
}
/** @type {boolean} */
get cancellationRequested() {
return this[symSource][symCancellationRequested];
}
/**
* @param {() => void} callback
*/
subscribe(callback) {
const source = this[symSource];
if (source[symCancellationRequested]) {
callback();
return;
}
source[symCancellationCallbacks].push(callback);
return {
unsubscribe() {
const index = source[symCancellationCallbacks].indexOf(callback);
if (index !== -1) source[symCancellationCallbacks].splice(index, 1);
}
};
}
}
exports.CancelToken = CancelToken;
class CancelError extends Error {
constructor(message = "Operation was canceled") {
super(message);
this.name = "CancelError";
}
}
exports.CancelError = CancelError;
+31
View File
@@ -0,0 +1,31 @@
// @ts-check
module.exports = debounce;
/**
* @param {() => void} cb
* @param {number} timeout
* @param {DebounceOptions} [opts]
*
* @typedef DebounceOptions
* @property {number} [max]
*/
function debounce(cb, timeout, opts = {}) {
if (timeout < 10) timeout = 10;
let max = opts.max || 10;
if (max < timeout) max = timeout;
let minTimer;
let maxTimer;
return trigger;
function trigger() {
if (max > timeout && !maxTimer) maxTimer = setTimeout(done, max);
if (minTimer) clearTimeout(minTimer);
minTimer = setTimeout(done, timeout);
}
function done() {
if (maxTimer) maxTimer = void clearTimeout(maxTimer);
if (minTimer) minTimer = void clearTimeout(minTimer);
cb();
}
}
+16 -3
View File
@@ -3,6 +3,7 @@ const cp = require("child_process");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const isWin = /^win/.test(process.platform);
const chalk = require("./chalk");
const { CancelToken, CancelError } = require("./cancellation");
module.exports = exec;
@@ -10,8 +11,11 @@ module.exports = exec;
* Executes the provided command once with the supplied arguments.
* @param {string} cmd
* @param {string[]} args
* @param {object} [options]
* @param {boolean} [options.ignoreExitCode]
* @param {ExecOptions} [options]
*
* @typedef ExecOptions
* @property {boolean} [ignoreExitCode]
* @property {CancelToken} [cancelToken]
*/
function exec(cmd, args, options = {}) {
return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => {
@@ -20,7 +24,13 @@ function exec(cmd, args, options = {}) {
const subshellFlag = isWin ? "/c" : "-c";
const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true });
const subscription = options.cancelToken && options.cancelToken.subscribe(() => {
ex.kill("SIGINT");
ex.kill("SIGTERM");
reject(new CancelError());
});
ex.on("exit", exitCode => {
subscription && subscription.unsubscribe();
if (exitCode === 0 || options.ignoreExitCode) {
resolve({ exitCode });
}
@@ -28,7 +38,10 @@ function exec(cmd, args, options = {}) {
reject(new Error(`Process exited with code: ${exitCode}`));
}
});
ex.on("error", reject);
ex.on("error", error => {
subscription && subscription.unsubscribe();
reject(error);
});
}));
}
+7 -3
View File
@@ -4,7 +4,7 @@ const os = require("os");
/** @type {CommandLineOptions} */
module.exports = minimist(process.argv.slice(2), {
boolean: ["debug", "inspect", "light", "colors", "lint", "soft", "fix", "failed", "keepFailed"],
boolean: ["debug", "dirty", "inspect", "light", "colors", "lint", "lkg", "soft", "fix", "failed", "keepFailed"],
string: ["browser", "tests", "host", "reporter", "stackTraceLimit", "timeout"],
alias: {
"b": "browser",
@@ -33,17 +33,21 @@ module.exports = minimist(process.argv.slice(2), {
fix: process.env.fix || process.env.f,
workers: process.env.workerCount || os.cpus().length,
failed: false,
keepFailed: false
keepFailed: false,
lkg: false,
dirty: false
}
});
/**
* @typedef TypedOptions
* @property {boolean} debug
* @property {boolean} dirty
* @property {boolean} inspect
* @property {boolean} light
* @property {boolean} colors
* @property {boolean} lint
* @property {boolean} lkg
* @property {boolean} soft
* @property {boolean} fix
* @property {string} browser
@@ -56,7 +60,7 @@ module.exports = minimist(process.argv.slice(2), {
* @property {string|number} timeout
* @property {boolean} failed
* @property {boolean} keepFailed
*
*
* @typedef {import("minimist").ParsedArgs & TypedOptions} CommandLineOptions
*/
void 0;
+66
View File
@@ -0,0 +1,66 @@
// @ts-check
const stream = require("stream");
const Vinyl = require("./vinyl");
const ts = require("../../lib/typescript");
const fs = require("fs");
const { base64VLQFormatEncode } = require("./sourcemaps");
module.exports = exports = prepend;
/**
* @param {string | ((file: Vinyl) => string)} data
*/
function prepend(data) {
return new stream.Transform({
objectMode: true,
/**
* @param {string | Buffer | Vinyl} input
* @param {(error: Error, data?: any) => void} cb
*/
transform(input, _, cb) {
if (typeof input === "string" || Buffer.isBuffer(input)) return cb(new Error("Only Vinyl files are supported."));
if (!input.isBuffer()) return cb(new Error("Streams not supported."));
try {
const output = input.clone();
const prependContent = typeof data === "function" ? data(input) : data;
output.contents = Buffer.concat([Buffer.from(prependContent, "utf8"), input.contents]);
if (input.sourceMap) {
if (typeof input.sourceMap === "string") input.sourceMap = /**@type {import("./sourcemaps").RawSourceMap}*/(JSON.parse(input.sourceMap));
const lineStarts = /**@type {*}*/(ts).computeLineStarts(prependContent);
let prependMappings = "";
for (let i = 1; i < lineStarts.length; i++) {
prependMappings += ";";
}
const offset = prependContent.length - lineStarts[lineStarts.length - 1];
if (offset > 0) {
prependMappings += base64VLQFormatEncode(offset) + ",";
}
output.sourceMap = {
version: input.sourceMap.version,
file: input.sourceMap.file,
sources: input.sourceMap.sources,
sourceRoot: input.sourceMap.sourceRoot,
mappings: prependMappings + input.sourceMap.mappings,
names: input.names,
sourcesContent: input.sourcesContent
};
}
return cb(null, output);
}
catch (e) {
return cb(e);
}
}
})
}
exports.prepend = prepend;
/**
* @param {string | ((file: Vinyl) => string)} file
*/
function prependFile(file) {
const data = typeof file === "string" ? fs.readFileSync(file, "utf8") :
vinyl => fs.readFileSync(file(vinyl), "utf8");
return prepend(data)
}
exports.file = prependFile;
+21
View File
@@ -209,6 +209,27 @@ function flatten(projectSpec, flattenedProjectSpec, options = {}) {
}
exports.flatten = flatten;
/**
* Returns a Promise that resolves when all pending build tasks have completed
*/
function wait() {
return new Promise(resolve => {
if (compilationGulp.allDone()) {
resolve();
}
else {
const onDone = () => {
compilationGulp.removeListener("onDone", onDone);
compilationGulp.removeListener("err", onDone);
resolve();
};
compilationGulp.on("stop", onDone);
compilationGulp.on("err", onDone);
}
});
}
exports.wait = wait;
/**
* Resolve a TypeScript specifier into a fully-qualified module specifier and any requisite dependencies.
* @param {string} typescript An unresolved module specifier to a TypeScript version.
+143
View File
@@ -0,0 +1,143 @@
// @ts-check
const path = require("path");
const Vinyl = require("./vinyl");
const convertMap = require("convert-source-map");
const applySourceMap = require("vinyl-sourcemaps-apply");
const through2 = require("through2");
/**
* @param {Vinyl} input
* @param {string | Buffer} contents
* @param {string | RawSourceMap} [sourceMap]
*/
function replaceContents(input, contents, sourceMap) {
const output = input.clone();
output.contents = typeof contents === "string" ? Buffer.from(contents, "utf8") : contents;
if (input.sourceMap) {
output.sourceMap = typeof input.sourceMap === "string" ? /**@type {RawSourceMap}*/(JSON.parse(input.sourceMap)) : input.sourceMap;
if (typeof sourceMap === "string") {
sourceMap = /**@type {RawSourceMap}*/(JSON.parse(sourceMap));
}
else if (sourceMap === undefined) {
const stringContents = typeof contents === "string" ? contents : contents.toString("utf8");
const newSourceMapConverter = convertMap.fromSource(stringContents);
if (newSourceMapConverter) {
sourceMap = /**@type {RawSourceMap}*/(newSourceMapConverter.toObject());
output.contents = new Buffer(convertMap.removeMapFileComments(stringContents), "utf8");
}
}
if (sourceMap) {
const cwd = input.cwd || process.cwd();
const base = input.base || cwd;
const sourceRoot = output.sourceMap.sourceRoot;
makeAbsoluteSourceMap(cwd, base, output.sourceMap);
makeAbsoluteSourceMap(cwd, base, sourceMap);
applySourceMap(output, sourceMap);
makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap);
}
else {
output.sourceMap = undefined;
}
}
return output;
}
exports.replaceContents = replaceContents;
function removeSourceMaps() {
return through2.obj((/**@type {Vinyl}*/file, _, cb) => {
if (file.sourceMap && file.isBuffer()) {
file.contents = Buffer.from(convertMap.removeMapFileComments(file.contents.toString("utf8")), "utf8");
file.sourceMap = undefined;
}
cb(null, file);
});
}
exports.removeSourceMaps = removeSourceMaps;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {RawSourceMap} sourceMap
*
* @typedef RawSourceMap
* @property {string} version
* @property {string} file
* @property {string} [sourceRoot]
* @property {string[]} sources
* @property {string[]} [sourcesContent]
* @property {string} mappings
* @property {string[]} [names]
*/
function makeAbsoluteSourceMap(cwd = process.cwd(), base = "", sourceMap) {
const sourceRoot = sourceMap.sourceRoot || "";
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.resolve(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.resolve(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = "";
}
exports.makeAbsoluteSourceMap = makeAbsoluteSourceMap;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {string} sourceRoot
* @param {RawSourceMap} sourceMap
*/
function makeRelativeSourceMap(cwd = process.cwd(), base = "", sourceRoot, sourceMap) {
makeAbsoluteSourceMap(cwd, base, sourceMap);
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.relative(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.relative(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = sourceRoot;
}
exports.makeRelativeSourceMap = makeRelativeSourceMap;
/**
* @param {string} message
* @returns {never}
*/
function fail(message) {
throw new Error(message);
}
/**
* @param {number} value
*/
function base64FormatEncode(value) {
return value < 0 ? fail("Invalid value") :
value < 26 ? 0x41 /*A*/ + value :
value < 52 ? 0x61 /*a*/ + value - 26 :
value < 62 ? 0x30 /*0*/ + value - 52 :
value === 62 ? 0x2B /*+*/ :
value === 63 ? 0x2F /*/*/ :
fail("Invalid value");
}
/**
* @param {number} value
*/
function base64VLQFormatEncode(value) {
if (value < 0) {
value = ((-value) << 1) + 1;
}
else {
value = value << 1;
}
// Encode 5 bits at a time starting from least significant bits
let result = "";
do {
let currentDigit = value & 31; // 11111
value = value >> 5;
if (value > 0) {
// There are still more digits to decode, set the msb (6th bit)
currentDigit = currentDigit | 32;
}
result += String.fromCharCode(base64FormatEncode(currentDigit));
} while (value > 0);
return result;
}
exports.base64VLQFormatEncode = base64VLQFormatEncode;
+108 -106
View File
@@ -1,4 +1,5 @@
// @ts-check
const gulp = require("./gulp");
const del = require("del");
const fs = require("fs");
const os = require("os");
@@ -6,13 +7,8 @@ const path = require("path");
const mkdirP = require("./mkdirp");
const cmdLineOptions = require("./options");
const exec = require("./exec");
const runSequence = require("run-sequence");
const finished = require("./finished");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const nodeModulesPathPrefix = path.resolve("./node_modules/.bin/");
const isWin = /^win/.test(process.platform);
const mocha = path.join(nodeModulesPathPrefix, "mocha") + (isWin ? ".cmd" : "");
const mochaJs = require.resolve("mocha/bin/_mocha");
exports.localBaseline = "tests/baselines/local/";
exports.refBaseline = "tests/baselines/reference/";
@@ -24,8 +20,10 @@ exports.localTest262Baseline = "internal/baselines/test262/local";
* @param {string} runJs
* @param {string} defaultReporter
* @param {boolean} runInParallel
* @param {boolean} watchMode
* @param {InstanceType<typeof import("./cancellation").CancelToken>} [cancelToken]
*/
function runConsoleTests(runJs, defaultReporter, runInParallel) {
async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, cancelToken) {
let testTimeout = cmdLineOptions.timeout;
let tests = cmdLineOptions.tests;
const lintFlag = cmdLineOptions.lint;
@@ -36,112 +34,116 @@ function runConsoleTests(runJs, defaultReporter, runInParallel) {
const stackTraceLimit = cmdLineOptions.stackTraceLimit;
const testConfigFile = "test.config";
const failed = cmdLineOptions.failed;
const keepFailed = cmdLineOptions.keepFailed || failed;
return cleanTestDirs()
.then(() => {
if (fs.existsSync(testConfigFile)) {
fs.unlinkSync(testConfigFile);
}
let workerCount, taskConfigsFolder;
if (runInParallel) {
// generate name to store task configuration files
const prefix = os.tmpdir() + "/ts-tests";
let i = 1;
do {
taskConfigsFolder = prefix + i;
i++;
} while (fs.existsSync(taskConfigsFolder));
fs.mkdirSync(taskConfigsFolder);
workerCount = cmdLineOptions.workers;
}
if (tests && tests.toLocaleLowerCase() === "rwc") {
testTimeout = 400000;
}
if (tests || runners || light || testTimeout || taskConfigsFolder || keepFailed) {
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout, keepFailed);
}
const colors = cmdLineOptions.colors;
const reporter = cmdLineOptions.reporter || defaultReporter;
/** @type {string} */
let host = "node";
/** @type {string[]} */
let args = [];
// timeout normally isn"t necessary but Travis-CI has been timing out on compiler baselines occasionally
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
if (!runInParallel) {
args.push("-R", "scripts/failed-tests");
args.push("-O", '"reporter=' + reporter + (keepFailed ? ",keepFailed=true" : "") + '"');
if (tests) {
args.push("-g", `"${tests}"`);
}
if (colors) {
args.push("--colors");
}
else {
args.push("--no-colors");
}
if (inspect) {
args.unshift("--inspect-brk");
}
else if (debug) {
args.unshift("--debug-brk");
}
else {
args.push("-t", "" + testTimeout);
}
args.push(runJs);
host = mocha;
}
else {
// run task to load all tests and partition them between workers
host = "node";
args.push(runJs);
}
setNodeEnvToDevelopment();
if (failed) {
return exec(host, ["scripts/run-failed-tests.js"].concat(args));
}
else {
return exec(host, args);
}
})
.then(({ exitCode }) => {
if (exitCode !== 0) return finish(undefined, exitCode);
if (lintFlag) return finished(runSequence("lint")).then(() => finish(), finish);
return finish();
}, finish);
/**
* @param {any=} error
* @param {number=} errorStatus
*/
function finish(error, errorStatus) {
restoreSavedNodeEnv();
return deleteTestConfig()
.then(deleteTemporaryProjectOutput)
.then(() => {
if (error !== undefined || errorStatus !== undefined) {
process.exit(typeof errorStatus === "number" ? errorStatus : 2);
}
});
const keepFailed = cmdLineOptions.keepFailed;
if (!cmdLineOptions.dirty) {
await cleanTestDirs();
}
function deleteTestConfig() {
return del("test.config");
if (fs.existsSync(testConfigFile)) {
fs.unlinkSync(testConfigFile);
}
let workerCount, taskConfigsFolder;
if (runInParallel) {
// generate name to store task configuration files
const prefix = os.tmpdir() + "/ts-tests";
let i = 1;
do {
taskConfigsFolder = prefix + i;
i++;
} while (fs.existsSync(taskConfigsFolder));
fs.mkdirSync(taskConfigsFolder);
workerCount = cmdLineOptions.workers;
}
if (tests && tests.toLocaleLowerCase() === "rwc") {
testTimeout = 400000;
}
if (tests || runners || light || testTimeout || taskConfigsFolder || keepFailed) {
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout, keepFailed);
}
const colors = cmdLineOptions.colors;
const reporter = cmdLineOptions.reporter || defaultReporter;
/** @type {string[]} */
let args = [];
// timeout normally isn"t necessary but Travis-CI has been timing out on compiler baselines occasionally
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
if (!runInParallel) {
args.push(failed ? "scripts/run-failed-tests.js" : mochaJs);
args.push("-R", "scripts/failed-tests");
args.push("-O", '"reporter=' + reporter + (keepFailed ? ",keepFailed=true" : "") + '"');
if (tests) {
args.push("-g", `"${tests}"`);
}
if (colors) {
args.push("--colors");
}
else {
args.push("--no-colors");
}
if (inspect) {
args.unshift("--inspect-brk");
}
else if (debug) {
args.unshift("--debug-brk");
}
else {
args.push("-t", "" + testTimeout);
}
args.push(runJs);
}
else {
// run task to load all tests and partition them between workers
args.push(runJs);
}
/** @type {number | undefined} */
let errorStatus;
/** @type {Error | undefined} */
let error;
try {
setNodeEnvToDevelopment();
const { exitCode } = await exec("node", args, { cancelToken });
if (exitCode !== 0) {
errorStatus = exitCode;
error = new Error(`Process exited with status code ${errorStatus}.`);
}
else if (lintFlag) {
await new Promise((resolve, reject) => gulp.start(["lint"], error => error ? reject(error) : resolve()));
}
}
catch (e) {
errorStatus = undefined;
error = e;
}
finally {
restoreSavedNodeEnv();
}
await del("test.config");
await deleteTemporaryProjectOutput();
if (error !== undefined) {
if (watchMode) {
throw error;
}
else {
log.error(error);
process.exit(typeof errorStatus === "number" ? errorStatus : 2);
}
}
}
exports.runConsoleTests = runConsoleTests;
function cleanTestDirs() {
return del([exports.localBaseline, exports.localRwcBaseline,])
return del([exports.localBaseline, exports.localRwcBaseline])
.then(() => mkdirP(exports.localRwcBaseline))
.then(() => mkdirP(exports.localBaseline));
}
+27
View File
@@ -0,0 +1,27 @@
// @ts-check
const fs = require("fs");
const File = require("./vinyl");
const { Readable } = require("stream");
/**
* @param {File} file
*/
function streamFromFile(file) {
return file.isBuffer() ? streamFromBuffer(file.contents) :
file.isStream() ? file.contents :
fs.createReadStream(file.path, { autoClose: true });
}
exports.streamFromFile = streamFromFile;
/**
* @param {Buffer} buffer
*/
function streamFromBuffer(buffer) {
return new Readable({
read() {
this.push(buffer);
this.push(null);
}
});
}
exports.streamFromBuffer = streamFromBuffer;
+60
View File
@@ -0,0 +1,60 @@
// NOTE: This makes it possible to correctly type vinyl Files under @ts-check.
export = File;
declare class File<T extends File.Contents = File.Contents> {
constructor(options?: File.VinylOptions<T>);
cwd: string;
base: string;
path: string;
readonly history: ReadonlyArray<string>;
contents: T;
relative: string;
dirname: string;
basename: string;
stem: string;
extname: string;
symlink: string | null;
stat: import("fs").Stats | null;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
isBuffer(): this is T extends Buffer ? File<Buffer> : never;
isStream(): this is T extends NodeJS.ReadableStream ? File<NodeJS.ReadableStream> : never;
isNull(): this is T extends null ? File<null> : never;
isDirectory(): this is T extends null ? File.Directory : never;
isSymbolic(): this is T extends null ? File.Symbolic : never;
clone(opts?: { contents?: boolean, deep?: boolean }): this;
}
namespace File {
export interface VinylOptions<T extends Contents = Contents> {
cwd?: string;
base?: string;
path?: string;
history?: ReadonlyArray<string>;
stat?: import("fs").Stats;
contents?: T;
sourceMap?: import("./sourcemaps").RawSourceMap | string;
[custom: string]: any;
}
export type Contents = Buffer | NodeJS.ReadableStream | null;
export type File = import("./vinyl");
export type NullFile = File<null>;
export type BufferFile = File<Buffer>;
export type StreamFile = File<NodeJS.ReadableStream>;
export interface Directory extends NullFile {
isNull(): true;
isDirectory(): true;
isSymbolic(): this is never;
}
export interface Symbolic extends NullFile {
isNull(): true;
isDirectory(): this is never;
isSymbolic(): true;
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = require("vinyl");
+42 -17
View File
@@ -4,9 +4,11 @@ const path = require("path");
const fs = require("fs");
const os = require("os");
const failingHookRegExp = /^(.*) "(before|after) (all|each)" hook$/;
/**
* .failed-tests reporter
*
*
* @typedef {Object} ReporterOptions
* @property {string} [file]
* @property {boolean} [keepFailed]
@@ -15,7 +17,7 @@ const os = require("os");
*/
class FailedTestsReporter extends Mocha.reporters.Base {
/**
* @param {Mocha.Runner} runner
* @param {Mocha.Runner} runner
* @param {{ reporterOptions?: ReporterOptions }} [options]
*/
constructor(runner, options) {
@@ -49,35 +51,58 @@ class FailedTestsReporter extends Mocha.reporters.Base {
/** @type {Mocha.Test[]} */
this.passes = [];
/** @type {Mocha.Test[]} */
/** @type {(Mocha.Test)[]} */
this.failures = [];
runner.on("pass", test => this.passes.push(test));
runner.on("fail", test => this.failures.push(test));
}
/**
* @param {string} file
* @param {ReadonlyArray<Mocha.Test>} passes
* @param {ReadonlyArray<Mocha.Test>} failures
* @param {boolean} keepFailed
* @param {(err?: NodeJS.ErrnoException) => void} done
* @param {string} file
* @param {ReadonlyArray<Mocha.Test>} passes
* @param {ReadonlyArray<Mocha.Test | Mocha.Hook>} failures
* @param {boolean} keepFailed
* @param {(err?: NodeJS.ErrnoException) => void} done
*/
static writeFailures(file, passes, failures, keepFailed, done) {
const failingTests = new Set(fs.existsSync(file) ? readTests() : undefined);
if (failingTests.size > 0) {
const possiblyPassingSuites = /**@type {Set<string>}*/(new Set());
// Remove tests that are now passing and track suites that are now
// possibly passing.
if (failingTests.size > 0 && !keepFailed) {
for (const test of passes) {
const title = test.fullTitle().trim();
if (title) failingTests.delete(title);
failingTests.delete(test.fullTitle().trim());
possiblyPassingSuites.add(test.parent.fullTitle().trim());
}
}
// Add tests that are now failing. If a hook failed, track its
// containing suite as failing. If the suite for a test or hook was
// possibly passing then it is now definitely failing.
for (const test of failures) {
const title = test.fullTitle().trim();
if (title) failingTests.add(title);
const suiteTitle = test.parent.fullTitle().trim();
if (test.type === "test") {
failingTests.add(test.fullTitle().trim());
}
else {
failingTests.add(suiteTitle);
}
possiblyPassingSuites.delete(suiteTitle);
}
// Remove all definitely passing suites.
for (const suite of possiblyPassingSuites) {
failingTests.delete(suite);
}
if (failingTests.size > 0) {
const failed = Array.from(failingTests).join(os.EOL);
const failed = Array
.from(failingTests)
.sort()
.join(os.EOL);
fs.writeFile(file, failed, "utf8", done);
}
else if (!keepFailed && fs.existsSync(file)) {
@@ -96,7 +121,7 @@ class FailedTestsReporter extends Mocha.reporters.Base {
}
/**
* @param {number} failures
* @param {number} failures
* @param {(failures: number) => void} [fn]
*/
done(failures, fn) {
+6 -5
View File
@@ -54,16 +54,17 @@ async function copyScriptOutputs() {
await copyWithCopyright("cancellationToken.js");
await copyWithCopyright("tsc.release.js", "tsc.js");
await copyWithCopyright("tsserver.js");
await copyWithCopyright("typescript.js");
await copyWithCopyright("typescriptServices.js");
await copyFromBuiltLocal("tsserverlibrary.js"); // copyright added by build
await copyFromBuiltLocal("typescript.js"); // copyright added by build
await copyFromBuiltLocal("typescriptServices.js"); // copyright added by build
await copyWithCopyright("typingsInstaller.js");
await copyWithCopyright("watchGuard.js");
}
async function copyDeclarationOutputs() {
await copyWithCopyright("tsserverlibrary.d.ts");
await copyWithCopyright("typescript.d.ts");
await copyWithCopyright("typescriptServices.d.ts");
await copyFromBuiltLocal("tsserverlibrary.d.ts"); // copyright added by build
await copyFromBuiltLocal("typescript.d.ts"); // copyright added by build
await copyFromBuiltLocal("typescriptServices.d.ts"); // copyright added by build
}
async function writeGitAttributes() {
+6 -1
View File
@@ -69,7 +69,12 @@ const proc = spawn(process.execPath, args, {
proc.on('exit', (code, signal) => {
process.on('exit', () => {
if (grepFile) {
fs.unlinkSync(grepFile);
try {
fs.unlinkSync(grepFile);
}
catch (e) {
if (e.code !== "ENOENT") throw e;
}
}
if (signal) {
+2 -2
View File
@@ -225,11 +225,11 @@ namespace ts {
node.symbol = symbol;
symbol.declarations = append(symbol.declarations, node);
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) {
symbol.exports = createSymbolTable();
}
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && !symbol.members) {
symbol.members = createSymbolTable();
}
+107 -39
View File
@@ -2417,12 +2417,12 @@ namespace ts {
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
function visit(symbol: Symbol | undefined): SymbolTable | undefined {
if (!(symbol && symbol.flags & SymbolFlags.HasExports && pushIfUnique(visitedSymbols, symbol))) {
if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) {
return;
}
const symbols = cloneMap(symbol.exports!);
const symbols = cloneMap(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports!.get(InternalSymbolName.ExportStar);
const exportStars = symbol.exports.get(InternalSymbolName.ExportStar);
if (exportStars) {
const nestedSymbols = createSymbolTable();
const lookupTable = createMap<ExportCollisionTracker>() as ExportCollisionTrackerTable;
@@ -7702,9 +7702,13 @@ namespace ts {
return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
}
function getRestTypeOfSignature(signature: Signature) {
function getRestTypeOfSignature(signature: Signature): Type {
return tryGetRestTypeOfSignature(signature) || anyType;
}
function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
const type = getTypeOfRestParameter(signature);
return type && getIndexTypeOfType(type, IndexKind.Number) || anyType;
return type && getIndexTypeOfType(type, IndexKind.Number);
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -19069,38 +19073,7 @@ namespace ts {
diagnostics.add(createDiagnosticForNode(node, fallbackError));
}
// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
// Pick the longest signature. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; }, b: number);
// f({ |
// Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
// declare function f<T>(k: keyof T);
// f<Foo>("
if (!produceDiagnostics) {
Debug.assert(candidates.length > 0); // Else would have exited above.
const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount);
const candidate = candidates[bestIndex];
const { typeParameters } = candidate;
if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217
while (typeArguments.length > typeParameters.length) {
typeArguments.pop();
}
while (typeArguments.length < typeParameters.length) {
typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
}
const instantiated = createSignatureInstantiation(candidate, typeArguments);
candidates[bestIndex] = instantiated;
return instantiated;
}
return candidate;
}
return resolveErrorCall(node);
return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
candidateForArgumentError = undefined;
@@ -19171,6 +19144,97 @@ namespace ts {
}
}
// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
function getCandidateForOverloadFailure(
node: CallLikeExpression,
candidates: Signature[],
args: ReadonlyArray<Expression>,
hasCandidatesOutArray: boolean,
): Signature {
Debug.assert(candidates.length > 0); // Else should not have called this.
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
// Don't do this if there is a `candidatesOutArray`,
// because then we want the chosen best candidate to be one of the overloads, not a combination.
return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
? pickLongestCandidateSignature(node, candidates, args)
: createUnionOfSignaturesForOverloadFailure(candidates);
}
function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
const thisParameters = mapDefined(candidates, c => c.thisParameter);
let thisParameter: Symbol | undefined;
if (thisParameters.length) {
thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
}
const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
const parameters: Symbol[] = [];
for (let i = 0; i < maxNonRestParam; i++) {
const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
i < parameters.length - 1 ? parameters[i] : last(parameters) :
i < parameters.length ? parameters[i] : undefined);
Debug.assert(symbols.length !== 0);
parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
}
const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
const hasRestParameter = restParameterSymbols.length !== 0;
if (hasRestParameter) {
const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
}
return createSignature(
candidates[0].declaration,
/*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
thisParameter,
parameters,
/*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
/*typePredicate*/ undefined,
minArgumentCount,
hasRestParameter,
/*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
}
function getNumNonRestParameters(signature: Signature): number {
const numParams = signature.parameters.length;
return signature.hasRestParameter ? numParams - 1 : numParams;
}
function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: Type[]): Symbol {
return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
}
function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
// This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
return createSymbolWithType(first(sources), type);
}
function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
// Pick the longest signature. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; }, b: number);
// f({ |
// Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
// declare function f<T>(k: keyof T);
// f<Foo>("
const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
const candidate = candidates[bestIndex];
const { typeParameters } = candidate;
if (!typeParameters) {
return candidate;
}
const typeArgumentNodes: ReadonlyArray<TypeNode> = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray;
const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType);
while (typeArguments.length > typeParameters.length) {
typeArguments.pop();
}
while (typeArguments.length < typeParameters.length) {
typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
}
const instantiated = createSignatureInstantiation(candidate, typeArguments);
candidates[bestIndex] = instantiated;
return instantiated;
}
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
let maxParamsIndex = -1;
let maxParams = -1;
@@ -19955,6 +20019,10 @@ namespace ts {
}
function getTypeAtPosition(signature: Signature, pos: number): Type {
return tryGetTypeAtPosition(signature, pos) || anyType;
}
function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
const paramCount = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
if (pos < paramCount) {
return getTypeOfParameter(signature.parameters[pos]);
@@ -19970,9 +20038,9 @@ namespace ts {
return tupleRestType;
}
}
return getIndexTypeOfType(restType, IndexKind.Number) || anyType;
return getIndexTypeOfType(restType, IndexKind.Number);
}
return anyType;
return undefined;
}
function getRestTypeAtPosition(source: Signature, pos: number): Type {
+4
View File
@@ -2864,6 +2864,10 @@
"category": "Error",
"code": 5070
},
"Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.": {
"category": "Error",
"code": 5071
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
+4
View File
@@ -2548,6 +2548,10 @@ namespace ts {
if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) {
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule");
}
// Any emit other than common js is error
else if (getEmitModuleKind(options) !== ModuleKind.CommonJS) {
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs, "resolveJsonModule", "module");
}
}
// there has to be common source directory if user specified --outdir || --sourceRoot
+2 -2
View File
@@ -171,8 +171,8 @@ namespace ts {
}
const t = getTypeOfSymbol(symbol);
visitType(t); // Should handle members on classes and such
if (symbol.flags & SymbolFlags.HasExports) {
symbol.exports!.forEach(visitSymbol);
if (symbol.exports) {
symbol.exports.forEach(visitSymbol);
}
forEach(symbol.declarations, d => {
// Type queries are too far resolved when we just visit the symbol's type
+65 -31
View File
@@ -332,9 +332,9 @@ namespace ts {
/*@internal*/
export interface RecursiveDirectoryWatcherHost {
watchDirectory: HostWatchDirectory;
useCaseSensitiveFileNames: boolean;
getAccessibleSortedChildDirectories(path: string): ReadonlyArray<string>;
directoryExists(dir: string): boolean;
filePathComparer: Comparer<string>;
realpath(s: string): string;
}
@@ -345,60 +345,94 @@ namespace ts {
*/
/*@internal*/
export function createRecursiveDirectoryWatcher(host: RecursiveDirectoryWatcherHost): (directoryName: string, callback: DirectoryWatcherCallback) => FileWatcher {
type ChildWatches = ReadonlyArray<DirectoryWatcher>;
interface DirectoryWatcher extends FileWatcher {
childWatches: ChildWatches;
interface ChildDirectoryWatcher extends FileWatcher {
dirName: string;
}
type ChildWatches = ReadonlyArray<ChildDirectoryWatcher>;
interface HostDirectoryWatcher {
watcher: FileWatcher;
childWatches: ChildWatches;
refCount: number;
}
const cache = createMap<HostDirectoryWatcher>();
const callbackCache = createMultiMap<DirectoryWatcherCallback>();
const filePathComparer = getStringComparer(!host.useCaseSensitiveFileNames);
const toCanonicalFilePath = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
return createDirectoryWatcher;
/**
* Create the directory watcher for the dirPath.
*/
function createDirectoryWatcher(dirName: string, callback: DirectoryWatcherCallback): DirectoryWatcher {
const watcher = host.watchDirectory(dirName, fileName => {
// Call the actual callback
callback(fileName);
function createDirectoryWatcher(dirName: string, callback?: DirectoryWatcherCallback): ChildDirectoryWatcher {
const dirPath = toCanonicalFilePath(dirName) as Path;
let directoryWatcher = cache.get(dirPath);
if (directoryWatcher) {
directoryWatcher.refCount++;
}
else {
directoryWatcher = {
watcher: host.watchDirectory(dirName, fileName => {
// Call the actual callback
callbackCache.forEach((callbacks, rootDirName) => {
if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) {
callbacks.forEach(callback => callback(fileName));
}
});
// Iterate through existing children and update the watches if needed
updateChildWatches(result, callback);
});
// Iterate through existing children and update the watches if needed
updateChildWatches(dirName, dirPath);
}),
refCount: 1,
childWatches: emptyArray
};
cache.set(dirPath, directoryWatcher);
updateChildWatches(dirName, dirPath);
}
let result: DirectoryWatcher = {
close: () => {
watcher.close();
result.childWatches.forEach(closeFileWatcher);
result = undefined!;
},
if (callback) {
callbackCache.add(dirPath, callback);
}
return {
dirName,
childWatches: emptyArray
close: () => {
const directoryWatcher = Debug.assertDefined(cache.get(dirPath));
if (callback) callbackCache.remove(dirPath, callback);
directoryWatcher.refCount--;
if (directoryWatcher.refCount) return;
cache.delete(dirPath);
closeFileWatcherOf(directoryWatcher);
directoryWatcher.childWatches.forEach(closeFileWatcher);
}
};
updateChildWatches(result, callback);
return result;
}
function updateChildWatches(watcher: DirectoryWatcher, callback: DirectoryWatcherCallback) {
function updateChildWatches(dirName: string, dirPath: Path) {
// Iterate through existing children and update the watches if needed
if (watcher) {
watcher.childWatches = watchChildDirectories(watcher.dirName, watcher.childWatches, callback);
const parentWatcher = cache.get(dirPath);
if (parentWatcher) {
parentWatcher.childWatches = watchChildDirectories(dirName, parentWatcher.childWatches);
}
}
/**
* Watch the directories in the parentDir
*/
function watchChildDirectories(parentDir: string, existingChildWatches: ChildWatches, callback: DirectoryWatcherCallback): ChildWatches {
let newChildWatches: DirectoryWatcher[] | undefined;
enumerateInsertsAndDeletes<string, DirectoryWatcher>(
function watchChildDirectories(parentDir: string, existingChildWatches: ChildWatches): ChildWatches {
let newChildWatches: ChildDirectoryWatcher[] | undefined;
enumerateInsertsAndDeletes<string, ChildDirectoryWatcher>(
host.directoryExists(parentDir) ? mapDefined(host.getAccessibleSortedChildDirectories(parentDir), child => {
const childFullName = getNormalizedAbsolutePath(child, parentDir);
// Filter our the symbolic link directories since those arent included in recursive watch
// which is same behaviour when recursive: true is passed to fs.watch
return host.filePathComparer(childFullName, host.realpath(childFullName)) === Comparison.EqualTo ? childFullName : undefined;
return filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
}) : emptyArray,
existingChildWatches,
(child, childWatcher) => host.filePathComparer(child, childWatcher.dirName),
(child, childWatcher) => filePathComparer(child, childWatcher.dirName),
createAndAddChildDirectoryWatcher,
closeFileWatcher,
addChildDirectoryWatcher
@@ -410,14 +444,14 @@ namespace ts {
* Create new childDirectoryWatcher and add it to the new ChildDirectoryWatcher list
*/
function createAndAddChildDirectoryWatcher(childName: string) {
const result = createDirectoryWatcher(childName, callback);
const result = createDirectoryWatcher(childName);
addChildDirectoryWatcher(result);
}
/**
* Add child directory watcher to the new ChildDirectoryWatcher list
*/
function addChildDirectoryWatcher(childWatcher: DirectoryWatcher) {
function addChildDirectoryWatcher(childWatcher: ChildDirectoryWatcher) {
(newChildWatches || (newChildWatches = [])).push(childWatcher);
}
}
@@ -710,7 +744,7 @@ namespace ts {
createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout })) :
watchDirectoryUsingFsWatch;
const watchDirectoryRecursively = createRecursiveDirectoryWatcher({
filePathComparer: getStringComparer(!useCaseSensitiveFileNames),
useCaseSensitiveFileNames,
directoryExists,
getAccessibleSortedChildDirectories: path => getAccessibleFileSystemEntries(path).directories,
watchDirectory,
+3 -6
View File
@@ -2994,9 +2994,9 @@ namespace ts {
*/
/* @internal */ tryGetMemberInModuleExportsAndProperties(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
getApparentType(type: Type): Type;
getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined;
getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
/* @internal */ getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined;
/* @internal */ getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
/* @internal */ getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
getBaseConstraintOfType(type: Type): Type | undefined;
getDefaultFromTypeParameter(type: Type): Type | undefined;
@@ -3439,9 +3439,6 @@ namespace ts {
ExportHasLocal = Function | Class | Enum | ValueModule,
HasExports = Class | Enum | Module | Variable,
HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
BlockScoped = BlockScopedVariable | Class | Enum,
PropertyOrAccessor = Property | Accessor,
+16
View File
@@ -8087,4 +8087,20 @@ namespace ts {
Debug.assert(index !== -1);
return arr.slice(index);
}
export function minAndMax<T>(arr: ReadonlyArray<T>, getValue: (value: T) => number): { readonly min: number, readonly max: number } {
Debug.assert(arr.length !== 0);
let min = getValue(arr[0]);
let max = min;
for (let i = 1; i < arr.length; i++) {
const value = getValue(arr[i]);
if (value < min) {
min = value;
}
else if (value > max) {
max = value;
}
}
return { min, max };
}
}
+20 -1
View File
@@ -398,7 +398,7 @@ namespace ts {
case WatchLogLevel.TriggerOnly:
return createFileWatcherWithTriggerLogging;
case WatchLogLevel.Verbose:
return createFileWatcherWithLogging;
return addWatch === <any>watchDirectory ? createDirectoryWatcherWithLogging : createFileWatcherWithLogging;
}
}
@@ -413,6 +413,25 @@ namespace ts {
};
}
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
const watchInfo = `${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
log(watchInfo);
const start = timestamp();
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
const elapsed = timestamp() - start;
log(`Elapsed:: ${elapsed}ms ${watchInfo}`);
return {
close: () => {
const watchInfo = `${watchCaption}:: Close:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
log(watchInfo);
const start = timestamp();
watcher.close();
const elapsed = timestamp() - start;
log(`Elapsed:: ${elapsed}ms ${watchInfo}`);
}
};
}
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
return addWatch(host, file, (fileName, cbOptional) => {
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName}${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
+3 -3
View File
@@ -352,9 +352,9 @@ interface Array<T> {}`
if (tscWatchDirectory === Tsc_WatchDirectory.WatchFile) {
const watchDirectory: HostWatchDirectory = (directory, cb) => this.watchFile(directory, () => cb(directory), PollingInterval.Medium);
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
useCaseSensitiveFileNames: this.useCaseSensitiveFileNames,
directoryExists: path => this.directoryExists(path),
getAccessibleSortedChildDirectories: path => this.getDirectories(path),
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
watchDirectory,
realpath: s => this.realpath(s)
});
@@ -362,9 +362,9 @@ interface Array<T> {}`
else if (tscWatchDirectory === Tsc_WatchDirectory.NonRecursiveWatchDirectory) {
const watchDirectory: HostWatchDirectory = (directory, cb) => this.watchDirectory(directory, fileName => cb(fileName), /*recursive*/ false);
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
useCaseSensitiveFileNames: this.useCaseSensitiveFileNames,
directoryExists: path => this.directoryExists(path),
getAccessibleSortedChildDirectories: path => this.getDirectories(path),
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
watchDirectory,
realpath: s => this.realpath(s)
});
@@ -373,9 +373,9 @@ interface Array<T> {}`
const watchFile = createDynamicPriorityPollingWatchFile(this);
const watchDirectory: HostWatchDirectory = (directory, cb) => watchFile(directory, () => cb(directory), PollingInterval.Medium);
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
useCaseSensitiveFileNames: this.useCaseSensitiveFileNames,
directoryExists: path => this.directoryExists(path),
getAccessibleSortedChildDirectories: path => this.getDirectories(path),
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
watchDirectory,
realpath: s => this.realpath(s)
});
-1
View File
@@ -1,4 +1,3 @@
/* @internal */
declare namespace ts.server {
export type ActionSet = "action::set";
export type ActionInvalidate = "action::invalidate";
-1
View File
@@ -1,5 +1,4 @@
namespace ts.server {
/*@internal*/
export interface ScriptInfoVersion {
svc: number;
text: number;
+3 -3
View File
@@ -1837,7 +1837,7 @@ namespace ts.server {
}
private mapTextChangeToCodeEdit(project: Project, change: FileTextChanges): protocol.FileCodeEdits {
return mapTextChangesToCodeEdits(change, project.getSourceFileOrConfigFile(this.normalizePath(change.fileName)));
return mapTextChangesToCodeEditsForFile(change, project.getSourceFileOrConfigFile(this.normalizePath(change.fileName)));
}
private mapTextChangeToCodeEditUsingScriptInfo(change: FileTextChanges): protocol.FileCodeEdits {
@@ -2357,8 +2357,8 @@ namespace ts.server {
return { file: fileName, start: scriptInfo.positionToLineOffset(textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) };
}
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !sourceFile);
function mapTextChangesToCodeEditsForFile(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !sourceFile, "Expected isNewFile for (only) new files", () => JSON.stringify({ isNewFile: textChanges.isNewFile, hasSourceFile: !!sourceFile }));
if (sourceFile) {
return {
fileName: textChanges.fileName,
+12 -10
View File
@@ -111,20 +111,22 @@ namespace ts.Completions {
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined {
const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
if (location && location.parent && isJsxClosingElement(location.parent)) {
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
// For example:
// var x = <div> </ /*1*/>
// The completion list at "1" will contain "div" with type any
// var x = <div> </ /*1*/
// The completion list at "1" will contain "div>" with type any
// And at `<div> </ /*1*/ >` (with a closing `>`), the completion list will contain "div".
const tagName = location.parent.parent.openingElement.tagName;
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false,
entries: [{
name: tagName.getFullText(),
kind: ScriptElementKind.classElement,
kindModifiers: undefined,
sortText: "0",
}]};
const hasClosingAngleBracket = !!findChildOfKind(location.parent, SyntaxKind.GreaterThanToken, sourceFile);
const entry: CompletionEntry = {
name: tagName.getFullText(sourceFile) + (hasClosingAngleBracket ? "" : ">"),
kind: ScriptElementKind.classElement,
kindModifiers: undefined,
sortText: "0",
};
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [entry] };
}
const entries: CompletionEntry[] = [];
+6 -4
View File
@@ -1463,12 +1463,14 @@ namespace ts.FindAllReferences.Core {
}
/** Gets all symbols for one property. Does not get symbols for every property. */
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): ReadonlyArray<Symbol> {
function getPropertySymbolsFromContextualType(node: ObjectLiteralElementWithName, checker: TypeChecker): ReadonlyArray<Symbol> {
const contextualType = checker.getContextualType(<ObjectLiteralExpression>node.parent);
const name = getNameFromPropertyName(node.name!);
const symbol = contextualType && name && contextualType.getProperty(name);
if (!contextualType) return emptyArray;
const name = getNameFromPropertyName(node.name);
if (!name) return emptyArray;
const symbol = contextualType.getProperty(name);
return symbol ? [symbol] :
contextualType && contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name!)) : emptyArray; // TODO: GH#18217
contextualType.isUnion() ? mapDefined(contextualType.types, t => t.getProperty(name)) : emptyArray;
}
/**
+11 -4
View File
@@ -1884,11 +1884,16 @@ namespace ts {
if (!token) return undefined;
const element = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningElement(token.parent) ? token.parent.parent
: isJsxText(token) ? token.parent : undefined;
if (element && !tagNamesAreEquivalent(element.openingElement.tagName, element.closingElement.tagName)) {
if (element && isUnclosedTag(element)) {
return { newText: `</${element.openingElement.tagName.getText(sourceFile)}>` };
}
}
function isUnclosedTag({ openingElement, closingElement, parent }: JsxElement): boolean {
return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) ||
isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent);
}
function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined {
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
const range = formatting.getRangeOfEnclosingComment(sourceFile, position);
@@ -2181,21 +2186,23 @@ namespace ts {
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
/* @internal */
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement | undefined {
export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElementWithName | undefined {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
return isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
return isObjectLiteralElement(node.parent.parent) ? node.parent.parent as ObjectLiteralElementWithName : undefined;
}
// falls through
case SyntaxKind.Identifier:
return isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === SyntaxKind.JsxAttributes) &&
node.parent.name === node ? node.parent : undefined;
node.parent.name === node ? node.parent as ObjectLiteralElementWithName : undefined;
}
return undefined;
}
/* @internal */
export type ObjectLiteralElementWithName = ObjectLiteralElement & { name: PropertyName };
/* @internal */
export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] {
@@ -8589,10 +8589,10 @@ export const x = 10;`
tscWatchDirectory === Tsc_WatchDirectory.WatchFile ?
expectedWatchedFiles :
createMap();
// For failed resolution lookup and tsconfig files
mapOfDirectories.set(projectFolder, 2);
// For failed resolution lookup and tsconfig files => cached so only watched only once
mapOfDirectories.set(projectFolder, 1);
// Through above recursive watches
mapOfDirectories.set(projectSrcFolder, 2);
mapOfDirectories.set(projectSrcFolder, 1);
// node_modules/@types folder
mapOfDirectories.set(`${projectFolder}/${nodeModulesAtTypes}`, 1);
const expectedCompletions = ["file1"];
File diff suppressed because it is too large Load Diff
+91 -7
View File
@@ -1,3 +1,18 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.0";
/** The version of the TypeScript compiler release */
@@ -1918,9 +1933,6 @@ declare namespace ts {
getAmbientModules(): Symbol[];
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
getApparentType(type: Type): Type;
getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined;
getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
getBaseConstraintOfType(type: Type): Type | undefined;
getDefaultFromTypeParameter(type: Type): Type | undefined;
/**
@@ -2063,8 +2075,6 @@ declare namespace ts {
AliasExcludes = 2097152,
ModuleMember = 2623475,
ExportHasLocal = 944,
HasExports = 1955,
HasMembers = 6240,
BlockScoped = 418,
PropertyOrAccessor = 98308,
ClassMember = 106500
@@ -4570,6 +4580,80 @@ declare namespace ts {
function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string>;
function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined;
}
declare namespace ts.server {
type ActionSet = "action::set";
type ActionInvalidate = "action::invalidate";
type ActionPackageInstalled = "action::packageInstalled";
type EventTypesRegistry = "event::typesRegistry";
type EventBeginInstallTypes = "event::beginInstallTypes";
type EventEndInstallTypes = "event::endInstallTypes";
type EventInitializationFailed = "event::initializationFailed";
interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
" __sortedArrayBrand": any;
}
interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
interface TypingInstallerRequestWithProjectName {
readonly projectName: string;
}
interface DiscoverTypings extends TypingInstallerRequestWithProjectName {
readonly fileNames: string[];
readonly projectRootPath: Path;
readonly compilerOptions: CompilerOptions;
readonly typeAcquisition: TypeAcquisition;
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly cachePath?: string;
readonly kind: "discover";
}
interface CloseProject extends TypingInstallerRequestWithProjectName {
readonly kind: "closeProject";
}
interface TypesRegistryRequest {
readonly kind: "typesRegistry";
}
interface InstallPackageRequest extends TypingInstallerRequestWithProjectName {
readonly kind: "installPackage";
readonly fileName: Path;
readonly packageName: string;
readonly projectRootPath: Path;
}
interface PackageInstalledResponse extends ProjectResponse {
readonly kind: ActionPackageInstalled;
readonly success: boolean;
readonly message: string;
}
interface InitializationFailedResponse extends TypingInstallerResponse {
readonly kind: EventInitializationFailed;
readonly message: string;
}
interface ProjectResponse extends TypingInstallerResponse {
readonly projectName: string;
}
interface InvalidateCachedTypings extends ProjectResponse {
readonly kind: ActionInvalidate;
}
interface InstallTypes extends ProjectResponse {
readonly kind: EventBeginInstallTypes | EventEndInstallTypes;
readonly eventId: number;
readonly typingsInstallerVersion: string;
readonly packagesToInstall: ReadonlyArray<string>;
}
interface BeginInstallTypes extends InstallTypes {
readonly kind: EventBeginInstallTypes;
}
interface EndInstallTypes extends InstallTypes {
readonly kind: EventEndInstallTypes;
readonly installSuccess: boolean;
}
interface SetTypings extends ProjectResponse {
readonly typeAcquisition: TypeAcquisition;
readonly compilerOptions: CompilerOptions;
readonly typings: string[];
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly kind: ActionSet;
}
}
declare namespace ts {
interface Node {
getSourceFile(): SourceFile;
@@ -5574,5 +5658,5 @@ declare namespace ts {
*/
function transform<T extends Node>(source: T | T[], transformers: TransformerFactory<T>[], compilerOptions?: CompilerOptions): TransformationResult<T>;
}
//# sourceMappingURL=typescriptServices.d.ts.map
export = ts
export = ts;
@@ -2,6 +2,10 @@ tests/cases/conformance/salsa/a.js(4,17): error TS2339: Property 'toFixed' does
Property 'toFixed' does not exist on type 'string'.
tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'.
Property 'toFixed' does not exist on type 'string'.
tests/cases/conformance/salsa/mod1.js(2,1): error TS2323: Cannot redeclare exported variable 'bothBefore'.
tests/cases/conformance/salsa/mod1.js(4,1): error TS2323: Cannot redeclare exported variable 'bothBefore'.
tests/cases/conformance/salsa/mod1.js(5,1): error TS2323: Cannot redeclare exported variable 'bothAfter'.
tests/cases/conformance/salsa/mod1.js(10,1): error TS2323: Cannot redeclare exported variable 'bothAfter'.
==== tests/cases/conformance/salsa/a.js (2 errors) ====
@@ -21,16 +25,24 @@ tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does
==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ====
declare var module: { exports: any };
declare function require(name: string): any;
==== tests/cases/conformance/salsa/mod1.js (0 errors) ====
==== tests/cases/conformance/salsa/mod1.js (4 errors) ====
/// <reference path='./requires.d.ts' />
module.exports.bothBefore = 'string'
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2323: Cannot redeclare exported variable 'bothBefore'.
A.justExport = 4
A.bothBefore = 2
~~~~~~~~~~~~
!!! error TS2323: Cannot redeclare exported variable 'bothBefore'.
A.bothAfter = 3
~~~~~~~~~~~
!!! error TS2323: Cannot redeclare exported variable 'bothAfter'.
module.exports = A
function A() {
this.p = 1
}
module.exports.bothAfter = 'string'
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2323: Cannot redeclare exported variable 'bothAfter'.
module.exports.justProperty = 'string'
@@ -0,0 +1,18 @@
error TS5070: Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy.
tests/cases/compiler/file1.ts(1,1): error TS1148: Cannot use imports, exports, or module augmentations when '--module' is 'none'.
tests/cases/compiler/file1.ts(1,20): error TS2307: Cannot find module './b.json'.
!!! error TS5070: Option '--resolveJsonModule' cannot be specified without 'node' module resolution strategy.
==== tests/cases/compiler/file1.ts (2 errors) ====
import * as b from './b.json';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1148: Cannot use imports, exports, or module augmentations when '--module' is 'none'.
~~~~~~~~~~
!!! error TS2307: Cannot find module './b.json'.
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleEmitNone.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
"use strict";
exports.__esModule = true;
@@ -0,0 +1,4 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
@@ -0,0 +1,4 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : any
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleEmitUndefined.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
"use strict";
exports.__esModule = true;
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,12 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (0 errors) ====
import * as b from './b.json';
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,21 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitAmd.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
define(["require", "exports"], function (require, exports) {
"use strict";
exports.__esModule = true;
});
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,12 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (0 errors) ====
import * as b from './b.json';
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitEs2015.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,12 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (0 errors) ====
import * as b from './b.json';
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,17 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitEsNext.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,15 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
tests/cases/compiler/file1.ts(1,1): error TS1148: Cannot use imports, exports, or module augmentations when '--module' is 'none'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (1 errors) ====
import * as b from './b.json';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1148: Cannot use imports, exports, or module augmentations when '--module' is 'none'.
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitNone.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
"use strict";
exports.__esModule = true;
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,12 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (0 errors) ====
import * as b from './b.json';
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,26 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitSystem.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
System.register([], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
return {
setters: [],
execute: function () {
}
};
});
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,12 @@
error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
!!! error TS5071: Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.
==== tests/cases/compiler/file1.ts (0 errors) ====
import * as b from './b.json';
==== tests/cases/compiler/b.json (0 errors) ====
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,29 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitUmd.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
exports.__esModule = true;
});
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/requireOfJsonFileWithModuleNodeResolutionEmitUndefined.ts] ////
//// [file1.ts]
import * as b from './b.json';
//// [b.json]
{
"a": true,
"b": "hello"
}
//// [out/b.json]
{
"a": true,
"b": "hello"
}
//// [out/file1.js]
"use strict";
exports.__esModule = true;
@@ -0,0 +1,12 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : Symbol(b, Decl(file1.ts, 0, 6))
=== tests/cases/compiler/b.json ===
{
"a": true,
>"a" : Symbol("a", Decl(b.json, 0, 1))
"b": "hello"
>"b" : Symbol("b", Decl(b.json, 1, 14))
}
@@ -0,0 +1,16 @@
=== tests/cases/compiler/file1.ts ===
import * as b from './b.json';
>b : { "a": boolean; "b": string; }
=== tests/cases/compiler/b.json ===
{
>{ "a": true, "b": "hello"} : { "a": boolean; "b": string; }
"a": true,
>"a" : boolean
>true : true
"b": "hello"
>"b" : string
>"hello" : "hello"
}
@@ -0,0 +1,13 @@
// @module: none
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,12 @@
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: amd
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: es2015
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: esnext
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: none
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: system
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,14 @@
// @module: umd
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
@@ -0,0 +1,13 @@
// @moduleResolution: node
// @outdir: out/
// @fullEmitPaths: true
// @resolveJsonModule: true
// @Filename: file1.ts
import * as b from './b.json';
// @Filename: b.json
{
"a": true,
"b": "hello"
}
+32 -1
View File
@@ -1,20 +1,51 @@
/// <reference path='fourslash.ts' />
// @Filename: /a.tsx
// Using separate files for each example to avoid unclosed JSX tags affecting other tests.
// @Filename: /0.tsx
////const x = <div>/*0*/;
// @Filename: /1.tsx
////const x = <div> foo/*1*/ </div>;
// @Filename: /2.tsx
////const x = <div></div>/*2*/;
// @Filename: /3.tsx
////const x = <div/>/*3*/;
// @Filename: /4.tsx
////const x = <div>
//// <p>/*4*/
//// </div>
////</p>;
// @Filename: /5.tsx
////const x = <div> text /*5*/;
// @Filename: /6.tsx
////const x = <div>
//// <div>/*6*/
////</div>;
// @Filename: /7.tsx
////const x = <div>
//// <p>/*7*/
////</div>;
// @Filename: /8.tsx
////const x = <div>
//// <div>/*8*/</div>
////</div>;
verify.jsxClosingTag({
0: { newText: "</div>" },
1: undefined,
2: undefined,
3: undefined,
4: { newText: "</p>" },
5: { newText: "</div>" },
6: { newText: "</div>" },
7: { newText: "</p>" },
8: undefined,
});
@@ -28,7 +28,7 @@ edit.deleteAtCaret('constructor(val: T) { }'.length);
verify.quickInfos({
Asig: "constructor A<string>(): A<string>",
Bsig: "constructor B<string>(val: string): B<string>",
Csig: "constructor C<T>(): C<T>", // Cannot resolve signature
Csig: "constructor C<{}>(): C<{}>", // Cannot resolve signature
Dsig: "constructor D<string>(val: string): D<string>" // Cannot resolve signature
});
@@ -37,6 +37,6 @@ edit.deleteAtCaret("val: T".length);
verify.quickInfos({
Asig: "constructor A<string>(): A<string>",
Bsig: "constructor B<string>(val: string): B<string>",
Csig: "constructor C<T>(): C<T>", // Cannot resolve signature
Csig: "constructor C<{}>(): C<{}>", // Cannot resolve signature
Dsig: "constructor D<string>(): D<string>"
});
@@ -0,0 +1,9 @@
/// <reference path="fourslash.ts" />
////interface A { a: number }
////interface B { b: number }
////declare function f(a: A): void;
////declare function f(b: B): void;
////f({ /**/ });
verify.completions({ marker: "", exact: ["a", "b"] });
@@ -0,0 +1,15 @@
/// <reference path="fourslash.ts" />
////interface A { a: number }
////interface B { b: number }
////interface C { c: number }
////declare function f(a: A): void;
////declare function f(...bs: B[]): void;
////declare function f(...cs: C[]): void;
////f({ /*1*/ });
////f({ a: 1 }, { /*2*/ });
verify.completions(
{ marker: "1", exact: ["a", "b", "c"] },
{ marker: "2", exact: ["b", "c"] },
);
@@ -0,0 +1,9 @@
/// <reference path="fourslash.ts" />
////interface A { a: number }
////interface B { b: number }
////declare function f(n: number): A;
////declare function f(s: string): B;
////f()./**/
verify.completions({ marker: "", exact: ["a", "b"] });
@@ -42,7 +42,7 @@ verify.completions(
{ marker: "openTag", includes: "div", triggerCharacter: "<" },
{ marker: "lessThan", exact: undefined, triggerCharacter: "<" },
{ marker: "closeTag", exact: "div", triggerCharacter: "/" },
{ marker: "closeTag", exact: "div>", triggerCharacter: "/" },
{ marker: "path", exact: "importMe", triggerCharacter: "/", isNewIdentifierLocation: true },
{ marker: "divide", exact: undefined, triggerCharacter: "/" },
);
@@ -17,10 +17,10 @@
////foo7(1, <string>(/*7*/ // signature help shows y as T
verify.signatureHelp(
{ marker: "1", text: "foo1<T>(x: number, callback: (y1: T) => number): void" },
{ marker: "1", text: "foo1(x: number, callback: (y1: {}) => number): void" },
// TODO: GH#23631
// { marker: "2", text: "foo2(x: number, callback: (y2: {}) => number): void" },
{ marker: "3", text: "foo3<T>(x: number, callback: (y3: T) => number): void" },
{ marker: "3", text: "foo3(x: number, callback: (y3: {}) => number): void" },
// TODO: GH#23631
// { marker: "4", text: "foo4(x: number, callback: (y4: string) => number): void" },
{ marker: "5", text: "foo5(x: number, callback: (y5: string) => number): void" },
@@ -31,4 +31,4 @@ goTo.marker('6');
// verify.signatureHelp({ text: "foo6(x: number, callback: (y6: {}) => number): void" });
edit.insert('string>(null,null);'); // need to make this line parse so we can get reasonable LS answers to later tests
verify.signatureHelp({ marker: "7", text: "foo7<T>(x: number, callback: (y7: T) => number): void" });
verify.signatureHelp({ marker: "7", text: "foo7(x: number, callback: (y7: {}) => number): void" });
@@ -24,9 +24,9 @@
////foo7(1, <string>(/*7*/ // signature help shows y as T
verify.signatureHelp(
{ marker: "1", text: "foo1<T>(x: number, callback: (y1: T) => number): void" },
{ marker: "2", text: "foo2<T>(x: number, callback: (y2: T) => number): void" },
{ marker: "3", text: "foo3<T>(x: number, callback: (y3: T) => number): void" },
{ marker: "1", text: "foo1(x: number, callback: (y1: {}) => number): void" },
{ marker: "2", text: "foo2(x: number, callback: (y2: {}) => number): void" },
{ marker: "3", text: "foo3(x: number, callback: (y3: {}) => number): void" },
{ marker: "4", text: "foo4(x: number, callback: (y4: string) => number): void" },
{ marker: "5", text: "foo5(x: number, callback: (y5: string) => number): void" },
);
@@ -35,4 +35,4 @@ goTo.marker('6');
verify.signatureHelp({ text: "foo6(x: number, callback: (y6: {}) => number): void" });
edit.insert('string>(null,null);'); // need to make this line parse so we can get reasonable LS answers to later tests
verify.signatureHelp({ marker: "7", text: "foo7<T>(x: number, callback: (y7: T) => number): void" })
verify.signatureHelp({ marker: "7", text: "foo7(x: number, callback: (y7: {}) => number): void" })
@@ -12,4 +12,4 @@
////fo/**/o()
goTo.marker();
verify.quickInfoIs("function foo<T>(x: T): void", "Do some foo things");
verify.quickInfoIs("function foo<any>(x: any): void", "Do some foo things");
+1 -1
View File
@@ -14,7 +14,7 @@
verify.signatureHelp({
marker: "",
text: "find<T>(l: T[], x: T): T",
text: "find(l: any[], x: any): any",
docComment: "Find an item",
tags: [
// TODO: GH#24130 (see PR #24600's commits for potential fix)
@@ -6,10 +6,8 @@
//// export var Foo: any = null;
//// }
//// const j = <NS.Foo>Hello!/**/
////
////
goTo.marker();
edit.insert("</");
verify.completionListContains("NS.Foo");
verify.not.completionListContains("Foo");
verify.completionListCount(1);
verify.completions({ exact: "NS.Foo>" });
@@ -509,7 +509,7 @@
//// function f<T extends A>(s: T, x: Exclude<A, T>, y: string) {}
//// f("_499", /*3*/);
//// type Decomposed/*4*/ = {[K in A]: Foo[K]}
//// type LongTuple/*5*/ = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17.18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70];
//// type LongTuple/*5*/ = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17.18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70];
//// type DeeplyMapped/*6*/ = {[K in keyof Foo]: {[K2 in keyof Foo]: [K, K2, Foo[K], Foo[K2]]}}
goTo.marker("1");
@@ -519,7 +519,7 @@ verify.quickInfoIs(`type Less = "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" |
goTo.marker("3");
verify.signatureHelp({
marker: "3",
text: `f<T extends "_0" | "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" | "_8" | "_9" | "_10" | "_11" | "_12" | "_13" | "_14" | "_15" | "_16" | "_17" | "_18" | "_19" | "_20" | "_21" | "_22" | "_23" | "_24" | ... 474 more ... | "_499">(s: T, x: Exclude<"_0", T> | Exclude<"_1", T> | Exclude<"_2", T> | Exclude<"_3", T> | Exclude<"_4", T> | Exclude<"_5", T> | Exclude<"_6", T> | Exclude<"_7", T> | Exclude<...> | ... 490 more ... | Exclude<...>, y: string): void`
text: `f(s: "_0" | "_1" | "_2" | "_3" | "_4" | "_5" | "_6" | "_7" | "_8" | "_9" | "_10" | "_11" | "_12" | "_13" | "_14" | "_15" | "_16" | "_17" | "_18" | "_19" | "_20" | "_21" | "_22" | "_23" | "_24" | ... 474 more ... | "_499", x: never, y: string): void`
});
goTo.marker("4");
verify.quickInfoIs(`type Decomposed = {
@@ -0,0 +1,6 @@
/// <reference path='fourslash.ts'/>
////declare function f<T>(x: number): T;
////const x/**/ = f();
verify.quickInfoAt("", "const x: {}");
@@ -8,7 +8,7 @@
verify.signatureHelp(
{ marker: "1", text: "f(x: number, y: string): number" },
{ marker: "2", text: "f<T = boolean, U = string>(x: T, y: U): T" },
{ marker: "2", text: "f(x: {}, y: {}): {}" },
// too few -- fill in rest with {}
{ marker: "3", text: "f(x: number, y: {}): number" },
// too many -- ignore extra type arguments
@@ -9,6 +9,6 @@
verify.signatureHelp(
{ marker: "1", text: "f1(a: any): a is number" },
{ marker: "2", text: "f2<T>(a: any): a is T" },
{ marker: "2", text: "f2(a: any): a is {}" },
{ marker: "3", text: "f3(a: any, ...b: any[]): a is number", isVariadic: true },
)
@@ -9,7 +9,7 @@ goTo.marker("1");
edit.insert("(");
verify.signatureHelp({
text: "bar<U>(x: U, y: U): U",
text: "bar(x: {}, y: {}): {}",
triggerReason: {
kind: "characterTyped",
triggerCharacter: "(",
+1 -3
View File
@@ -9,6 +9,4 @@
//// }
//// var x1 = <div><//**/
goTo.marker();
verify.completionListCount(1);
verify.completionListContains('div');
verify.completions({ marker: "", exact: "div>" });

Some files were not shown because too many files have changed in this diff Show More