mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into pvb/codeaction/api
This commit is contained in:
+6
-1
@@ -8,7 +8,7 @@ node_js:
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
- workerCount=4
|
||||
- workerCount=3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
@@ -17,6 +17,8 @@ matrix:
|
||||
node_js: stable
|
||||
osx_image: xcode7.3
|
||||
env: workerCount=2
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
branches:
|
||||
only:
|
||||
@@ -32,3 +34,6 @@ install:
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
+120
-93
@@ -17,7 +17,7 @@ declare module "gulp-typescript" {
|
||||
stripInternal?: boolean;
|
||||
types?: string[];
|
||||
}
|
||||
interface CompileStream extends NodeJS.ReadWriteStream {} // Either gulp or gulp-typescript has some odd typings which don't reflect reality, making this required
|
||||
interface CompileStream extends NodeJS.ReadWriteStream { } // Either gulp or gulp-typescript has some odd typings which don't reflect reality, making this required
|
||||
}
|
||||
import * as insert from "gulp-insert";
|
||||
import * as sourcemaps from "gulp-sourcemaps";
|
||||
@@ -34,7 +34,7 @@ import through2 = require("through2");
|
||||
import merge2 = require("merge2");
|
||||
import intoStream = require("into-stream");
|
||||
import * as os from "os";
|
||||
import Linter = require("tslint");
|
||||
import fold = require("travis-fold");
|
||||
const gulp = helpMaker(originalGulp);
|
||||
const mochaParallel = require("./scripts/mocha-parallel.js");
|
||||
const {runTestsInParallel} = mochaParallel;
|
||||
@@ -65,7 +65,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
|
||||
}
|
||||
});
|
||||
|
||||
function exec(cmd: string, args: string[], complete: () => void = (() => {}), error: (e: any, status: number) => void = (() => {})) {
|
||||
function exec(cmd: string, args: string[], complete: () => void = (() => { }), error: (e: any, status: number) => void = (() => { })) {
|
||||
console.log(`${cmd} ${args.join(" ")}`);
|
||||
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
|
||||
const subshellFlag = isWin ? "/c" : "-c";
|
||||
@@ -116,12 +116,12 @@ const es2015LibrarySources = [
|
||||
];
|
||||
|
||||
const es2015LibrarySourceMap = es2015LibrarySources.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const es2016LibrarySource = [ "es2016.array.include.d.ts" ];
|
||||
const es2016LibrarySource = ["es2016.array.include.d.ts"];
|
||||
|
||||
const es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
|
||||
const es2016LibrarySourceMap = es2016LibrarySource.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
@@ -130,38 +130,38 @@ const es2017LibrarySource = [
|
||||
"es2017.sharedmemory.d.ts"
|
||||
];
|
||||
|
||||
const es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
|
||||
const es2017LibrarySourceMap = es2017LibrarySource.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
const librarySourceMap = [
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
|
||||
const libraryTargets = librarySourceMap.map(function (f) {
|
||||
const libraryTargets = librarySourceMap.map(function(f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
});
|
||||
|
||||
for (const i in libraryTargets) {
|
||||
const entry = librarySourceMap[i];
|
||||
const target = libraryTargets[i];
|
||||
const sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
const sources = [copyright].concat(entry.sources.map(function(s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
gulp.task(target, false, [], function() {
|
||||
@@ -391,7 +391,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(tsc(servicesProject));
|
||||
const completedJs = js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."));
|
||||
.pipe(sourcemaps.write("."));
|
||||
const completedDts = dts.pipe(prependCopyright(/*outputCopyright*/true))
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
file.path = standaloneDefinitionsFile;
|
||||
@@ -434,17 +434,17 @@ const tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverli
|
||||
|
||||
gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
|
||||
const serverLibraryProject = tsc.createProject("src/server/tsconfig.library.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
const {js, dts}: {js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream} = serverLibraryProject.src()
|
||||
const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer(tsserverLibraryFile))
|
||||
.pipe(tsc(serverLibraryProject));
|
||||
|
||||
return merge2([
|
||||
js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(builtLocalDirectory)),
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(builtLocalDirectory)),
|
||||
dts.pipe(prependCopyright())
|
||||
.pipe(gulp.dest(builtLocalDirectory))
|
||||
.pipe(gulp.dest(builtLocalDirectory))
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -476,7 +476,7 @@ gulp.task(specMd, false, [word2mdJs], (done) => {
|
||||
const specMDFullPath = path.resolve(specMd);
|
||||
const cmd = "cscript //nologo " + word2mdJs + " \"" + specWordFullPath + "\" " + "\"" + specMDFullPath + "\"";
|
||||
console.log(cmd);
|
||||
cp.exec(cmd, function () {
|
||||
cp.exec(cmd, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -492,12 +492,12 @@ gulp.task("dontUseDebugMode", false, [], (done) => { useDebugMode = false; done(
|
||||
|
||||
gulp.task("VerifyLKG", false, [], () => {
|
||||
const expectedFiles = [builtLocalCompiler, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile].concat(libraryTargets);
|
||||
const missingFiles = expectedFiles.filter(function (f) {
|
||||
const missingFiles = expectedFiles.filter(function(f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
throw new Error("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
return gulp.src(expectedFiles).pipe(gulp.dest(LKGDirectory));
|
||||
@@ -531,8 +531,6 @@ const localRwcBaseline = path.join(internalTests, "baselines/rwc/local");
|
||||
const refRwcBaseline = path.join(internalTests, "baselines/rwc/reference");
|
||||
|
||||
const localTest262Baseline = path.join(internalTests, "baselines/test262/local");
|
||||
const refTest262Baseline = path.join(internalTests, "baselines/test262/reference");
|
||||
|
||||
|
||||
gulp.task("tests", "Builds the test infrastructure using the built compiler", [run]);
|
||||
gulp.task("tests-debug", "Builds the test sources and automation in debug mode", () => {
|
||||
@@ -553,7 +551,7 @@ function restoreSavedNodeEnv() {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
}
|
||||
|
||||
let testTimeout = 20000;
|
||||
let testTimeout = 40000;
|
||||
function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: (e?: any) => void) {
|
||||
const lintFlag = cmdLineOptions["lint"];
|
||||
cleanTestDirs((err) => {
|
||||
@@ -627,7 +625,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
}
|
||||
args.push(run);
|
||||
setNodeEnvToDevelopment();
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function(err) {
|
||||
// last worker clean everything and runs linter in case if there were no errors
|
||||
del(taskConfigsFolder).then(() => {
|
||||
if (!err) {
|
||||
@@ -679,7 +677,7 @@ gulp.task("runtests",
|
||||
["build-rules", "tests"],
|
||||
(done) => {
|
||||
runConsoleTests("mocha-fivemat-progress-reporter", /*runInParallel*/ false, done);
|
||||
});
|
||||
});
|
||||
|
||||
const nodeServerOutFile = "tests/webTestServer.js";
|
||||
const nodeServerInFile = "tests/webTestServer.ts";
|
||||
@@ -811,32 +809,36 @@ gulp.task("diff-rwc", "Diffs the RWC baselines using the diff tool specified by
|
||||
exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], done, done);
|
||||
});
|
||||
|
||||
gulp.task("baseline-accept", "Makes the most recent test results the new baseline, overwriting the old baseline", () => {
|
||||
return baselineAccept("");
|
||||
});
|
||||
|
||||
function baselineAccept(subfolder = "") {
|
||||
return merge2(baselineCopy(subfolder), baselineDelete(subfolder));
|
||||
}
|
||||
|
||||
function baselineCopy(subfolder = "") {
|
||||
return gulp.src([`tests/baselines/local/${subfolder}/**`, `!tests/baselines/local/${subfolder}/**/*.delete`])
|
||||
.pipe(gulp.dest(refBaseline));
|
||||
}
|
||||
|
||||
function baselineDelete(subfolder = "") {
|
||||
return gulp.src(["tests/baselines/local/**/*.delete"])
|
||||
.pipe(insert.transform((content, fileObj) => {
|
||||
const target = path.join(refBaseline, fileObj.relative.substr(0, fileObj.relative.length - ".delete".length));
|
||||
del.sync(target);
|
||||
del.sync(fileObj.path);
|
||||
return "";
|
||||
}));
|
||||
}
|
||||
|
||||
gulp.task("baseline-accept", "Makes the most recent test results the new baseline, overwriting the old baseline", (done) => {
|
||||
const softAccept = cmdLineOptions["soft"];
|
||||
if (!softAccept) {
|
||||
del(refBaseline).then(() => {
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
done();
|
||||
}, done);
|
||||
}
|
||||
else {
|
||||
gulp.src(localBaseline)
|
||||
.pipe(gulp.dest(refBaseline))
|
||||
.on("end", () => {
|
||||
del(path.join(refBaseline, "local")).then(() => done(), done);
|
||||
});
|
||||
}
|
||||
});
|
||||
gulp.task("baseline-accept-rwc", "Makes the most recent rwc test results the new baseline, overwriting the old baseline", () => {
|
||||
return del(refRwcBaseline).then(() => {
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
});
|
||||
return baselineAccept("rwc");
|
||||
});
|
||||
|
||||
|
||||
gulp.task("baseline-accept-test262", "Makes the most recent test262 test results the new baseline, overwriting the old baseline", () => {
|
||||
return del(refTest262Baseline).then(() => {
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
});
|
||||
return baselineAccept("test262");
|
||||
});
|
||||
|
||||
|
||||
@@ -928,26 +930,6 @@ gulp.task("build-rules", "Compiles tslint rules to js", () => {
|
||||
.pipe(gulp.dest(dest));
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("./tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
const ll = new Linter(path, contents, options);
|
||||
console.log("Linting '" + path + "'.");
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFile(options, path) {
|
||||
const contents = fs.readFileSync(path, "utf8");
|
||||
return lintFileContents(options, path, contents);
|
||||
}
|
||||
|
||||
const lintTargets = [
|
||||
"Gulpfile.ts",
|
||||
"src/compiler/**/*.ts",
|
||||
@@ -959,27 +941,72 @@ const lintTargets = [
|
||||
"tests/*.ts", "tests/webhost/*.ts" // Note: does *not* descend recursively
|
||||
];
|
||||
|
||||
function sendNextFile(files: {path: string}[], child: cp.ChildProcess, callback: (failures: number) => void, failures: number) {
|
||||
const file = files.pop();
|
||||
if (file) {
|
||||
console.log(`Linting '${file.path}'.`);
|
||||
child.send({ kind: "file", name: file.path });
|
||||
}
|
||||
else {
|
||||
child.send({ kind: "close" });
|
||||
callback(failures);
|
||||
}
|
||||
}
|
||||
|
||||
function spawnLintWorker(files: {path: string}[], callback: (failures: number) => void) {
|
||||
const child = cp.fork("./scripts/parallel-lint");
|
||||
let failures = 0;
|
||||
child.on("message", function(data) {
|
||||
switch (data.kind) {
|
||||
case "result":
|
||||
if (data.failures > 0) {
|
||||
failures += data.failures;
|
||||
console.log(data.output);
|
||||
}
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
case "error":
|
||||
console.error(data.error);
|
||||
failures++;
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
}
|
||||
});
|
||||
sendNextFile(files, child, callback, failures);
|
||||
}
|
||||
|
||||
gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
|
||||
const fileMatcher = RegExp(cmdLineOptions["files"]);
|
||||
const lintOptions = getLinterOptions();
|
||||
let failed = 0;
|
||||
return gulp.src(lintTargets)
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
if (!fileMatcher.test(file.path)) return contents;
|
||||
const result = lintFile(lintOptions, file.path);
|
||||
if (result.failureCount > 0) {
|
||||
console.log(result.output);
|
||||
failed += result.failureCount;
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
|
||||
let files: {stat: fs.Stats, path: string}[] = [];
|
||||
return gulp.src(lintTargets, { read: false })
|
||||
.pipe(through2.obj((chunk, enc, cb) => {
|
||||
files.push(chunk);
|
||||
cb();
|
||||
}, (cb) => {
|
||||
files = files.filter(file => fileMatcher.test(file.path)).sort((filea, fileb) => filea.stat.size - fileb.stat.size);
|
||||
const workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(files, finished);
|
||||
}
|
||||
return contents; // TODO (weswig): Automatically apply fixes? :3
|
||||
}))
|
||||
.on("end", () => {
|
||||
if (failed > 0) {
|
||||
console.error("Linter errors.");
|
||||
process.exit(1);
|
||||
|
||||
let completed = 0;
|
||||
let failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
throw new Error(`Linter errors: ${failures}`);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
|
||||
+270
-232
@@ -4,7 +4,7 @@ var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
var Linter = require("tslint");
|
||||
var fold = require("travis-fold");
|
||||
var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
|
||||
|
||||
// Variables
|
||||
@@ -27,9 +27,31 @@ var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
// 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;
|
||||
if (process.env.path !== undefined) {
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
} else if (process.env.PATH !== undefined) {
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
}
|
||||
|
||||
function toNs(diff) {
|
||||
return diff[0] * 1e9 + diff[1];
|
||||
}
|
||||
|
||||
function mark() {
|
||||
if (!fold.isTravis()) return;
|
||||
var stamp = process.hrtime();
|
||||
var id = Math.floor(Math.random() * 0xFFFFFFFF).toString(16);
|
||||
console.log("travis_time:start:" + id + "\r");
|
||||
return {
|
||||
stamp: stamp,
|
||||
id: id
|
||||
};
|
||||
}
|
||||
|
||||
function measure(marker) {
|
||||
if (!fold.isTravis()) return;
|
||||
var diff = process.hrtime(marker.stamp);
|
||||
var total = [marker.stamp[0] + diff[0], marker.stamp[1] + diff[1]];
|
||||
console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r");
|
||||
}
|
||||
|
||||
var compilerSources = [
|
||||
@@ -158,7 +180,8 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"convertCompilerOptionsFromJson.ts",
|
||||
"convertTypingOptionsFromJson.ts",
|
||||
"tsserverProjectSystem.ts",
|
||||
"matchFiles.ts"
|
||||
"matchFiles.ts",
|
||||
"initializeTSConfig.ts",
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
@@ -182,11 +205,11 @@ var es2015LibrarySources = [
|
||||
"es2015.symbol.wellknown.d.ts"
|
||||
];
|
||||
|
||||
var es2015LibrarySourceMap = es2015LibrarySources.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
var es2015LibrarySourceMap = es2015LibrarySources.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
var es2016LibrarySource = [ "es2016.array.include.d.ts" ];
|
||||
var es2016LibrarySource = ["es2016.array.include.d.ts"];
|
||||
|
||||
var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
@@ -204,21 +227,21 @@ var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
|
||||
var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
var librarySourceMap = [
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
|
||||
var libraryTargets = librarySourceMap.map(function (f) {
|
||||
@@ -234,7 +257,7 @@ function prependFile(prefixFile, destinationFile) {
|
||||
fail(destinationFile + " failed to be created!");
|
||||
}
|
||||
var temp = "temptemp";
|
||||
jake.cpR(prefixFile, temp, {silent: true});
|
||||
jake.cpR(prefixFile, temp, { silent: true });
|
||||
fs.appendFileSync(temp, fs.readFileSync(destinationFile));
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
@@ -246,11 +269,11 @@ function concatenateFiles(destinationFile, sourceFiles) {
|
||||
if (!fs.existsSync(sourceFiles[0])) {
|
||||
fail(sourceFiles[0] + " does not exist!");
|
||||
}
|
||||
jake.cpR(sourceFiles[0], temp, {silent: true});
|
||||
jake.cpR(sourceFiles[0], temp, { silent: true });
|
||||
// append all files in sequence
|
||||
for (var i = 1; i < sourceFiles.length; i++) {
|
||||
if (!fs.existsSync(sourceFiles[i])) {
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
}
|
||||
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
|
||||
}
|
||||
@@ -284,10 +307,11 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
|
||||
* @param callback: a function to execute after the compilation process ends
|
||||
*/
|
||||
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts, callback) {
|
||||
file(outFile, prereqs, function() {
|
||||
file(outFile, prereqs, function () {
|
||||
var startCompileTime = mark();
|
||||
opts = opts || {};
|
||||
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler;
|
||||
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
|
||||
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
|
||||
if (opts.types) {
|
||||
options += opts.types.join(",");
|
||||
}
|
||||
@@ -317,7 +341,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
options += " --module commonjs";
|
||||
}
|
||||
|
||||
if(opts.noResolve) {
|
||||
if (opts.noResolve) {
|
||||
options += " --noResolve";
|
||||
}
|
||||
|
||||
@@ -344,13 +368,13 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
if (!useDebugMode && prefixes && fs.existsSync(outFile)) {
|
||||
for (var i in prefixes) {
|
||||
prependFile(prefixes[i], outFile);
|
||||
@@ -361,14 +385,16 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
callback();
|
||||
}
|
||||
|
||||
measure(startCompileTime);
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function() {
|
||||
ex.addListener("error", function () {
|
||||
fs.unlinkSync(outFile);
|
||||
fail("Compilation of " + outFile + " unsuccessful");
|
||||
measure(startCompileTime);
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
}
|
||||
|
||||
// Prerequisite task for built directory and library typings
|
||||
@@ -381,7 +407,7 @@ for (var i in libraryTargets) {
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
file(target, [builtLocalDirectory].concat(sources), function () {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
})(i);
|
||||
@@ -404,30 +430,30 @@ file(processDiagnosticMessagesTs);
|
||||
|
||||
// processDiagnosticMessages script
|
||||
compileFile(processDiagnosticMessagesJs,
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
|
||||
file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () {
|
||||
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
file(builtGeneratedDiagnosticMessagesJSON,[generatedDiagnosticMessagesJSON], function() {
|
||||
file(builtGeneratedDiagnosticMessagesJSON, [generatedDiagnosticMessagesJSON], function () {
|
||||
if (fs.existsSync(builtLocalDirectory)) {
|
||||
jake.cpR(generatedDiagnosticMessagesJSON, builtGeneratedDiagnosticMessagesJSON);
|
||||
}
|
||||
@@ -445,17 +471,17 @@ var programTs = path.join(compilerDirectory, "program.ts");
|
||||
file(configureNightlyTs);
|
||||
|
||||
compileFile(/*outfile*/configureNightlyJs,
|
||||
/*sources*/ [configureNightlyTs],
|
||||
/*prereqs*/ [configureNightlyTs],
|
||||
/*prefixes*/ [],
|
||||
/*sources*/[configureNightlyTs],
|
||||
/*prereqs*/[configureNightlyTs],
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler*/ false,
|
||||
{ noOutFile: false, generateDeclarations: false, keepComments: false, noResolve: false, stripInternal: false });
|
||||
{ noOutFile: false, generateDeclarations: false, keepComments: false, noResolve: false, stripInternal: false });
|
||||
|
||||
task("setDebugMode", function() {
|
||||
task("setDebugMode", function () {
|
||||
useDebugMode = true;
|
||||
});
|
||||
|
||||
task("configure-nightly", [configureNightlyJs], function() {
|
||||
task("configure-nightly", [configureNightlyJs], function () {
|
||||
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
@@ -496,63 +522,65 @@ var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
var nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_standalone.d.ts");
|
||||
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*opts*/ { noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true
|
||||
},
|
||||
/*opts*/ {
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true
|
||||
},
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
jake.cpR(servicesFile, nodePackageFile, { silent: true });
|
||||
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, { silent: true });
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
|
||||
compileFile(
|
||||
servicesFileInBrowserTest,
|
||||
servicesSources,
|
||||
[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{ noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
noMapRoot: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
{
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
noMapRoot: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"] });
|
||||
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/[copyright], /*useBuiltCompiler*/ true, { types: ["node"] });
|
||||
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
compileFile(
|
||||
tsserverLibraryFile,
|
||||
languageServiceLibrarySources,
|
||||
[builtLocalDirectory, copyright, builtLocalCompiler].concat(languageServiceLibrarySources).concat(libraryTargets),
|
||||
/*prefixes*/ [copyright],
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{ noOutFile: false, generateDeclarations: true });
|
||||
|
||||
@@ -560,9 +588,19 @@ compileFile(
|
||||
desc("Builds language service server library");
|
||||
task("lssl", [tsserverLibraryFile, tsserverLibraryDefinitionFile]);
|
||||
|
||||
desc("Emit the start of the build fold");
|
||||
task("build-fold-start", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("build"));
|
||||
});
|
||||
|
||||
desc("Emit the end of the build fold");
|
||||
task("build-fold-end", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.end("build"));
|
||||
});
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON, "lssl"]);
|
||||
task("local", ["build-fold-start", "generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON, "lssl", "build-fold-end"]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
@@ -570,7 +608,7 @@ task("tsc", ["generate-diagnostics", "lib", tscFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Sets release mode flag");
|
||||
task("release", function() {
|
||||
task("release", function () {
|
||||
useDebugMode = false;
|
||||
});
|
||||
|
||||
@@ -580,7 +618,7 @@ task("default", ["local"]);
|
||||
|
||||
// Cleans the built directory
|
||||
desc("Cleans the compiler output, declare files, and tests");
|
||||
task("clean", function() {
|
||||
task("clean", function () {
|
||||
jake.rmRf(builtDirectory);
|
||||
});
|
||||
|
||||
@@ -594,9 +632,9 @@ file(word2mdTs);
|
||||
|
||||
// word2md script
|
||||
compileFile(word2mdJs,
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated spec.md; built for the 'generate-spec' task
|
||||
@@ -608,7 +646,7 @@ file(specMd, [word2mdJs, specWord], function () {
|
||||
child_process.exec(cmd, function () {
|
||||
complete();
|
||||
});
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
|
||||
desc("Generates a Markdown version of the Language Specification");
|
||||
@@ -617,14 +655,14 @@ task("generate-spec", [specMd]);
|
||||
|
||||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () {
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile].concat(libraryTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
fail("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
jake.mkdirP(LKGDirectory);
|
||||
@@ -645,8 +683,8 @@ var run = path.join(builtLocalDirectory, "run.js");
|
||||
compileFile(
|
||||
/*outFile*/ run,
|
||||
/*source*/ harnessSources,
|
||||
/*prereqs*/ [builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/ [],
|
||||
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler:*/ true,
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"] });
|
||||
|
||||
@@ -665,22 +703,22 @@ desc("Builds the test infrastructure using the built compiler");
|
||||
task("tests", ["local", run].concat(libraryTargets));
|
||||
|
||||
function exec(cmd, completeHandler, errorHandler) {
|
||||
var ex = jake.createExec([cmd], {windowsVerbatimArguments: true});
|
||||
var ex = jake.createExec([cmd], { windowsVerbatimArguments: true });
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
if (completeHandler) {
|
||||
completeHandler();
|
||||
}
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function(e, status) {
|
||||
if(errorHandler) {
|
||||
ex.addListener("error", function (e, status) {
|
||||
if (errorHandler) {
|
||||
errorHandler(e, status);
|
||||
} else {
|
||||
fail("Process exited with code " + status);
|
||||
@@ -724,7 +762,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
if (fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
var workerCount, taskConfigsFolder;
|
||||
@@ -757,7 +795,8 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
|
||||
// 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) {
|
||||
if (!runInParallel) {
|
||||
var startTime = mark();
|
||||
tests = tests ? ' -g "' + tests + '"' : '';
|
||||
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
@@ -766,10 +805,12 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
process.env.NODE_ENV = "development";
|
||||
exec(cmd, function () {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
measure(startTime);
|
||||
runLinter();
|
||||
finish();
|
||||
}, function(e, status) {
|
||||
}, function (e, status) {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
measure(startTime);
|
||||
finish(status);
|
||||
});
|
||||
|
||||
@@ -777,9 +818,10 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
else {
|
||||
var savedNodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = "development";
|
||||
var startTime = mark();
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
|
||||
measure(startTime);
|
||||
// last worker clean everything and runs linter in case if there were no errors
|
||||
deleteTemporaryProjectOutput();
|
||||
jake.rmRf(taskConfigsFolder);
|
||||
@@ -820,14 +862,14 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () {
|
||||
runConsoleTests('min', /*runInParallel*/ true);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("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 bail=false.");
|
||||
task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
task("runtests", ["build-rules", "tests", builtLocalDirectory], function () {
|
||||
runConsoleTests('mocha-fivemat-progress-reporter', /*runInParallel*/ false);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Generates code coverage data via instanbul");
|
||||
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
@@ -842,23 +884,23 @@ var nodeServerInFile = "tests/webTestServer.ts";
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true });
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function () {
|
||||
var cmd = 'browserify built/local/run.js -d -o built/local/bundle.js';
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function() {
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function () {
|
||||
cleanTestDirs();
|
||||
host = "node";
|
||||
browser = process.env.browser || process.env.b || "IE";
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
if (fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests || light) {
|
||||
if (tests || light) {
|
||||
writeTestConfigFile(tests, light);
|
||||
}
|
||||
|
||||
@@ -866,7 +908,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi
|
||||
var cmd = host + " tests/webTestServer.js " + browser + " " + JSON.stringify(tests);
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
function getDiffTool() {
|
||||
var program = process.env['DIFF'];
|
||||
@@ -879,17 +921,17 @@ function getDiffTool() {
|
||||
// Baseline Diff
|
||||
desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff-rwc', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Builds the test sources and automation in debug mode");
|
||||
task("tests-debug", ["setDebugMode", "tests"]);
|
||||
@@ -897,30 +939,39 @@ task("tests-debug", ["setDebugMode", "tests"]);
|
||||
|
||||
// Makes the test results the new baseline
|
||||
desc("Makes the most recent test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept", function(hardOrSoft) {
|
||||
if (!hardOrSoft || hardOrSoft === "hard") {
|
||||
jake.rmRf(refBaseline);
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
}
|
||||
else if (hardOrSoft === "soft") {
|
||||
var files = jake.readdirR(localBaseline);
|
||||
for (var i in files) {
|
||||
jake.cpR(files[i], refBaseline);
|
||||
}
|
||||
jake.rmRf(path.join(refBaseline, "local"));
|
||||
}
|
||||
task("baseline-accept", function () {
|
||||
acceptBaseline("");
|
||||
});
|
||||
|
||||
function acceptBaseline(containerFolder) {
|
||||
var sourceFolder = path.join(localBaseline, containerFolder);
|
||||
var targetFolder = path.join(refBaseline, containerFolder);
|
||||
console.log('Accept baselines from ' + sourceFolder + ' to ' + targetFolder);
|
||||
var files = fs.readdirSync(sourceFolder);
|
||||
var deleteEnding = '.delete';
|
||||
for (var i in files) {
|
||||
var filename = files[i];
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
} else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-rwc", function() {
|
||||
jake.rmRf(refRwcBaseline);
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
task("baseline-accept-rwc", function () {
|
||||
acceptBaseline("rwc");
|
||||
});
|
||||
|
||||
desc("Makes the most recent test262 test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-test262", function() {
|
||||
jake.rmRf(refTest262Baseline);
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
task("baseline-accept-test262", function () {
|
||||
acceptBaseline("test262");
|
||||
});
|
||||
|
||||
|
||||
@@ -930,8 +981,8 @@ var webhostJsPath = "tests/webhost/webtsc.js";
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true);
|
||||
|
||||
desc("Builds the tsc web host");
|
||||
task("webhost", [webhostJsPath], function() {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
|
||||
task("webhost", [webhostJsPath], function () {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", { silent: true });
|
||||
});
|
||||
|
||||
// Perf compiler
|
||||
@@ -944,38 +995,38 @@ task("perftsc", [perftscJsPath]);
|
||||
// Instrumented compiler
|
||||
var loggedIOpath = harnessDirectory + 'loggedIO.ts';
|
||||
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () {
|
||||
var temp = builtLocalDirectory + 'temp';
|
||||
jake.mkdirP(temp);
|
||||
var options = "--outdir " + temp + ' ' + loggedIOpath;
|
||||
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
|
||||
console.log(cmd + "\n");
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath);
|
||||
jake.rmRf(temp);
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () {
|
||||
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, { async: true });
|
||||
|
||||
desc("Updates the sublime plugin's tsserver");
|
||||
task("update-sublime", ["local", serverFile], function() {
|
||||
task("update-sublime", ["local", serverFile], function () {
|
||||
jake.cpR(serverFile, "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
jake.cpR(serverFile + ".map", "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
});
|
||||
@@ -991,124 +1042,111 @@ var tslintRules = [
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"noTypeAssertionWhitespaceRule"
|
||||
];
|
||||
var tslintRulesFiles = tslintRules.map(function(p) {
|
||||
var tslintRulesFiles = tslintRules.map(function (p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
});
|
||||
var tslintRulesOutFiles = tslintRules.map(function(p) {
|
||||
var tslintRulesOutFiles = tslintRules.map(function (p) {
|
||||
return path.join(builtLocalDirectory, "tslint", p + ".js");
|
||||
});
|
||||
desc("Compiles tslint rules to js");
|
||||
task("build-rules", tslintRulesOutFiles);
|
||||
tslintRulesFiles.forEach(function(ruleFile, i) {
|
||||
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
|
||||
tslintRulesFiles.forEach(function (ruleFile, i) {
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint")});
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint") });
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("./tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
desc("Emit the start of the build-rules fold");
|
||||
task("build-rules-start", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("build-rules"));
|
||||
});
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
var ll = new Linter(path, contents, options);
|
||||
console.log("Linting '" + path + "'.");
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFile(options, path) {
|
||||
var contents = fs.readFileSync(path, "utf8");
|
||||
return lintFileContents(options, path, contents);
|
||||
}
|
||||
|
||||
function lintFileAsync(options, path, cb) {
|
||||
fs.readFile(path, "utf8", function(err, contents) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
var result = lintFileContents(options, path, contents);
|
||||
cb(undefined, result);
|
||||
});
|
||||
}
|
||||
desc("Emit the end of the build-rules fold");
|
||||
task("build-rules-end", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.end("build-rules"));
|
||||
});
|
||||
|
||||
var lintTargets = compilerSources
|
||||
.concat(harnessSources)
|
||||
// Other harness sources
|
||||
.concat(["instrumenter.ts"].map(function(f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(["instrumenter.ts"].map(function (f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(serverCoreSources)
|
||||
.concat(tslintRulesFiles)
|
||||
.concat(servicesSources)
|
||||
.concat(["Gulpfile.ts"])
|
||||
.concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath]);
|
||||
|
||||
function sendNextFile(files, child, callback, failures) {
|
||||
var file = files.pop();
|
||||
if (file) {
|
||||
console.log("Linting '" + file + "'.");
|
||||
child.send({ kind: "file", name: file });
|
||||
}
|
||||
else {
|
||||
child.send({ kind: "close" });
|
||||
callback(failures);
|
||||
}
|
||||
}
|
||||
|
||||
function spawnLintWorker(files, callback) {
|
||||
var child = child_process.fork("./scripts/parallel-lint");
|
||||
var failures = 0;
|
||||
child.on("message", function (data) {
|
||||
switch (data.kind) {
|
||||
case "result":
|
||||
if (data.failures > 0) {
|
||||
failures += data.failures;
|
||||
console.log(data.output);
|
||||
}
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
case "error":
|
||||
console.error(data.error);
|
||||
failures++;
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
}
|
||||
});
|
||||
sendNextFile(files, child, callback, failures);
|
||||
}
|
||||
|
||||
desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
|
||||
task("lint", ["build-rules"], function() {
|
||||
var lintOptions = getLinterOptions();
|
||||
task("lint", ["build-rules"], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
var startTime = mark();
|
||||
var failed = 0;
|
||||
var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || "");
|
||||
var done = {};
|
||||
for (var i in lintTargets) {
|
||||
var target = lintTargets[i];
|
||||
if (!done[target] && fileMatcher.test(target)) {
|
||||
var result = lintFile(lintOptions, target);
|
||||
if (result.failureCount > 0) {
|
||||
console.log(result.output);
|
||||
failed += result.failureCount;
|
||||
}
|
||||
done[target] = true;
|
||||
done[target] = fs.statSync(target).size;
|
||||
}
|
||||
}
|
||||
if (failed > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This is required because file watches on Windows get fires _twice_
|
||||
* when a file changes on some node/windows version configuations
|
||||
* (node v4 and win 10, for example). By not running a lint for a file
|
||||
* which already has a pending lint, we avoid duplicating our work.
|
||||
* (And avoid printing duplicate results!)
|
||||
*/
|
||||
var lintSemaphores = {};
|
||||
var workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
|
||||
function lintWatchFile(filename) {
|
||||
fs.watch(filename, {persistent: true}, function(event) {
|
||||
if (event !== "change") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lintSemaphores[filename]) {
|
||||
lintSemaphores[filename] = true;
|
||||
lintFileAsync(getLinterOptions(), filename, function(err, result) {
|
||||
delete lintSemaphores[filename];
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
if (result.failureCount > 0) {
|
||||
console.log("***Lint failure***");
|
||||
for (var i = 0; i < result.failures.length; i++) {
|
||||
var failure = result.failures[i];
|
||||
var start = failure.startPosition.lineAndCharacter;
|
||||
var end = failure.endPosition.lineAndCharacter;
|
||||
console.log("warning " + filename + " (" + (start.line + 1) + "," + (start.character + 1) + "," + (end.line + 1) + "," + (end.character + 1) + "): " + failure.failure);
|
||||
}
|
||||
console.log("*** Total " + result.failureCount + " failures.");
|
||||
}
|
||||
});
|
||||
}
|
||||
var names = Object.keys(done).sort(function (namea, nameb) {
|
||||
return done[namea] - done[nameb];
|
||||
});
|
||||
}
|
||||
|
||||
desc("Watches files for changes to rerun a lint pass");
|
||||
task("lint-server", ["build-rules"], function() {
|
||||
console.log("Watching ./src for changes to linted files");
|
||||
for (var i = 0; i < lintTargets.length; i++) {
|
||||
lintWatchFile(lintTargets[i]);
|
||||
for (var i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(names, finished);
|
||||
}
|
||||
});
|
||||
|
||||
var completed = 0;
|
||||
var failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
measure(startTime);
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { async: true });
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
[](https://gitter.im/Microsoft/TypeScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](http://blogs.msdn.com/typescript) and [Twitter account](https://twitter.com/typescriptlang).
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescriptlang).
|
||||
|
||||
## Installing
|
||||
|
||||
|
||||
+3
-1
@@ -30,8 +30,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/browserify": "latest",
|
||||
"@types/convert-source-map": "latest",
|
||||
"@types/chai": "latest",
|
||||
"@types/convert-source-map": "latest",
|
||||
"@types/del": "latest",
|
||||
"@types/glob": "latest",
|
||||
"@types/gulp": "latest",
|
||||
@@ -69,9 +69,11 @@
|
||||
"mkdirp": "latest",
|
||||
"mocha": "latest",
|
||||
"mocha-fivemat-progress-reporter": "latest",
|
||||
"q": "latest",
|
||||
"run-sequence": "latest",
|
||||
"sorcery": "latest",
|
||||
"through2": "latest",
|
||||
"travis-fold": "latest",
|
||||
"ts-node": "latest",
|
||||
"tslint": "next",
|
||||
"typescript": "next"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../src/harness/external/node.d.ts" />
|
||||
/// <reference types="node"/>
|
||||
|
||||
import fs = require('fs');
|
||||
import path = require('path');
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
var Linter = require("tslint");
|
||||
var fs = require("fs");
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("../tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
var ll = new Linter(path, contents, options);
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFileAsync(options, path, cb) {
|
||||
fs.readFile(path, "utf8", function (err, contents) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
var result = lintFileContents(options, path, contents);
|
||||
cb(undefined, result);
|
||||
});
|
||||
}
|
||||
|
||||
process.on("message", function (data) {
|
||||
switch (data.kind) {
|
||||
case "file":
|
||||
var target = data.name;
|
||||
var lintOptions = getLinterOptions();
|
||||
lintFileAsync(lintOptions, target, function (err, result) {
|
||||
if (err) {
|
||||
process.send({ kind: "error", error: err.toString() });
|
||||
return;
|
||||
}
|
||||
process.send({ kind: "result", failures: result.failureCount, output: result.output });
|
||||
});
|
||||
break;
|
||||
case "close":
|
||||
process.exit(0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -69,7 +69,7 @@ function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosti
|
||||
}
|
||||
|
||||
function buildUniqueNameMap(names: string[]): ts.Map<string> {
|
||||
var nameMap: ts.Map<string> = {};
|
||||
var nameMap = ts.createMap<string>();
|
||||
|
||||
var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (identifier: string) => `Identifier '${identifier}' never appears on the LHS of an assignment - use const instead of let for its declaration.`;
|
||||
|
||||
@@ -64,7 +63,7 @@ interface DeclarationUsages {
|
||||
}
|
||||
|
||||
class PreferConstWalker extends Lint.RuleWalker {
|
||||
private inScopeLetDeclarations: ts.Map<DeclarationUsages>[] = [];
|
||||
private inScopeLetDeclarations: ts.MapLike<DeclarationUsages>[] = [];
|
||||
private errors: Lint.RuleFailure[] = [];
|
||||
private markAssignment(identifier: ts.Identifier) {
|
||||
const name = identifier.text;
|
||||
@@ -172,7 +171,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
|
||||
private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
const names: ts.MapLike<DeclarationUsages> = {};
|
||||
if (isLet(node.initializer)) {
|
||||
if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) {
|
||||
this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names);
|
||||
@@ -194,7 +193,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
|
||||
visitBlock(node: ts.Block) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
const names: ts.MapLike<DeclarationUsages> = {};
|
||||
for (const statement of node.statements) {
|
||||
if (statement.kind === ts.SyntaxKind.VariableStatement) {
|
||||
this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names);
|
||||
@@ -205,7 +204,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
this.popDeclarations();
|
||||
}
|
||||
|
||||
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.Map<DeclarationUsages>) {
|
||||
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.MapLike<DeclarationUsages>) {
|
||||
for (const node of list.declarations) {
|
||||
if (isLet(node) && !isExported(node)) {
|
||||
this.collectNameIdentifiers(node, node.name, ret);
|
||||
@@ -213,7 +212,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
}
|
||||
|
||||
private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.MapLike<DeclarationUsages>) {
|
||||
if (node.kind === ts.SyntaxKind.Identifier) {
|
||||
table[(node as ts.Identifier).text] = { declaration, usages: 0 };
|
||||
}
|
||||
@@ -222,7 +221,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
}
|
||||
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.MapLike<DeclarationUsages>) {
|
||||
for (const element of pattern.elements) {
|
||||
this.collectNameIdentifiers(value, element.name, table);
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -10,7 +10,7 @@ declare module "gulp-insert" {
|
||||
export function append(text: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function prepend(text: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function wrap(text: string | Buffer, tail: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function transform(cb: (contents: string, file: {path: string}) => string): NodeJS.ReadWriteStream; // file is a vinyl file
|
||||
export function transform(cb: (contents: string, file: {path: string, relative: string}) => string): NodeJS.ReadWriteStream; // file is a vinyl file
|
||||
}
|
||||
|
||||
declare module "into-stream" {
|
||||
@@ -22,3 +22,4 @@ declare module "into-stream" {
|
||||
}
|
||||
|
||||
declare module "sorcery";
|
||||
declare module "travis-fold";
|
||||
|
||||
+70
-55
@@ -89,9 +89,10 @@ namespace ts {
|
||||
const binder = createBinder();
|
||||
|
||||
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeBind");
|
||||
binder(file, options);
|
||||
performance.measure("Bind", start);
|
||||
performance.mark("afterBind");
|
||||
performance.measure("Bind", "beforeBind", "afterBind");
|
||||
}
|
||||
|
||||
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
@@ -135,7 +136,7 @@ namespace ts {
|
||||
options = opts;
|
||||
languageVersion = getEmitScriptTarget(options);
|
||||
inStrictMode = !!file.externalModuleIndicator;
|
||||
classifiableNames = {};
|
||||
classifiableNames = createMap<string>();
|
||||
symbolCount = 0;
|
||||
|
||||
Symbol = objectAllocator.getSymbolConstructor();
|
||||
@@ -183,11 +184,11 @@ namespace ts {
|
||||
symbol.declarations.push(node);
|
||||
|
||||
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
|
||||
symbol.exports = {};
|
||||
symbol.exports = createMap<Symbol>();
|
||||
}
|
||||
|
||||
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
|
||||
symbol.members = {};
|
||||
symbol.members = createMap<Symbol>();
|
||||
}
|
||||
|
||||
if (symbolFlags & SymbolFlags.Value) {
|
||||
@@ -298,8 +299,10 @@ namespace ts {
|
||||
const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
|
||||
|
||||
let symbol: Symbol;
|
||||
if (name !== undefined) {
|
||||
|
||||
if (name === undefined) {
|
||||
symbol = createSymbol(SymbolFlags.None, "__missing");
|
||||
}
|
||||
else {
|
||||
// Check and see if the symbol table already has a symbol with this name. If not,
|
||||
// create a new symbol with this name and add it to the table. Note that we don't
|
||||
// give the new symbol any flags *yet*. This ensures that it will not conflict
|
||||
@@ -311,6 +314,11 @@ namespace ts {
|
||||
// declaration we have for this symbol, and then create a new symbol for this
|
||||
// declaration.
|
||||
//
|
||||
// Note that when properties declared in Javascript constructors
|
||||
// (marked by isReplaceableByMethod) conflict with another symbol, the property loses.
|
||||
// Always. This allows the common Javascript pattern of overwriting a prototype method
|
||||
// with an bound instance method of the same type: `this.method = this.method.bind(this)`
|
||||
//
|
||||
// If we created a new symbol, either because we didn't have a symbol with this name
|
||||
// in the symbol table, or we conflicted with an existing symbol, then just add this
|
||||
// node as the sole declaration of the new symbol.
|
||||
@@ -318,42 +326,44 @@ namespace ts {
|
||||
// Otherwise, we'll be merging into a compatible existing symbol (for example when
|
||||
// you have multiple 'vars' with the same name in the same container). In this case
|
||||
// just add this node into the declarations list of the symbol.
|
||||
symbol = hasProperty(symbolTable, name)
|
||||
? symbolTable[name]
|
||||
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
|
||||
symbol = symbolTable[name] || (symbolTable[name] = createSymbol(SymbolFlags.None, name));
|
||||
|
||||
if (name && (includes & SymbolFlags.Classifiable)) {
|
||||
classifiableNames[name] = name;
|
||||
}
|
||||
|
||||
if (symbol.flags & excludes) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
if (symbol.isReplaceableByMethod) {
|
||||
// Javascript constructor-declared symbols can be discarded in favor of
|
||||
// prototype symbols like methods.
|
||||
symbol = symbolTable[name] = createSymbol(SymbolFlags.None, name);
|
||||
}
|
||||
|
||||
// Report errors every position with duplicate declaration
|
||||
// Report errors on previous encountered declarations
|
||||
let message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
if (declaration.flags & NodeFlags.Default) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
else {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
});
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
// Report errors every position with duplicate declaration
|
||||
// Report errors on previous encountered declarations
|
||||
let message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
symbol = createSymbol(SymbolFlags.None, name);
|
||||
forEach(symbol.declarations, declaration => {
|
||||
if (declaration.flags & NodeFlags.Default) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
}
|
||||
});
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
|
||||
symbol = createSymbol(SymbolFlags.None, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
symbol = createSymbol(SymbolFlags.None, "__missing");
|
||||
}
|
||||
|
||||
addDeclarationToSymbol(symbol, node, includes);
|
||||
symbol.parent = parent;
|
||||
@@ -434,7 +444,7 @@ namespace ts {
|
||||
if (containerFlags & ContainerFlags.IsContainer) {
|
||||
container = blockScopeContainer = node;
|
||||
if (containerFlags & ContainerFlags.HasLocals) {
|
||||
container.locals = {};
|
||||
container.locals = createMap<Symbol>();
|
||||
}
|
||||
addToContainerChain(container);
|
||||
}
|
||||
@@ -1399,7 +1409,8 @@ namespace ts {
|
||||
|
||||
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
|
||||
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
|
||||
typeLiteralSymbol.members = { [symbol.name]: symbol };
|
||||
typeLiteralSymbol.members = createMap<Symbol>();
|
||||
typeLiteralSymbol.members[symbol.name] = symbol;
|
||||
}
|
||||
|
||||
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
|
||||
@@ -1409,7 +1420,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (inStrictMode) {
|
||||
const seen: Map<ElementKind> = {};
|
||||
const seen = createMap<ElementKind>();
|
||||
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name.kind !== SyntaxKind.Identifier) {
|
||||
@@ -1465,7 +1476,7 @@ namespace ts {
|
||||
// fall through.
|
||||
default:
|
||||
if (!blockScopeContainer.locals) {
|
||||
blockScopeContainer.locals = {};
|
||||
blockScopeContainer.locals = createMap<Symbol>();
|
||||
addToContainerChain(blockScopeContainer);
|
||||
}
|
||||
declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
@@ -1887,18 +1898,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
|
||||
const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (<ExportAssignment>node).expression : (<BinaryExpression>node).right;
|
||||
if (!container.symbol || !container.symbol.exports) {
|
||||
// Export assignment in some sort of block construct
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
|
||||
}
|
||||
else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) {
|
||||
// An export default clause with an identifier exports all meanings of that identifier
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
}
|
||||
else {
|
||||
// An export default clause with an expression exports a value
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node)
|
||||
// An export default clause with an EntityNameExpression exports all meanings of that identifier
|
||||
? SymbolFlags.Alias
|
||||
// An export default clause with any other expression exports a value
|
||||
: SymbolFlags.Property;
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1925,7 +1935,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
file.symbol.globalExports = file.symbol.globalExports || {};
|
||||
file.symbol.globalExports = file.symbol.globalExports || createMap<Symbol>();
|
||||
declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
|
||||
}
|
||||
|
||||
@@ -1967,20 +1977,25 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
// Declare a 'member' in case it turns out the container was an ES5 class or ES6 constructor
|
||||
let assignee: Node;
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
|
||||
assignee = container;
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
else if (container.kind === SyntaxKind.Constructor) {
|
||||
assignee = container.parent;
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const saveContainer = container;
|
||||
container = container.parent;
|
||||
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// constructor-declared symbols can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
container = saveContainer;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
assignee.symbol.members = assignee.symbol.members || {};
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(assignee.symbol.members, assignee.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
|
||||
function bindPrototypePropertyAssignment(node: BinaryExpression) {
|
||||
@@ -2004,7 +2019,7 @@ namespace ts {
|
||||
|
||||
// Set up the members collection if it doesn't exist already
|
||||
if (!funcSymbol.members) {
|
||||
funcSymbol.members = {};
|
||||
funcSymbol.members = createMap<Symbol>();
|
||||
}
|
||||
|
||||
// Declare the method/property
|
||||
@@ -2053,7 +2068,7 @@ namespace ts {
|
||||
// module might have an exported variable called 'prototype'. We can't allow that as
|
||||
// that would clash with the built-in 'prototype' for the class.
|
||||
const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
|
||||
if (hasProperty(symbol.exports, prototypeSymbol.name)) {
|
||||
if (symbol.exports[prototypeSymbol.name]) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
|
||||
+705
-492
File diff suppressed because it is too large
Load Diff
@@ -61,10 +61,10 @@ namespace ts {
|
||||
},
|
||||
{
|
||||
name: "jsx",
|
||||
type: {
|
||||
type: createMap({
|
||||
"preserve": JsxEmit.Preserve,
|
||||
"react": JsxEmit.React
|
||||
},
|
||||
}),
|
||||
paramType: Diagnostics.KIND,
|
||||
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
|
||||
},
|
||||
@@ -91,7 +91,7 @@ namespace ts {
|
||||
{
|
||||
name: "module",
|
||||
shortName: "m",
|
||||
type: {
|
||||
type: createMap({
|
||||
"none": ModuleKind.None,
|
||||
"commonjs": ModuleKind.CommonJS,
|
||||
"amd": ModuleKind.AMD,
|
||||
@@ -99,16 +99,16 @@ namespace ts {
|
||||
"umd": ModuleKind.UMD,
|
||||
"es6": ModuleKind.ES6,
|
||||
"es2015": ModuleKind.ES2015,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
|
||||
paramType: Diagnostics.KIND,
|
||||
},
|
||||
{
|
||||
name: "newLine",
|
||||
type: {
|
||||
type: createMap({
|
||||
"crlf": NewLineKind.CarriageReturnLineFeed,
|
||||
"lf": NewLineKind.LineFeed
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix,
|
||||
paramType: Diagnostics.NEWLINE,
|
||||
},
|
||||
@@ -126,6 +126,10 @@ namespace ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
|
||||
},
|
||||
{
|
||||
name: "noErrorTruncation",
|
||||
type: "boolean"
|
||||
},
|
||||
{
|
||||
name: "noImplicitAny",
|
||||
type: "boolean",
|
||||
@@ -250,12 +254,12 @@ namespace ts {
|
||||
{
|
||||
name: "target",
|
||||
shortName: "t",
|
||||
type: {
|
||||
type: createMap({
|
||||
"es3": ScriptTarget.ES3,
|
||||
"es5": ScriptTarget.ES5,
|
||||
"es6": ScriptTarget.ES6,
|
||||
"es2015": ScriptTarget.ES2015,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015,
|
||||
paramType: Diagnostics.VERSION,
|
||||
},
|
||||
@@ -284,10 +288,10 @@ namespace ts {
|
||||
},
|
||||
{
|
||||
name: "moduleResolution",
|
||||
type: {
|
||||
type: createMap({
|
||||
"node": ModuleResolutionKind.NodeJs,
|
||||
"classic": ModuleResolutionKind.Classic,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
|
||||
},
|
||||
{
|
||||
@@ -392,7 +396,7 @@ namespace ts {
|
||||
type: "list",
|
||||
element: {
|
||||
name: "lib",
|
||||
type: {
|
||||
type: createMap({
|
||||
// JavaScript only
|
||||
"es5": "lib.es5.d.ts",
|
||||
"es6": "lib.es2015.d.ts",
|
||||
@@ -417,7 +421,7 @@ namespace ts {
|
||||
"es2016.array.include": "lib.es2016.array.include.d.ts",
|
||||
"es2017.object": "lib.es2017.object.d.ts",
|
||||
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts"
|
||||
},
|
||||
}),
|
||||
},
|
||||
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
|
||||
},
|
||||
@@ -462,6 +466,14 @@ namespace ts {
|
||||
shortOptionNames: Map<string>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
};
|
||||
|
||||
let optionNameMapCache: OptionNameMap;
|
||||
|
||||
/* @internal */
|
||||
@@ -470,8 +482,8 @@ namespace ts {
|
||||
return optionNameMapCache;
|
||||
}
|
||||
|
||||
const optionNameMap: Map<CommandLineOption> = {};
|
||||
const shortOptionNames: Map<string> = {};
|
||||
const optionNameMap = createMap<CommandLineOption>();
|
||||
const shortOptionNames = createMap<string>();
|
||||
forEach(optionDeclarations, option => {
|
||||
optionNameMap[option.name.toLowerCase()] = option;
|
||||
if (option.shortName) {
|
||||
@@ -486,10 +498,9 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
|
||||
const namesOfType: string[] = [];
|
||||
forEachKey(opt.type, key => {
|
||||
for (const key in opt.type) {
|
||||
namesOfType.push(` '${key}'`);
|
||||
});
|
||||
|
||||
}
|
||||
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
|
||||
}
|
||||
|
||||
@@ -497,7 +508,7 @@ namespace ts {
|
||||
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
const key = trimString((value || "")).toLowerCase();
|
||||
const map = opt.type;
|
||||
if (hasProperty(map, key)) {
|
||||
if (key in map) {
|
||||
return map[key];
|
||||
}
|
||||
else {
|
||||
@@ -551,11 +562,11 @@ namespace ts {
|
||||
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
|
||||
// Try to translate short option names to their full equivalents.
|
||||
if (hasProperty(shortOptionNames, s)) {
|
||||
if (s in shortOptionNames) {
|
||||
s = shortOptionNames[s];
|
||||
}
|
||||
|
||||
if (hasProperty(optionNameMap, s)) {
|
||||
if (s in optionNameMap) {
|
||||
const opt = optionNameMap[s];
|
||||
|
||||
if (opt.isTSConfigOnly) {
|
||||
@@ -668,6 +679,94 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate tsconfig configuration when running command line "--init"
|
||||
* @param options commandlineOptions to be generated into tsconfig.json
|
||||
* @param fileNames array of filenames to be generated into tsconfig.json
|
||||
*/
|
||||
/* @internal */
|
||||
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map<CompilerOptionsValue> } {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: any = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions)
|
||||
};
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
|
||||
return configurations;
|
||||
|
||||
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
|
||||
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
|
||||
// this is of a type CommandLineOptionOfPrimitiveType
|
||||
return undefined;
|
||||
}
|
||||
else if (optionDefinition.type === "list") {
|
||||
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
|
||||
}
|
||||
else {
|
||||
return (<CommandLineOptionOfCustomType>optionDefinition).type;
|
||||
}
|
||||
}
|
||||
|
||||
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike<string | number>): string | undefined {
|
||||
// There is a typeMap associated with this command-line option so use it to map value back to its name
|
||||
for (const key in customTypeMap) {
|
||||
if (customTypeMap[key] === value) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
|
||||
const result = createMap<CompilerOptionsValue>();
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
if (hasProperty(options, name)) {
|
||||
// tsconfig only options cannot be specified via command line,
|
||||
// so we can assume that only types that can appear here string | number | boolean
|
||||
switch (name) {
|
||||
case "init":
|
||||
case "watch":
|
||||
case "version":
|
||||
case "help":
|
||||
case "project":
|
||||
break;
|
||||
default:
|
||||
const value = options[name];
|
||||
let optionDefinition = optionsNameMap[name.toLowerCase()];
|
||||
if (optionDefinition) {
|
||||
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
|
||||
if (!customTypeMap) {
|
||||
// There is no map associated with this compiler option then use the value as-is
|
||||
// This is the case if the value is expect to be string, number, boolean or list of string
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
if (optionDefinition.type === "list") {
|
||||
const convertedValue: string[] = [];
|
||||
for (const element of value as (string | number)[]) {
|
||||
convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap));
|
||||
}
|
||||
result[name] = convertedValue;
|
||||
}
|
||||
else {
|
||||
// There is a typeMap associated with this command-line option so use it to map value back to its name
|
||||
result[name] = getNameOfCompilerOptionValue(value, customTypeMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the comments from a json like text.
|
||||
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
|
||||
@@ -786,7 +885,7 @@ namespace ts {
|
||||
function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
|
||||
basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
|
||||
|
||||
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {};
|
||||
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {};
|
||||
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
|
||||
return options;
|
||||
}
|
||||
@@ -811,7 +910,7 @@ namespace ts {
|
||||
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
|
||||
|
||||
for (const id in jsonOptions) {
|
||||
if (hasProperty(optionNameMap, id)) {
|
||||
if (id in optionNameMap) {
|
||||
const opt = optionNameMap[id];
|
||||
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
|
||||
}
|
||||
@@ -848,7 +947,7 @@ namespace ts {
|
||||
|
||||
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
const key = value.toLowerCase();
|
||||
if (hasProperty(opt.type, key)) {
|
||||
if (key in opt.type) {
|
||||
return opt.type[key];
|
||||
}
|
||||
else {
|
||||
@@ -958,12 +1057,12 @@ namespace ts {
|
||||
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
|
||||
// file map with a possibly case insensitive key. We use this map later when when including
|
||||
// wildcard paths.
|
||||
const literalFileMap: Map<string> = {};
|
||||
const literalFileMap = createMap<string>();
|
||||
|
||||
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
|
||||
// file map with a possibly case insensitive key. We use this map to store paths matched
|
||||
// via wildcard, and to handle extension priority.
|
||||
const wildcardFileMap: Map<string> = {};
|
||||
const wildcardFileMap = createMap<string>();
|
||||
|
||||
if (include) {
|
||||
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
|
||||
@@ -1011,7 +1110,7 @@ namespace ts {
|
||||
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
|
||||
|
||||
const key = keyMapper(file);
|
||||
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
|
||||
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
|
||||
wildcardFileMap[key] = file;
|
||||
}
|
||||
}
|
||||
@@ -1063,7 +1162,7 @@ namespace ts {
|
||||
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
|
||||
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
|
||||
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
|
||||
const wildcardDirectories: Map<WatchDirectoryFlags> = {};
|
||||
const wildcardDirectories = createMap<WatchDirectoryFlags>();
|
||||
if (include !== undefined) {
|
||||
const recursiveKeys: string[] = [];
|
||||
for (const file of include) {
|
||||
@@ -1076,7 +1175,7 @@ namespace ts {
|
||||
if (match) {
|
||||
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
|
||||
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
|
||||
const existingFlags = getProperty(wildcardDirectories, key);
|
||||
const existingFlags = wildcardDirectories[key];
|
||||
if (existingFlags === undefined || existingFlags < flags) {
|
||||
wildcardDirectories[key] = flags;
|
||||
if (flags === WatchDirectoryFlags.Recursive) {
|
||||
@@ -1088,11 +1187,9 @@ namespace ts {
|
||||
|
||||
// Remove any subpaths under an existing recursively watched directory.
|
||||
for (const key in wildcardDirectories) {
|
||||
if (hasProperty(wildcardDirectories, key)) {
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
}
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,7 +1212,7 @@ namespace ts {
|
||||
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
|
||||
const higherPriorityExtension = extensions[i];
|
||||
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
|
||||
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
|
||||
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+238
-95
@@ -19,8 +19,28 @@ namespace ts {
|
||||
True = -1
|
||||
}
|
||||
|
||||
const createObject = Object.create;
|
||||
|
||||
export function createMap<T>(template?: MapLike<T>): Map<T> {
|
||||
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
|
||||
|
||||
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
|
||||
// This disables creation of hidden classes, which are expensive when an object is
|
||||
// constantly changing shape.
|
||||
map["__"] = undefined;
|
||||
delete map["__"];
|
||||
|
||||
// Copies keys/values from template. Note that for..in will not throw if
|
||||
// template is undefined, and instead will just exit the loop.
|
||||
for (const key in template) if (hasOwnProperty.call(template, key)) {
|
||||
map[key] = template[key];
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
|
||||
let files: Map<T> = {};
|
||||
let files = createMap<T>();
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
@@ -46,7 +66,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function contains(path: Path) {
|
||||
return hasProperty(files, toKey(path));
|
||||
return toKey(path) in files;
|
||||
}
|
||||
|
||||
function remove(path: Path) {
|
||||
@@ -55,7 +75,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function clear() {
|
||||
files = {};
|
||||
files = createMap<T>();
|
||||
}
|
||||
|
||||
function toKey(path: Path): string {
|
||||
@@ -81,7 +101,7 @@ namespace ts {
|
||||
* returns a truthy value, then returns that value.
|
||||
* If no such value is found, the callback is applied to each element of array and undefined is returned.
|
||||
*/
|
||||
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
export function forEach<T, U>(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
|
||||
if (array) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const result = callback(array[i], i);
|
||||
@@ -93,6 +113,31 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */
|
||||
export function find<T>(array: T[], predicate: (element: T, index: number) => boolean): T | undefined {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const value = array[i];
|
||||
if (predicate(value, i)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first truthy result of `callback`, or else fails.
|
||||
* This is like `forEach`, but never returns undefined.
|
||||
*/
|
||||
export function findMap<T, U>(array: T[], callback: (element: T, index: number) => U | undefined): U {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Debug.fail();
|
||||
}
|
||||
|
||||
export function contains<T>(array: T[], value: T): boolean {
|
||||
if (array) {
|
||||
for (const v of array) {
|
||||
@@ -136,17 +181,44 @@ namespace ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an array by a predicate function. Returns the same array instance if the predicate is
|
||||
* true for all elements, otherwise returns a new array instance containing the filtered subset.
|
||||
*/
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
let result: T[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (const item of array) {
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
const len = array.length;
|
||||
let i = 0;
|
||||
while (i < len && f(array[i])) i++;
|
||||
if (i < len) {
|
||||
const result = array.slice(0, i);
|
||||
i++;
|
||||
while (i < len) {
|
||||
const item = array[i];
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return array;
|
||||
}
|
||||
|
||||
export function removeWhere<T>(array: T[], f: (x: T) => boolean): boolean {
|
||||
let outIndex = 0;
|
||||
for (const item of array) {
|
||||
if (!f(item)) {
|
||||
array[outIndex] = item;
|
||||
outIndex++;
|
||||
}
|
||||
}
|
||||
if (outIndex !== array.length) {
|
||||
array.length = outIndex;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function filterMutate<T>(array: T[], f: (x: T) => boolean): void {
|
||||
@@ -324,82 +396,142 @@ namespace ts {
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||||
/**
|
||||
* Indicates whether a map-like contains an own property with the specified key.
|
||||
*
|
||||
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
|
||||
* the 'in' operator.
|
||||
*
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
}
|
||||
|
||||
export function getKeys<T>(map: Map<T>): string[] {
|
||||
/**
|
||||
* Gets the value of an owned property in a map-like.
|
||||
*
|
||||
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
|
||||
* an indexer.
|
||||
*
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
|
||||
return hasOwnProperty.call(map, key) ? map[key] : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owned, enumerable property keys of a map-like.
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* Object.keys instead as it offers better performance.
|
||||
*
|
||||
* @param map A map-like.
|
||||
*/
|
||||
export function getOwnKeys<T>(map: MapLike<T>): string[] {
|
||||
const keys: string[] = [];
|
||||
for (const key in map) {
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
export function getProperty<T>(map: Map<T>, key: string): T | undefined {
|
||||
return hasProperty(map, key) ? map[key] : undefined;
|
||||
/**
|
||||
* Enumerates the properties of a Map<T>, invoking a callback and returning the first truthy result.
|
||||
*
|
||||
* @param map A map for which properties should be enumerated.
|
||||
* @param callback A callback to invoke for each property.
|
||||
*/
|
||||
export function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U {
|
||||
let result: U;
|
||||
for (const key in map) {
|
||||
if (result = callback(map[key], key)) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getOrUpdateProperty<T>(map: Map<T>, key: string, makeValue: () => T): T {
|
||||
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
|
||||
/**
|
||||
* Returns true if a Map<T> has some matching property.
|
||||
*
|
||||
* @param map A map whose properties should be tested.
|
||||
* @param predicate An optional callback used to test each property.
|
||||
*/
|
||||
export function someProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
|
||||
for (const key in map) {
|
||||
if (!predicate || predicate(map[key], key)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isEmpty<T>(map: Map<T>) {
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Performs a shallow copy of the properties from a source Map<T> to a target MapLike<T>
|
||||
*
|
||||
* @param source A map from which properties should be copied.
|
||||
* @param target A map to which properties should be copied.
|
||||
*/
|
||||
export function copyProperties<T>(source: Map<T>, target: MapLike<T>): void {
|
||||
for (const key in source) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
|
||||
* reduceOwnProperties instead as it offers better runtime safety.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
for (const key in map) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties defined on a map-like (but not from its prototype chain).
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* reduceProperties instead as it offers better performance.
|
||||
*
|
||||
* @param map The map-like to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a shallow equality comparison of the contents of two map-likes.
|
||||
*
|
||||
* @param left A map-like whose properties should be compared.
|
||||
* @param right A map-like whose properties should be compared.
|
||||
*/
|
||||
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>, equalityComparer?: (left: T, right: T) => boolean) {
|
||||
if (left === right) return true;
|
||||
if (!left || !right) return false;
|
||||
for (const key in left) if (hasOwnProperty.call(left, key)) {
|
||||
if (!hasOwnProperty.call(right, key) === undefined) return false;
|
||||
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
|
||||
}
|
||||
for (const key in right) if (hasOwnProperty.call(right, key)) {
|
||||
if (!hasOwnProperty.call(left, key)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
const result: any = {};
|
||||
for (const id in object) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
return <T>result;
|
||||
}
|
||||
|
||||
export function extend<T1 extends Map<{}>, T2 extends Map<{}>>(first: T1 , second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in first) {
|
||||
(result as any)[id] = first[id];
|
||||
}
|
||||
for (const id in second) {
|
||||
if (!hasProperty(result, id)) {
|
||||
(result as any)[id] = second[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
|
||||
let result: U;
|
||||
for (const id in map) {
|
||||
if (result = callback(map[id])) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
|
||||
let result: U;
|
||||
for (const id in map) {
|
||||
if (result = callback(id)) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function lookUp<T>(map: Map<T>, key: string): T {
|
||||
return hasProperty(map, key) ? map[key] : undefined;
|
||||
}
|
||||
|
||||
export function copyMap<T>(source: Map<T>, target: Map<T>): void {
|
||||
for (const p in source) {
|
||||
target[p] = source[p];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a map from the elements of an array.
|
||||
*
|
||||
@@ -410,33 +542,40 @@ namespace ts {
|
||||
* the same key with the given 'makeKey' function, then the element with the higher
|
||||
* index in the array will be the one associated with the produced key.
|
||||
*/
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
|
||||
const result: Map<T> = {};
|
||||
|
||||
forEach(array, value => {
|
||||
result[makeKey(value)] = value;
|
||||
});
|
||||
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
|
||||
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
|
||||
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map<T | U> {
|
||||
const result = createMap<T | U>();
|
||||
for (const value of array) {
|
||||
result[makeKey(value)] = makeValue ? makeValue(value) : value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
if (map) {
|
||||
for (const key in map) {
|
||||
if (hasProperty(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
export function cloneMap<T>(map: Map<T>) {
|
||||
const clone = createMap<T>();
|
||||
copyProperties(map, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
const result: any = {};
|
||||
for (const id in object) {
|
||||
if (hasOwnProperty.call(object, id)) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in second) if (hasOwnProperty.call(second, id)) {
|
||||
(result as any)[id] = (second as any)[id];
|
||||
}
|
||||
for (const id in first) if (hasOwnProperty.call(first, id)) {
|
||||
(result as any)[id] = (first as any)[id];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -467,9 +606,7 @@ namespace ts {
|
||||
export let localizedDiagnosticMessages: Map<string> = undefined;
|
||||
|
||||
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key]
|
||||
? localizedDiagnosticMessages[message.key]
|
||||
: message.message;
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
|
||||
}
|
||||
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
@@ -1205,6 +1342,8 @@ namespace ts {
|
||||
* List of supported extensions in order of file resolution precedence.
|
||||
*/
|
||||
export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"];
|
||||
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
|
||||
export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"];
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
@@ -1287,8 +1426,12 @@ namespace ts {
|
||||
return path;
|
||||
}
|
||||
|
||||
export function tryRemoveExtension(path: string, extension: string): string {
|
||||
return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined;
|
||||
export function tryRemoveExtension(path: string, extension: string): string | undefined {
|
||||
return fileExtensionIs(path, extension) ? removeExtension(path, extension) : undefined;
|
||||
}
|
||||
|
||||
export function removeExtension(path: string, extension: string): string {
|
||||
return path.substring(0, path.length - extension.length);
|
||||
}
|
||||
|
||||
export function isJsxOrTsxExtension(ext: string): boolean {
|
||||
|
||||
@@ -157,9 +157,7 @@ namespace ts {
|
||||
|
||||
if (usedTypeDirectiveReferences) {
|
||||
for (const directive in usedTypeDirectiveReferences) {
|
||||
if (hasProperty(usedTypeDirectiveReferences, directive)) {
|
||||
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
|
||||
}
|
||||
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +267,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!usedTypeDirectiveReferences) {
|
||||
usedTypeDirectiveReferences = {};
|
||||
usedTypeDirectiveReferences = createMap<string>();
|
||||
}
|
||||
for (const directive of typeReferenceDirectives) {
|
||||
if (!hasProperty(usedTypeDirectiveReferences, directive)) {
|
||||
if (!(directive in usedTypeDirectiveReferences)) {
|
||||
usedTypeDirectiveReferences[directive] = directive;
|
||||
}
|
||||
}
|
||||
@@ -441,7 +439,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
|
||||
function emitEntityName(entityName: EntityNameOrEntityNameExpression) {
|
||||
const visibilityResult = resolver.isEntityNameVisible(entityName,
|
||||
// Aliases can be written asynchronously so use correct enclosing declaration
|
||||
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
|
||||
@@ -452,9 +450,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
|
||||
if (isSupportedExpressionWithTypeArguments(node)) {
|
||||
if (isEntityNameExpression(node.expression)) {
|
||||
Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
|
||||
emitEntityName(<Identifier | PropertyAccessExpression>node.expression);
|
||||
emitEntityName(node.expression);
|
||||
if (node.typeArguments) {
|
||||
write("<");
|
||||
emitCommaList(node.typeArguments, emitType);
|
||||
@@ -537,14 +535,14 @@ namespace ts {
|
||||
// do not need to keep track of created temp names.
|
||||
function getExportDefaultTempVariableName(): string {
|
||||
const baseName = "_default";
|
||||
if (!hasProperty(currentIdentifiers, baseName)) {
|
||||
if (!(baseName in currentIdentifiers)) {
|
||||
return baseName;
|
||||
}
|
||||
let count = 0;
|
||||
while (true) {
|
||||
count++;
|
||||
const name = baseName + "_" + count;
|
||||
if (!hasProperty(currentIdentifiers, name)) {
|
||||
if (!(name in currentIdentifiers)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1019,7 +1017,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) {
|
||||
if (isSupportedExpressionWithTypeArguments(node)) {
|
||||
if (isEntityNameExpression(node.expression)) {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
|
||||
}
|
||||
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
|
||||
@@ -1134,8 +1132,10 @@ namespace ts {
|
||||
// it if it's not a well known symbol. In that case, the text of the name will be exactly
|
||||
// what we want, namely the name expression enclosed in brackets.
|
||||
writeTextOfNode(currentText, node.name);
|
||||
// If optional property emit ?
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.Parameter) && hasQuestionToken(node)) {
|
||||
// If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor
|
||||
// we don't want to emit property declaration with "?"
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
|
||||
(node.kind === SyntaxKind.Parameter && !isParameterPropertyDeclaration(node))) && hasQuestionToken(node)) {
|
||||
write("?");
|
||||
}
|
||||
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
|
||||
|
||||
@@ -1951,6 +1951,14 @@
|
||||
"category": "Error",
|
||||
"code": 2690
|
||||
},
|
||||
"An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
|
||||
"category": "Error",
|
||||
"code": 2691
|
||||
},
|
||||
"'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible.": {
|
||||
"category": "Error",
|
||||
"code": 2692
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
@@ -2231,7 +2239,7 @@
|
||||
"category": "Error",
|
||||
"code": 4082
|
||||
},
|
||||
"Conflicting library definitions for '{0}' found at '{1}' and '{2}'. Copy the correct file to the 'typings' folder to resolve this conflict.": {
|
||||
"Conflicting definitions for '{0}' found at '{1}' and '{2}'. Consider installing a specific version of this library to resolve the conflict.": {
|
||||
"category": "Message",
|
||||
"code": 4090
|
||||
},
|
||||
@@ -2828,6 +2836,10 @@
|
||||
"category": "Message",
|
||||
"code": 6137
|
||||
},
|
||||
"Property '{0}' is declared but never used.": {
|
||||
"category": "Error",
|
||||
"code": 6138
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
|
||||
+46
-37
@@ -24,7 +24,7 @@ namespace ts {
|
||||
Return = 1 << 3
|
||||
}
|
||||
|
||||
const entities: Map<number> = {
|
||||
const entities = createMap({
|
||||
"quot": 0x0022,
|
||||
"amp": 0x0026,
|
||||
"apos": 0x0027,
|
||||
@@ -278,7 +278,7 @@ namespace ts {
|
||||
"clubs": 0x2663,
|
||||
"hearts": 0x2665,
|
||||
"diams": 0x2666
|
||||
};
|
||||
});
|
||||
|
||||
// Flags enum to track count of temp variables and a few dedicated names
|
||||
const enum TempFlags {
|
||||
@@ -407,7 +407,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
function isUniqueLocalName(name: string, container: Node): boolean {
|
||||
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
|
||||
if (node.locals && hasProperty(node.locals, name)) {
|
||||
if (node.locals && name in node.locals) {
|
||||
// We conservatively include alias symbols to cover cases where they're emitted as locals
|
||||
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
|
||||
return false;
|
||||
@@ -489,13 +489,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void {
|
||||
if (isBreak) {
|
||||
if (!state.labeledNonLocalBreaks) {
|
||||
state.labeledNonLocalBreaks = {};
|
||||
state.labeledNonLocalBreaks = createMap<string>();
|
||||
}
|
||||
state.labeledNonLocalBreaks[labelText] = labelMarker;
|
||||
}
|
||||
else {
|
||||
if (!state.labeledNonLocalContinues) {
|
||||
state.labeledNonLocalContinues = {};
|
||||
state.labeledNonLocalContinues = createMap<string>();
|
||||
}
|
||||
state.labeledNonLocalContinues[labelText] = labelMarker;
|
||||
}
|
||||
@@ -577,27 +577,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { };
|
||||
|
||||
const moduleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
|
||||
const moduleEmitDelegates = createMap<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void>({
|
||||
[ModuleKind.ES6]: emitES6Module,
|
||||
[ModuleKind.AMD]: emitAMDModule,
|
||||
[ModuleKind.System]: emitSystemModule,
|
||||
[ModuleKind.UMD]: emitUMDModule,
|
||||
[ModuleKind.CommonJS]: emitCommonJSModule,
|
||||
};
|
||||
});
|
||||
|
||||
const bundleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
|
||||
const bundleEmitDelegates = createMap<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void>({
|
||||
[ModuleKind.ES6]() {},
|
||||
[ModuleKind.AMD]: emitAMDModule,
|
||||
[ModuleKind.System]: emitSystemModule,
|
||||
[ModuleKind.UMD]() {},
|
||||
[ModuleKind.CommonJS]() {},
|
||||
};
|
||||
});
|
||||
|
||||
return doEmit;
|
||||
|
||||
function doEmit(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
|
||||
generatedNameSet = {};
|
||||
generatedNameSet = createMap<string>();
|
||||
nodeToGeneratedName = [];
|
||||
decoratedClassAliases = [];
|
||||
isOwnFileEmit = !isBundledEmit;
|
||||
@@ -669,8 +669,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
function isUniqueName(name: string): boolean {
|
||||
return !resolver.hasGlobalName(name) &&
|
||||
!hasProperty(currentFileIdentifiers, name) &&
|
||||
!hasProperty(generatedNameSet, name);
|
||||
!(name in currentFileIdentifiers) &&
|
||||
!(name in generatedNameSet);
|
||||
}
|
||||
|
||||
// Return the next available name in the pattern _a ... _z, _0, _1, ...
|
||||
@@ -1817,6 +1817,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
else if (node.parent.kind === SyntaxKind.ConditionalExpression && (<ConditionalExpression>node.parent).condition === node) {
|
||||
return true;
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.PrefixUnaryExpression || node.parent.kind === SyntaxKind.DeleteExpression ||
|
||||
node.parent.kind === SyntaxKind.TypeOfExpression || node.parent.kind === SyntaxKind.VoidExpression) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -2646,7 +2650,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
return false;
|
||||
}
|
||||
|
||||
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
|
||||
return !exportEquals && exportSpecifiers && (<Identifier>node).text in exportSpecifiers;
|
||||
}
|
||||
|
||||
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
|
||||
@@ -3257,13 +3261,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
// Don't initialize seen unless we have at least one element.
|
||||
// Emit a comma to separate for all but the first element.
|
||||
if (!seen) {
|
||||
seen = {};
|
||||
seen = createMap<string>();
|
||||
}
|
||||
else {
|
||||
write(", ");
|
||||
}
|
||||
|
||||
if (!hasProperty(seen, id.text)) {
|
||||
if (!(id.text in seen)) {
|
||||
emit(id);
|
||||
seen[id.text] = id.text;
|
||||
}
|
||||
@@ -3856,7 +3860,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
|
||||
if (convertedLoopState) {
|
||||
if (!convertedLoopState.labels) {
|
||||
convertedLoopState.labels = {};
|
||||
convertedLoopState.labels = createMap<string>();
|
||||
}
|
||||
convertedLoopState.labels[node.label.text] = node.label.text;
|
||||
}
|
||||
@@ -3970,7 +3974,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
return;
|
||||
}
|
||||
|
||||
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
|
||||
if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) {
|
||||
for (const specifier of exportSpecifiers[name.text]) {
|
||||
writeLine();
|
||||
emitStart(specifier.name);
|
||||
@@ -5311,18 +5315,22 @@ const _super = (function (geti, seti) {
|
||||
emitSignatureParameters(ctor);
|
||||
}
|
||||
else {
|
||||
// Based on EcmaScript6 section 14.5.14: Runtime Semantics: ClassDefinitionEvaluation.
|
||||
// If constructor is empty, then,
|
||||
// If ClassHeritageopt is present, then
|
||||
// Let constructor be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol MethodDefinition.
|
||||
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
|
||||
// If constructor is empty, then
|
||||
// If ClassHeritag_eopt is present and protoParent is not null, then
|
||||
// Let constructor be the result of parsing the source text
|
||||
// constructor(...args) { super (...args);}
|
||||
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
|
||||
// Else,
|
||||
// Let constructor be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol MethodDefinition
|
||||
if (baseTypeElement) {
|
||||
write("(...args)");
|
||||
}
|
||||
else {
|
||||
write("()");
|
||||
}
|
||||
// Let constructor be the result of parsing the source text
|
||||
// constructor( ){ }
|
||||
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
|
||||
//
|
||||
// While we could emit the '...args' rest parameter, certain later tools in the pipeline might
|
||||
// downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array.
|
||||
// Instead, we'll avoid using a rest parameter and spread into the super call as
|
||||
// 'super(...arguments)' instead of 'super(...args)', as you can see below.
|
||||
write("()");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5360,7 +5368,8 @@ const _super = (function (geti, seti) {
|
||||
write("_super.apply(this, arguments);");
|
||||
}
|
||||
else {
|
||||
write("super(...args);");
|
||||
// See comment above on using '...arguments' instead of '...args'.
|
||||
write("super(...arguments);");
|
||||
}
|
||||
emitEnd(baseTypeElement);
|
||||
}
|
||||
@@ -6461,7 +6470,7 @@ const _super = (function (geti, seti) {
|
||||
* Here we check if alternative name was provided for a given moduleName and return it if possible.
|
||||
*/
|
||||
function tryRenameExternalModule(moduleName: LiteralExpression): string {
|
||||
if (renamedDependencies && hasProperty(renamedDependencies, moduleName.text)) {
|
||||
if (renamedDependencies && moduleName.text in renamedDependencies) {
|
||||
return `"${renamedDependencies[moduleName.text]}"`;
|
||||
}
|
||||
return undefined;
|
||||
@@ -6803,7 +6812,7 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function collectExternalModuleInfo(sourceFile: SourceFile) {
|
||||
externalImports = [];
|
||||
exportSpecifiers = {};
|
||||
exportSpecifiers = createMap<ExportSpecifier[]>();
|
||||
exportEquals = undefined;
|
||||
hasExportStarsToExportValues = false;
|
||||
for (const node of sourceFile.statements) {
|
||||
@@ -6842,7 +6851,7 @@ const _super = (function (geti, seti) {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
const name = (specifier.propertyName || specifier.name).text;
|
||||
getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
|
||||
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -6941,7 +6950,7 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
|
||||
// local names set should only be added if we have anything exported
|
||||
if (!exportedDeclarations && isEmpty(exportSpecifiers)) {
|
||||
if (!exportedDeclarations && !someProperties(exportSpecifiers)) {
|
||||
// no exported declarations (export var ...) or export specifiers (export {x})
|
||||
// check if we have any non star export declarations.
|
||||
let hasExportDeclarationWithExportClause = false;
|
||||
@@ -7081,7 +7090,7 @@ const _super = (function (geti, seti) {
|
||||
if (hoistedVars) {
|
||||
writeLine();
|
||||
write("var ");
|
||||
const seen: Map<string> = {};
|
||||
const seen = createMap<string>();
|
||||
for (let i = 0; i < hoistedVars.length; i++) {
|
||||
const local = hoistedVars[i];
|
||||
const name = local.kind === SyntaxKind.Identifier
|
||||
@@ -7091,7 +7100,7 @@ const _super = (function (geti, seti) {
|
||||
if (name) {
|
||||
// do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables
|
||||
const text = unescapeIdentifier(name.text);
|
||||
if (hasProperty(seen, text)) {
|
||||
if (text in seen) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
@@ -7447,7 +7456,7 @@ const _super = (function (geti, seti) {
|
||||
writeModuleName(node, emitRelativePathAsModuleName);
|
||||
write("[");
|
||||
|
||||
const groupIndices: Map<number> = {};
|
||||
const groupIndices = createMap<number>();
|
||||
const dependencyGroups: DependencyGroup[] = [];
|
||||
|
||||
for (let i = 0; i < externalImports.length; i++) {
|
||||
@@ -7460,7 +7469,7 @@ const _super = (function (geti, seti) {
|
||||
// for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same
|
||||
const key = text.substr(1, text.length - 2);
|
||||
|
||||
if (hasProperty(groupIndices, key)) {
|
||||
if (key in groupIndices) {
|
||||
// deduplicate/group entries in dependency list by the dependency name
|
||||
const groupIndex = groupIndices[key];
|
||||
dependencyGroups[groupIndex].push(externalImports[i]);
|
||||
|
||||
+58
-21
@@ -417,14 +417,16 @@ namespace ts {
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return visitNode(cbNode, (<JSDocPropertyTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocPropertyTag>node).name);
|
||||
case SyntaxKind.JSDocLiteralType:
|
||||
return visitNode(cbNode, (<JSDocLiteralType>node).literal);
|
||||
}
|
||||
}
|
||||
|
||||
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeParse");
|
||||
const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
|
||||
|
||||
performance.measure("Parse", start);
|
||||
performance.mark("afterParse");
|
||||
performance.measure("Parse", "beforeParse", "afterParse");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -595,7 +597,7 @@ namespace ts {
|
||||
|
||||
parseDiagnostics = [];
|
||||
parsingContext = 0;
|
||||
identifiers = {};
|
||||
identifiers = createMap<string>();
|
||||
identifierCount = 0;
|
||||
nodeCount = 0;
|
||||
|
||||
@@ -910,7 +912,7 @@ namespace ts {
|
||||
// Note: it is not actually necessary to save/restore the context flags here. That's
|
||||
// because the saving/restoring of these flags happens naturally through the recursive
|
||||
// descent nature of our parser. However, we still store this here just so we can
|
||||
// assert that that invariant holds.
|
||||
// assert that invariant holds.
|
||||
const saveContextFlags = contextFlags;
|
||||
|
||||
// If we're only looking ahead, then tell the scanner to only lookahead as well.
|
||||
@@ -1084,7 +1086,7 @@ namespace ts {
|
||||
|
||||
function internIdentifier(text: string): string {
|
||||
text = escapeIdentifier(text);
|
||||
return hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
|
||||
return identifiers[text] || (identifiers[text] = text);
|
||||
}
|
||||
|
||||
// An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
|
||||
@@ -2763,7 +2765,7 @@ namespace ts {
|
||||
// Note: for ease of implementation we treat productions '2' and '3' as the same thing.
|
||||
// (i.e. they're both BinaryExpressions with an assignment operator in it).
|
||||
|
||||
// First, do the simple check if we have a YieldExpression (production '5').
|
||||
// First, do the simple check if we have a YieldExpression (production '6').
|
||||
if (isYieldExpression()) {
|
||||
return parseYieldExpression();
|
||||
}
|
||||
@@ -3371,24 +3373,40 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ES7 unary expression and await expression
|
||||
* Parse ES7 exponential expression and await expression
|
||||
*
|
||||
* ES7 ExponentiationExpression:
|
||||
* 1) UnaryExpression[?Yield]
|
||||
* 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
|
||||
*
|
||||
* ES7 UnaryExpression:
|
||||
* 1) SimpleUnaryExpression[?yield]
|
||||
* 2) IncrementExpression[?yield] ** UnaryExpression[?yield]
|
||||
*/
|
||||
function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
|
||||
if (isAwaitExpression()) {
|
||||
return parseAwaitExpression();
|
||||
}
|
||||
|
||||
if (isIncrementExpression()) {
|
||||
/**
|
||||
* ES7 UpdateExpression:
|
||||
* 1) LeftHandSideExpression[?Yield]
|
||||
* 2) LeftHandSideExpression[?Yield][no LineTerminator here]++
|
||||
* 3) LeftHandSideExpression[?Yield][no LineTerminator here]--
|
||||
* 4) ++UnaryExpression[?Yield]
|
||||
* 5) --UnaryExpression[?Yield]
|
||||
*/
|
||||
if (isUpdateExpression()) {
|
||||
const incrementExpression = parseIncrementExpression();
|
||||
return token() === SyntaxKind.AsteriskAsteriskToken ?
|
||||
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
|
||||
incrementExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* ES7 UnaryExpression:
|
||||
* 1) UpdateExpression[?yield]
|
||||
* 2) delete UpdateExpression[?yield]
|
||||
* 3) void UpdateExpression[?yield]
|
||||
* 4) typeof UpdateExpression[?yield]
|
||||
* 5) + UpdateExpression[?yield]
|
||||
* 6) - UpdateExpression[?yield]
|
||||
* 7) ~ UpdateExpression[?yield]
|
||||
* 8) ! UpdateExpression[?yield]
|
||||
*/
|
||||
const unaryOperator = token();
|
||||
const simpleUnaryExpression = parseSimpleUnaryExpression();
|
||||
if (token() === SyntaxKind.AsteriskAsteriskToken) {
|
||||
@@ -3406,8 +3424,8 @@ namespace ts {
|
||||
/**
|
||||
* Parse ES7 simple-unary expression or higher:
|
||||
*
|
||||
* ES7 SimpleUnaryExpression:
|
||||
* 1) IncrementExpression[?yield]
|
||||
* ES7 UnaryExpression:
|
||||
* 1) UpdateExpression[?yield]
|
||||
* 2) delete UnaryExpression[?yield]
|
||||
* 3) void UnaryExpression[?yield]
|
||||
* 4) typeof UnaryExpression[?yield]
|
||||
@@ -3415,6 +3433,7 @@ namespace ts {
|
||||
* 6) - UnaryExpression[?yield]
|
||||
* 7) ~ UnaryExpression[?yield]
|
||||
* 8) ! UnaryExpression[?yield]
|
||||
* 9) [+Await] await UnaryExpression[?yield]
|
||||
*/
|
||||
function parseSimpleUnaryExpression(): UnaryExpression {
|
||||
switch (token()) {
|
||||
@@ -3434,6 +3453,10 @@ namespace ts {
|
||||
// UnaryExpression (modified):
|
||||
// < type > UnaryExpression
|
||||
return parseTypeAssertion();
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
if (isAwaitExpression()) {
|
||||
return parseAwaitExpression();
|
||||
}
|
||||
default:
|
||||
return parseIncrementExpression();
|
||||
}
|
||||
@@ -3442,14 +3465,14 @@ namespace ts {
|
||||
/**
|
||||
* Check if the current token can possibly be an ES7 increment expression.
|
||||
*
|
||||
* ES7 IncrementExpression:
|
||||
* ES7 UpdateExpression:
|
||||
* LeftHandSideExpression[?Yield]
|
||||
* LeftHandSideExpression[?Yield][no LineTerminator here]++
|
||||
* LeftHandSideExpression[?Yield][no LineTerminator here]--
|
||||
* ++LeftHandSideExpression[?Yield]
|
||||
* --LeftHandSideExpression[?Yield]
|
||||
*/
|
||||
function isIncrementExpression(): boolean {
|
||||
function isUpdateExpression(): boolean {
|
||||
// This function is called inside parseUnaryExpression to decide
|
||||
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
|
||||
switch (token()) {
|
||||
@@ -3460,6 +3483,7 @@ namespace ts {
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
return false;
|
||||
case SyntaxKind.LessThanToken:
|
||||
// If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
|
||||
@@ -5888,10 +5912,17 @@ namespace ts {
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.UndefinedKeyword:
|
||||
case SyntaxKind.NeverKeyword:
|
||||
return parseTokenNode<JSDocType>();
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
return parseJSDocLiteralType();
|
||||
}
|
||||
|
||||
// TODO (drosen): Parse string literal types in JSDoc as well.
|
||||
return parseJSDocTypeReference();
|
||||
}
|
||||
|
||||
@@ -6070,6 +6101,12 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseJSDocLiteralType(): JSDocLiteralType {
|
||||
const result = <JSDocLiteralType>createNode(SyntaxKind.JSDocLiteralType);
|
||||
result.literal = parseLiteralTypeNode();
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
|
||||
const pos = scanner.getStartPos();
|
||||
// skip the ?
|
||||
|
||||
+50
-64
@@ -6,71 +6,57 @@ namespace ts {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
/** Performance measurements for the compiler. */
|
||||
namespace ts.performance {
|
||||
/** Performance measurements for the compiler. */
|
||||
declare const onProfilerEvent: { (markName: string): void; profiler: boolean; };
|
||||
let profilerEvent: (markName: string) => void;
|
||||
let counters: Map<number>;
|
||||
|
||||
const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
|
||||
? onProfilerEvent
|
||||
: (markName: string) => { };
|
||||
|
||||
let enabled = false;
|
||||
let profilerStart = 0;
|
||||
let counts: Map<number>;
|
||||
let marks: Map<number>;
|
||||
let measures: Map<number>;
|
||||
|
||||
/**
|
||||
* Emit a performance event if ts-profiler is connected. This is primarily used
|
||||
* to generate heap snapshots.
|
||||
* Marks a performance event.
|
||||
*
|
||||
* @param eventName A name for the event.
|
||||
* @param markName The name of the mark.
|
||||
*/
|
||||
export function emit(eventName: string) {
|
||||
if (profilerEvent) {
|
||||
profilerEvent(eventName);
|
||||
export function mark(markName: string) {
|
||||
if (enabled) {
|
||||
marks[markName] = timestamp();
|
||||
counts[markName] = (counts[markName] || 0) + 1;
|
||||
profilerEvent(markName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a counter with the specified name.
|
||||
*
|
||||
* @param counterName The name of the counter.
|
||||
*/
|
||||
export function increment(counterName: string) {
|
||||
if (counters) {
|
||||
counters[counterName] = (getProperty(counters, counterName) || 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the counter with the specified name.
|
||||
*
|
||||
* @param counterName The name of the counter.
|
||||
*/
|
||||
export function getCount(counterName: string) {
|
||||
return counters && getProperty(counters, counterName) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the start of a performance measurement.
|
||||
*/
|
||||
export function mark() {
|
||||
return measures ? timestamp() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a performance measurement with the specified name.
|
||||
*
|
||||
* @param measureName The name of the performance measurement.
|
||||
* @param marker The timestamp of the starting mark.
|
||||
* @param startMarkName The name of the starting mark. If not supplied, the point at which the
|
||||
* profiler was enabled is used.
|
||||
* @param endMarkName The name of the ending mark. If not supplied, the current timestamp is
|
||||
* used.
|
||||
*/
|
||||
export function measure(measureName: string, marker: number) {
|
||||
if (measures) {
|
||||
measures[measureName] = (getProperty(measures, measureName) || 0) + (timestamp() - marker);
|
||||
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
|
||||
if (enabled) {
|
||||
const end = endMarkName && marks[endMarkName] || timestamp();
|
||||
const start = startMarkName && marks[startMarkName] || profilerStart;
|
||||
measures[measureName] = (measures[measureName] || 0) + (end - start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each measure, performing some action
|
||||
*
|
||||
* @param cb The action to perform for each measure
|
||||
* Gets the number of times a marker was encountered.
|
||||
*
|
||||
* @param markName The name of the mark.
|
||||
*/
|
||||
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
|
||||
return forEachKey(measures, key => cb(key, measures[key]));
|
||||
export function getCount(markName: string) {
|
||||
return counts && counts[markName] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,31 +65,31 @@ namespace ts.performance {
|
||||
* @param measureName The name of the measure whose durations should be accumulated.
|
||||
*/
|
||||
export function getDuration(measureName: string) {
|
||||
return measures && getProperty(measures, measureName) || 0;
|
||||
return measures && measures[measureName] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each measure, performing some action
|
||||
*
|
||||
* @param cb The action to perform for each measure
|
||||
*/
|
||||
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
|
||||
for (const key in measures) {
|
||||
cb(key, measures[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Enables (and resets) performance measurements for the compiler. */
|
||||
export function enable() {
|
||||
counters = { };
|
||||
measures = {
|
||||
"I/O Read": 0,
|
||||
"I/O Write": 0,
|
||||
"Program": 0,
|
||||
"Parse": 0,
|
||||
"Bind": 0,
|
||||
"Check": 0,
|
||||
"Emit": 0,
|
||||
};
|
||||
|
||||
profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
|
||||
? onProfilerEvent
|
||||
: undefined;
|
||||
counts = createMap<number>();
|
||||
marks = createMap<number>();
|
||||
measures = createMap<number>();
|
||||
enabled = true;
|
||||
profilerStart = timestamp();
|
||||
}
|
||||
|
||||
/** Disables (and clears) performance measurements for the compiler. */
|
||||
/** Disables performance measurements for the compiler. */
|
||||
export function disable() {
|
||||
counters = undefined;
|
||||
measures = undefined;
|
||||
profilerEvent = undefined;
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
+114
-115
@@ -119,49 +119,31 @@ namespace ts {
|
||||
}
|
||||
|
||||
function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
|
||||
let jsonContent: { typings?: string, types?: string, main?: string };
|
||||
try {
|
||||
const jsonText = state.host.readFile(packageJsonPath);
|
||||
jsonContent = jsonText ? <{ typings?: string, types?: string, main?: string }>JSON.parse(jsonText) : {};
|
||||
}
|
||||
catch (e) {
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
jsonContent = {};
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
|
||||
function tryReadFromField(fieldName: string) {
|
||||
if (hasProperty(jsonContent, fieldName)) {
|
||||
const typesFile = (<any>jsonContent)[fieldName];
|
||||
if (typeof typesFile === "string") {
|
||||
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
|
||||
}
|
||||
return typesFilePath;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let typesFile: string;
|
||||
let fieldName: string;
|
||||
// first try to read content of 'typings' section (backward compatibility)
|
||||
if (jsonContent.typings) {
|
||||
if (typeof jsonContent.typings === "string") {
|
||||
fieldName = "typings";
|
||||
typesFile = jsonContent.typings;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings);
|
||||
}
|
||||
}
|
||||
}
|
||||
// then read 'types'
|
||||
if (!typesFile && jsonContent.types) {
|
||||
if (typeof jsonContent.types === "string") {
|
||||
fieldName = "types";
|
||||
typesFile = jsonContent.types;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typesFile) {
|
||||
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
|
||||
}
|
||||
const typesFilePath = tryReadFromField("typings") || tryReadFromField("types");
|
||||
if (typesFilePath) {
|
||||
return typesFilePath;
|
||||
}
|
||||
|
||||
// Use the main module for inferring types if no types package specified and the allowJs is set
|
||||
if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") {
|
||||
if (state.traceEnabled) {
|
||||
@@ -173,6 +155,17 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } {
|
||||
try {
|
||||
const jsonText = host.readFile(path);
|
||||
return jsonText ? JSON.parse(jsonText) : {};
|
||||
}
|
||||
catch (e) {
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const typeReferenceExtensions = [".d.ts"];
|
||||
|
||||
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
|
||||
@@ -508,7 +501,7 @@ namespace ts {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
|
||||
}
|
||||
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
|
||||
matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName);
|
||||
}
|
||||
|
||||
if (matchedPattern) {
|
||||
@@ -668,24 +661,27 @@ namespace ts {
|
||||
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
// First try to keep/add an extension: importing "./foo.ts" can be matched by a file "./foo.ts", and "./foo" by "./foo.d.ts"
|
||||
const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (resolvedByAddingOrKeepingExtension) {
|
||||
return resolvedByAddingOrKeepingExtension;
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
|
||||
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (resolvedByAddingExtension) {
|
||||
return resolvedByAddingExtension;
|
||||
}
|
||||
// Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
|
||||
// If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
|
||||
// e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
if (hasJavaScriptFileExtension(candidate)) {
|
||||
const extensionless = removeFileExtension(candidate);
|
||||
if (state.traceEnabled) {
|
||||
const extension = candidate.substring(extensionless.length);
|
||||
trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension);
|
||||
}
|
||||
return loadModuleFromFileWorker(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
}
|
||||
}
|
||||
|
||||
function loadModuleFromFileWorker(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
/** Try to return an existing file that adds one of the `extensions` to `candidate`. */
|
||||
function tryAddingExtensions(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
const directory = getDirectoryPath(candidate);
|
||||
@@ -693,31 +689,29 @@ namespace ts {
|
||||
onlyRecordFailures = !directoryProbablyExists(directory, state.host);
|
||||
}
|
||||
}
|
||||
return forEach(extensions, tryLoad);
|
||||
return forEach(extensions, ext =>
|
||||
!(state.skipTsx && isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state));
|
||||
}
|
||||
|
||||
function tryLoad(ext: string): string {
|
||||
if (state.skipTsx && isJsxOrTsxExtension(ext)) {
|
||||
return undefined;
|
||||
/** Return the file if it exists. */
|
||||
function tryFile(fileName: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures && state.host.fileExists(fileName)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName);
|
||||
}
|
||||
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
|
||||
if (!onlyRecordFailures && state.host.fileExists(fileName)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, fileName);
|
||||
}
|
||||
failedLookupLocation.push(fileName);
|
||||
return undefined;
|
||||
return fileName;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, fileName);
|
||||
}
|
||||
failedLookupLocation.push(fileName);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
const packageJsonPath = combinePaths(candidate, "package.json");
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
if (state.traceEnabled) {
|
||||
@@ -725,7 +719,10 @@ namespace ts {
|
||||
}
|
||||
const typesFile = tryReadTypesSection(packageJsonPath, candidate, state);
|
||||
if (typesFile) {
|
||||
const result = loadModuleFromFile(typesFile, extensions, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(typesFile), state.host), state);
|
||||
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
|
||||
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
|
||||
const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state) ||
|
||||
tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -747,6 +744,10 @@ namespace ts {
|
||||
return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state);
|
||||
}
|
||||
|
||||
function pathToPackageJson(directory: string): string {
|
||||
return combinePaths(directory, "package.json");
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
|
||||
const nodeModulesFolder = combinePaths(directory, "node_modules");
|
||||
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
|
||||
@@ -831,14 +832,6 @@ namespace ts {
|
||||
: { resolvedModule: undefined, failedLookupLocations };
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
};
|
||||
|
||||
interface OutputFingerprint {
|
||||
hash: string;
|
||||
byteOrderMark: boolean;
|
||||
@@ -846,7 +839,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
|
||||
const existingDirectories: Map<boolean> = {};
|
||||
const existingDirectories = createMap<boolean>();
|
||||
|
||||
function getCanonicalFileName(fileName: string): string {
|
||||
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
|
||||
@@ -860,9 +853,10 @@ namespace ts {
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeIORead");
|
||||
text = sys.readFile(fileName, options.charset);
|
||||
performance.measure("I/O Read", start);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@@ -877,7 +871,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function directoryExists(directoryPath: string): boolean {
|
||||
if (hasProperty(existingDirectories, directoryPath)) {
|
||||
if (directoryPath in existingDirectories) {
|
||||
return true;
|
||||
}
|
||||
if (sys.directoryExists(directoryPath)) {
|
||||
@@ -899,13 +893,13 @@ namespace ts {
|
||||
|
||||
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
|
||||
if (!outputFingerprints) {
|
||||
outputFingerprints = {};
|
||||
outputFingerprints = createMap<OutputFingerprint>();
|
||||
}
|
||||
|
||||
const hash = sys.createHash(data);
|
||||
const mtimeBefore = sys.getModifiedTime(fileName);
|
||||
|
||||
if (mtimeBefore && hasProperty(outputFingerprints, fileName)) {
|
||||
if (mtimeBefore && fileName in outputFingerprints) {
|
||||
const fingerprint = outputFingerprints[fileName];
|
||||
|
||||
// If output has not been changed, and the file has no external modification
|
||||
@@ -929,7 +923,7 @@ namespace ts {
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||
try {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
|
||||
@@ -939,7 +933,8 @@ namespace ts {
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
performance.measure("I/O Write", start);
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@@ -1040,16 +1035,11 @@ namespace ts {
|
||||
return [];
|
||||
}
|
||||
const resolutions: T[] = [];
|
||||
const cache: Map<T> = {};
|
||||
const cache = createMap<T>();
|
||||
for (const name of names) {
|
||||
let result: T;
|
||||
if (hasProperty(cache, name)) {
|
||||
result = cache[name];
|
||||
}
|
||||
else {
|
||||
result = loader(name, containingFile);
|
||||
cache[name] = result;
|
||||
}
|
||||
const result = name in cache
|
||||
? cache[name]
|
||||
: cache[name] = loader(name, containingFile);
|
||||
resolutions.push(result);
|
||||
}
|
||||
return resolutions;
|
||||
@@ -1070,15 +1060,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Walk the primary type lookup locations
|
||||
let result: string[] = [];
|
||||
const result: string[] = [];
|
||||
if (host.directoryExists && host.getDirectories) {
|
||||
const typeRoots = getEffectiveTypeRoots(options, host);
|
||||
if (typeRoots) {
|
||||
for (const root of typeRoots) {
|
||||
if (host.directoryExists(root)) {
|
||||
for (const typeDirectivePath of host.getDirectories(root)) {
|
||||
// Return just the type directive names
|
||||
result = result.concat(getBaseFileName(normalizePath(typeDirectivePath)));
|
||||
const normalized = normalizePath(typeDirectivePath);
|
||||
const packageJsonPath = pathToPackageJson(combinePaths(root, normalized));
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null;
|
||||
if (!isNotNeededPackage) {
|
||||
// Return just the type directive names
|
||||
result.push(getBaseFileName(normalized));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1095,7 +1091,7 @@ namespace ts {
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {};
|
||||
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
|
||||
@@ -1105,17 +1101,17 @@ namespace ts {
|
||||
// - This calls resolveModuleNames, and then calls findSourceFile for each resolved module.
|
||||
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
|
||||
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
|
||||
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 2;
|
||||
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0;
|
||||
let currentNodeModulesDepth = 0;
|
||||
|
||||
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
|
||||
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
|
||||
const modulesWithElidedImports: Map<boolean> = {};
|
||||
const modulesWithElidedImports = createMap<boolean>();
|
||||
|
||||
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
|
||||
const sourceFilesFoundSearchingNodeModules: Map<boolean> = {};
|
||||
const sourceFilesFoundSearchingNodeModules = createMap<boolean>();
|
||||
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
host = host || createCompilerHost(options);
|
||||
|
||||
@@ -1213,8 +1209,8 @@ namespace ts {
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
|
||||
performance.measure("Program", start);
|
||||
performance.mark("afterProgram");
|
||||
performance.measure("Program", "beforeProgram", "afterProgram");
|
||||
|
||||
return program;
|
||||
|
||||
@@ -1241,10 +1237,10 @@ namespace ts {
|
||||
if (!classifiableNames) {
|
||||
// Initialize a checker so that all our files are bound.
|
||||
getTypeChecker();
|
||||
classifiableNames = {};
|
||||
classifiableNames = createMap<string>();
|
||||
|
||||
for (const sourceFile of files) {
|
||||
copyMap(sourceFile.classifiableNames, classifiableNames);
|
||||
copyProperties(sourceFile.classifiableNames, classifiableNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1272,7 +1268,7 @@ namespace ts {
|
||||
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
|
||||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
|
||||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
|
||||
!mapIsEqualTo(oldOptions.paths, options.paths)) {
|
||||
!equalOwnProperties(oldOptions.paths, options.paths)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1394,7 +1390,7 @@ namespace ts {
|
||||
getSourceFile: program.getSourceFile,
|
||||
getSourceFileByPath: program.getSourceFileByPath,
|
||||
getSourceFiles: program.getSourceFiles,
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path),
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
|
||||
writeFile: writeFileCallback || (
|
||||
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
|
||||
isEmitBlocked,
|
||||
@@ -1457,14 +1453,15 @@ namespace ts {
|
||||
// checked is to not pass the file to getEmitResolver.
|
||||
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
|
||||
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeEmit");
|
||||
|
||||
const emitResult = emitFiles(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
|
||||
performance.measure("Emit", start);
|
||||
performance.mark("afterEmit");
|
||||
performance.measure("Emit", "beforeEmit", "afterEmit");
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
@@ -1931,7 +1928,7 @@ namespace ts {
|
||||
|
||||
// If the file was previously found via a node_modules search, but is now being processed as a root file,
|
||||
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
|
||||
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
|
||||
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
|
||||
sourceFilesFoundSearchingNodeModules[file.path] = false;
|
||||
if (!options.noResolve) {
|
||||
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
|
||||
@@ -1942,7 +1939,7 @@ namespace ts {
|
||||
processImportedModules(file, getDirectoryPath(fileName));
|
||||
}
|
||||
// See if we need to reprocess the imports due to prior skipped imports
|
||||
else if (file && lookUp(modulesWithElidedImports, file.path)) {
|
||||
else if (file && modulesWithElidedImports[file.path]) {
|
||||
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
|
||||
modulesWithElidedImports[file.path] = false;
|
||||
processImportedModules(file, getDirectoryPath(fileName));
|
||||
@@ -2009,15 +2006,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function processTypeReferenceDirectives(file: SourceFile) {
|
||||
const typeDirectives = map(file.typeReferenceDirectives, l => l.fileName);
|
||||
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
|
||||
const typeDirectives = map(file.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase());
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
|
||||
|
||||
for (let i = 0; i < typeDirectives.length; i++) {
|
||||
const ref = file.typeReferenceDirectives[i];
|
||||
const resolvedTypeReferenceDirective = resolutions[i];
|
||||
// store resolved type directive on the file
|
||||
setResolvedTypeReferenceDirective(file, ref.fileName, resolvedTypeReferenceDirective);
|
||||
processTypeReferenceDirective(ref.fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
|
||||
const fileName = ref.fileName.toLocaleLowerCase();
|
||||
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective);
|
||||
processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2042,7 +2041,7 @@ namespace ts {
|
||||
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
|
||||
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
|
||||
Diagnostics.Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_the_typings_folder_to_resolve_this_conflict,
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
@@ -2082,7 +2081,7 @@ namespace ts {
|
||||
function processImportedModules(file: SourceFile, basePath: string) {
|
||||
collectExternalModuleReferences(file);
|
||||
if (file.imports.length || file.moduleAugmentations.length) {
|
||||
file.resolvedModules = {};
|
||||
file.resolvedModules = createMap<ResolvedModule>();
|
||||
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
|
||||
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
|
||||
for (let i = 0; i < moduleNames.length; i++) {
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace ts {
|
||||
tryScan<T>(callback: () => T): T;
|
||||
}
|
||||
|
||||
const textToToken: Map<SyntaxKind> = {
|
||||
const textToToken = createMap({
|
||||
"abstract": SyntaxKind.AbstractKeyword,
|
||||
"any": SyntaxKind.AnyKeyword,
|
||||
"as": SyntaxKind.AsKeyword,
|
||||
@@ -179,7 +179,7 @@ namespace ts {
|
||||
"|=": SyntaxKind.BarEqualsToken,
|
||||
"^=": SyntaxKind.CaretEqualsToken,
|
||||
"@": SyntaxKind.AtToken,
|
||||
};
|
||||
});
|
||||
|
||||
/*
|
||||
As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
|
||||
@@ -274,9 +274,7 @@ namespace ts {
|
||||
function makeReverseMap(source: Map<number>): string[] {
|
||||
const result: string[] = [];
|
||||
for (const name in source) {
|
||||
if (source.hasOwnProperty(name)) {
|
||||
result[source[name]] = name;
|
||||
}
|
||||
result[source[name]] = name;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace ts {
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
let currentSourceFile: SourceFile;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
let stopOverridingSpan = false;
|
||||
@@ -240,7 +241,9 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = performance.mark();
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("beforeSourcemap");
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
@@ -282,7 +285,10 @@ namespace ts {
|
||||
|
||||
updateLastEncodedAndRecordedSpans();
|
||||
|
||||
performance.measure("Source Map", start);
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("afterSourcemap");
|
||||
performance.measure("Source Map", "beforeSourcemap", "afterSourcemap");
|
||||
}
|
||||
}
|
||||
|
||||
function getStartPos(range: TextRange) {
|
||||
|
||||
+12
-17
@@ -233,15 +233,15 @@ namespace ts {
|
||||
const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"];
|
||||
|
||||
function createWatchedFileSet() {
|
||||
const dirWatchers: Map<DirectoryWatcher> = {};
|
||||
const dirWatchers = createMap<DirectoryWatcher>();
|
||||
// One file can have multiple watchers
|
||||
const fileWatcherCallbacks: Map<FileWatcherCallback[]> = {};
|
||||
const fileWatcherCallbacks = createMap<FileWatcherCallback[]>();
|
||||
return { addFile, removeFile };
|
||||
|
||||
function reduceDirWatcherRefCountForFile(fileName: string) {
|
||||
const dirName = getDirectoryPath(fileName);
|
||||
if (hasProperty(dirWatchers, dirName)) {
|
||||
const watcher = dirWatchers[dirName];
|
||||
const watcher = dirWatchers[dirName];
|
||||
if (watcher) {
|
||||
watcher.referenceCount -= 1;
|
||||
if (watcher.referenceCount <= 0) {
|
||||
watcher.close();
|
||||
@@ -251,13 +251,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addDirWatcher(dirPath: string): void {
|
||||
if (hasProperty(dirWatchers, dirPath)) {
|
||||
const watcher = dirWatchers[dirPath];
|
||||
let watcher = dirWatchers[dirPath];
|
||||
if (watcher) {
|
||||
watcher.referenceCount += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const watcher: DirectoryWatcher = _fs.watch(
|
||||
watcher = _fs.watch(
|
||||
dirPath,
|
||||
{ persistent: true },
|
||||
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
|
||||
@@ -268,12 +267,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
|
||||
if (hasProperty(fileWatcherCallbacks, filePath)) {
|
||||
fileWatcherCallbacks[filePath].push(callback);
|
||||
}
|
||||
else {
|
||||
fileWatcherCallbacks[filePath] = [callback];
|
||||
}
|
||||
(fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback);
|
||||
}
|
||||
|
||||
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
|
||||
@@ -289,8 +283,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
|
||||
if (hasProperty(fileWatcherCallbacks, filePath)) {
|
||||
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks[filePath]);
|
||||
const callbacks = fileWatcherCallbacks[filePath];
|
||||
if (callbacks) {
|
||||
const newCallbacks = copyListRemovingItem(callback, callbacks);
|
||||
if (newCallbacks.length === 0) {
|
||||
delete fileWatcherCallbacks[filePath];
|
||||
}
|
||||
@@ -306,7 +301,7 @@ namespace ts {
|
||||
? undefined
|
||||
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
|
||||
// Some applications save a working file via rename operations
|
||||
if ((eventName === "change" || eventName === "rename") && hasProperty(fileWatcherCallbacks, fileName)) {
|
||||
if ((eventName === "change" || eventName === "rename") && fileWatcherCallbacks[fileName]) {
|
||||
for (const fileCallback of fileWatcherCallbacks[fileName]) {
|
||||
fileCallback(fileName);
|
||||
}
|
||||
|
||||
+11
-68
@@ -122,11 +122,11 @@ namespace ts {
|
||||
const gutterSeparator = " ";
|
||||
const resetEscapeSequence = "\u001b[0m";
|
||||
const ellipsis = "...";
|
||||
const categoryFormatMap: Map<string> = {
|
||||
const categoryFormatMap = createMap<string>({
|
||||
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
|
||||
};
|
||||
});
|
||||
|
||||
function formatAndReset(text: string, formatStyle: string) {
|
||||
return formatStyle + text + resetEscapeSequence;
|
||||
@@ -432,7 +432,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// reset the cache of existing files
|
||||
cachedExistingFiles = {};
|
||||
cachedExistingFiles = createMap<boolean>();
|
||||
|
||||
const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
|
||||
|
||||
@@ -445,10 +445,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function cachedFileExists(fileName: string): boolean {
|
||||
if (hasProperty(cachedExistingFiles, fileName)) {
|
||||
return cachedExistingFiles[fileName];
|
||||
}
|
||||
return cachedExistingFiles[fileName] = hostFileExists(fileName);
|
||||
return fileName in cachedExistingFiles
|
||||
? cachedExistingFiles[fileName]
|
||||
: cachedExistingFiles[fileName] = hostFileExists(fileName);
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
|
||||
@@ -676,7 +675,7 @@ namespace ts {
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap: Map<string[]> = {}; // Map between option.description and list of option.type if it is a kind
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (let i = 0; i < optsList.length; i++) {
|
||||
const option = optsList[i];
|
||||
@@ -704,9 +703,10 @@ namespace ts {
|
||||
description = getDiagnosticText(option.description);
|
||||
const options: string[] = [];
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
forEachKey(<Map<number | string>>element.type, key => {
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
for (const key in typeMap) {
|
||||
options.push(`'${key}'`);
|
||||
});
|
||||
}
|
||||
optionsDescriptionMap[description] = options;
|
||||
}
|
||||
else {
|
||||
@@ -763,68 +763,11 @@ namespace ts {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
|
||||
}
|
||||
else {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: any = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions)
|
||||
};
|
||||
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
else {
|
||||
configurations.exclude = ["node_modules"];
|
||||
if (compilerOptions.outDir) {
|
||||
configurations.exclude.push(compilerOptions.outDir);
|
||||
}
|
||||
}
|
||||
|
||||
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
|
||||
sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
|
||||
const result: Map<string | number | boolean> = {};
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
if (hasProperty(options, name)) {
|
||||
// tsconfig only options cannot be specified via command line,
|
||||
// so we can assume that only types that can appear here string | number | boolean
|
||||
const value = <string | number | boolean>options[name];
|
||||
switch (name) {
|
||||
case "init":
|
||||
case "watch":
|
||||
case "version":
|
||||
case "help":
|
||||
case "project":
|
||||
break;
|
||||
default:
|
||||
let optionDefinition = optionsNameMap[name.toLowerCase()];
|
||||
if (optionDefinition) {
|
||||
if (typeof optionDefinition.type === "string") {
|
||||
// string, number or boolean
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
// Enum
|
||||
const typeMap = <Map<number>>optionDefinition.type;
|
||||
for (const key in typeMap) {
|
||||
if (hasProperty(typeMap, key)) {
|
||||
if (typeMap[key] === value)
|
||||
result[name] = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-29
@@ -1,9 +1,13 @@
|
||||
|
||||
namespace ts {
|
||||
export interface Map<T> {
|
||||
|
||||
export interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
export interface Map<T> extends MapLike<T> {
|
||||
__mapBrand: any;
|
||||
}
|
||||
|
||||
// branded string type used to store absolute, normalized and canonicalized paths
|
||||
// arbitrary file name can be converted to Path via toPath function
|
||||
export type Path = string & { __pathBrand: any };
|
||||
@@ -346,6 +350,10 @@ namespace ts {
|
||||
JSDocTypedefTag,
|
||||
JSDocPropertyTag,
|
||||
JSDocTypeLiteral,
|
||||
JSDocLiteralType,
|
||||
JSDocNullKeyword,
|
||||
JSDocUndefinedKeyword,
|
||||
JSDocNeverKeyword,
|
||||
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
@@ -376,9 +384,9 @@ namespace ts {
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocTypeLiteral,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
FirstJSDocTagNode = JSDocComment,
|
||||
LastJSDocTagNode = JSDocTypeLiteral
|
||||
LastJSDocTagNode = JSDocNeverKeyword
|
||||
}
|
||||
|
||||
export const enum NodeFlags {
|
||||
@@ -982,13 +990,19 @@ namespace ts {
|
||||
multiLine?: boolean;
|
||||
}
|
||||
|
||||
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
|
||||
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
|
||||
|
||||
// @kind(SyntaxKind.PropertyAccessExpression)
|
||||
export interface PropertyAccessExpression extends MemberExpression, Declaration {
|
||||
expression: LeftHandSideExpression;
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression;
|
||||
/** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */
|
||||
export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression {
|
||||
_propertyAccessExpressionLikeQualifiedNameBrand?: any;
|
||||
expression: EntityNameExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.ElementAccessExpression)
|
||||
export interface ElementAccessExpression extends MemberExpression {
|
||||
@@ -1492,6 +1506,10 @@ namespace ts {
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocLiteralType extends JSDocType {
|
||||
literal: LiteralTypeNode;
|
||||
}
|
||||
|
||||
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
|
||||
|
||||
// @kind(SyntaxKind.JSDocRecordMember)
|
||||
@@ -2031,7 +2049,7 @@ namespace ts {
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult;
|
||||
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
getReferencedValueDeclaration(reference: Identifier): Declaration;
|
||||
@@ -2040,7 +2058,7 @@ namespace ts {
|
||||
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
|
||||
isArgumentsLocalBinding(node: Identifier): boolean;
|
||||
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile;
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityName | PropertyAccessExpression): string[];
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
|
||||
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
|
||||
}
|
||||
|
||||
@@ -2147,6 +2165,8 @@ namespace ts {
|
||||
/* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
|
||||
/* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
|
||||
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
|
||||
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
|
||||
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2160,6 +2180,8 @@ namespace ts {
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
|
||||
hasCommonType?: boolean; // True if constituents of synthetic property all have same type
|
||||
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
|
||||
@@ -2170,9 +2192,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
|
||||
export interface SymbolTable {
|
||||
[index: string]: Symbol;
|
||||
}
|
||||
export type SymbolTable = Map<Symbol>;
|
||||
|
||||
/** Represents a "prefix*suffix" pattern. */
|
||||
/* @internal */
|
||||
@@ -2199,23 +2219,24 @@ namespace ts {
|
||||
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
|
||||
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
|
||||
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
|
||||
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
|
||||
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
|
||||
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
|
||||
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
|
||||
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
|
||||
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
|
||||
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
|
||||
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
|
||||
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
|
||||
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
|
||||
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
|
||||
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
|
||||
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
|
||||
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
|
||||
AssignmentsMarked = 0x00400000, // Parameter assignments have been marked
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NodeLinks {
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
resolvedType?: Type; // Cached type of type node
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
enumMemberValue?: number; // Constant value of enum member
|
||||
isVisible?: boolean; // Is this node visible
|
||||
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
|
||||
@@ -2245,7 +2266,7 @@ namespace ts {
|
||||
Class = 1 << 15, // Class
|
||||
Interface = 1 << 16, // Interface
|
||||
Reference = 1 << 17, // Generic type reference
|
||||
Tuple = 1 << 18, // Tuple
|
||||
Tuple = 1 << 18, // Synthesized generic tuple type
|
||||
Union = 1 << 19, // Union (T | U)
|
||||
Intersection = 1 << 20, // Intersection (T & U)
|
||||
Anonymous = 1 << 21, // Anonymous
|
||||
@@ -2367,10 +2388,6 @@ namespace ts {
|
||||
instantiations: Map<TypeReference>; // Generic instantiation cache
|
||||
}
|
||||
|
||||
export interface TupleType extends ObjectType {
|
||||
elementTypes: Type[]; // Element types
|
||||
}
|
||||
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
@@ -2555,7 +2572,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export type RootPaths = string[];
|
||||
export type PathSubstitutions = Map<string[]>;
|
||||
export type PathSubstitutions = MapLike<string[]>;
|
||||
export type TsConfigOnlyOptions = RootPaths | PathSubstitutions;
|
||||
|
||||
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions;
|
||||
@@ -2715,7 +2732,7 @@ namespace ts {
|
||||
fileNames: string[];
|
||||
raw?: any;
|
||||
errors: Diagnostic[];
|
||||
wildcardDirectories?: Map<WatchDirectoryFlags>;
|
||||
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
|
||||
}
|
||||
|
||||
export const enum WatchDirectoryFlags {
|
||||
@@ -2725,7 +2742,7 @@ namespace ts {
|
||||
|
||||
export interface ExpandResult {
|
||||
fileNames: string[];
|
||||
wildcardDirectories: Map<WatchDirectoryFlags>;
|
||||
wildcardDirectories: MapLike<WatchDirectoryFlags>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2747,7 +2764,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
|
||||
type: Map<number | string>; // an object literal mapping named values to actual values
|
||||
type: Map<number | string>; // an object literal mapping named values to actual values
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
+37
-61
@@ -87,25 +87,6 @@ namespace ts {
|
||||
return node.end - node.pos;
|
||||
}
|
||||
|
||||
export function mapIsEqualTo<T>(map1: Map<T>, map2: Map<T>): boolean {
|
||||
if (!map1 || !map2) {
|
||||
return map1 === map2;
|
||||
}
|
||||
return containsAll(map1, map2) && containsAll(map2, map1);
|
||||
}
|
||||
|
||||
function containsAll<T>(map: Map<T>, other: Map<T>): boolean {
|
||||
for (const key in map) {
|
||||
if (!hasProperty(map, key)) {
|
||||
continue;
|
||||
}
|
||||
if (!hasProperty(other, key) || map[key] !== other[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
|
||||
if (!array1 || !array2) {
|
||||
return array1 === array2;
|
||||
@@ -126,7 +107,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
|
||||
return sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleNameText);
|
||||
return !!(sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]);
|
||||
}
|
||||
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
|
||||
@@ -135,7 +116,7 @@ namespace ts {
|
||||
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
|
||||
if (!sourceFile.resolvedModules) {
|
||||
sourceFile.resolvedModules = {};
|
||||
sourceFile.resolvedModules = createMap<ResolvedModule>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedModules[moduleNameText] = resolvedModule;
|
||||
@@ -143,7 +124,7 @@ namespace ts {
|
||||
|
||||
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
|
||||
if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames = {};
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective;
|
||||
@@ -166,7 +147,7 @@ namespace ts {
|
||||
}
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const newResolution = newResolutions[i];
|
||||
const oldResolution = oldResolutions && hasProperty(oldResolutions, names[i]) ? oldResolutions[names[i]] : undefined;
|
||||
const oldResolution = oldResolutions && oldResolutions[names[i]];
|
||||
const changed =
|
||||
oldResolution
|
||||
? !newResolution || !comparer(oldResolution, newResolution)
|
||||
@@ -320,6 +301,10 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
|
||||
}
|
||||
|
||||
export function isJSDocTag(node: Node) {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
@@ -1033,14 +1018,14 @@ namespace ts {
|
||||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return (<ExpressionWithTypeArguments>node).expression;
|
||||
Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
|
||||
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.QualifiedName:
|
||||
return (<EntityName><Node>node);
|
||||
@@ -1694,8 +1679,8 @@ namespace ts {
|
||||
// import * as <symbol> from ...
|
||||
// import { x as <symbol> } from ...
|
||||
// export { x as <symbol> } from ...
|
||||
// export = ...
|
||||
// export default ...
|
||||
// export = <EntityNameExpression>
|
||||
// export default <EntityNameExpression>
|
||||
export function isAliasSymbolDeclaration(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
|
||||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
|
||||
@@ -1703,7 +1688,11 @@ namespace ts {
|
||||
node.kind === SyntaxKind.NamespaceImport ||
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier;
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node);
|
||||
}
|
||||
|
||||
export function exportAssignmentIsAlias(node: ExportAssignment): boolean {
|
||||
return isEntityNameExpression(node.expression);
|
||||
}
|
||||
|
||||
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
@@ -1966,7 +1955,7 @@ namespace ts {
|
||||
|
||||
export function createDiagnosticCollection(): DiagnosticCollection {
|
||||
let nonFileDiagnostics: Diagnostic[] = [];
|
||||
const fileDiagnostics: Map<Diagnostic[]> = {};
|
||||
const fileDiagnostics = createMap<Diagnostic[]>();
|
||||
|
||||
let diagnosticsModified = false;
|
||||
let modificationCount = 0;
|
||||
@@ -1984,12 +1973,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reattachFileDiagnostics(newFile: SourceFile): void {
|
||||
if (!hasProperty(fileDiagnostics, newFile.fileName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const diagnostic of fileDiagnostics[newFile.fileName]) {
|
||||
diagnostic.file = newFile;
|
||||
const diagnostics = fileDiagnostics[newFile.fileName];
|
||||
if (diagnostics) {
|
||||
for (const diagnostic of diagnostics) {
|
||||
diagnostic.file = newFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2030,9 +2018,7 @@ namespace ts {
|
||||
forEach(nonFileDiagnostics, pushDiagnostic);
|
||||
|
||||
for (const key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
forEach(fileDiagnostics[key], pushDiagnostic);
|
||||
}
|
||||
forEach(fileDiagnostics[key], pushDiagnostic);
|
||||
}
|
||||
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
@@ -2047,9 +2033,7 @@ namespace ts {
|
||||
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
|
||||
|
||||
for (const key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
|
||||
}
|
||||
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2060,7 +2044,7 @@ namespace ts {
|
||||
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
|
||||
// There is no reason for this other than that JSON.stringify does not handle it either.
|
||||
const escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const escapedCharsMap: Map<string> = {
|
||||
const escapedCharsMap = createMap({
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
@@ -2073,7 +2057,7 @@ namespace ts {
|
||||
"\u2028": "\\u2028", // lineSeparator
|
||||
"\u2029": "\\u2029", // paragraphSeparator
|
||||
"\u0085": "\\u0085" // nextLine
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
@@ -2681,22 +2665,9 @@ namespace ts {
|
||||
isClassLike(node.parent.parent);
|
||||
}
|
||||
|
||||
// Returns false if this heritage clause element's expression contains something unsupported
|
||||
// (i.e. not a name or dotted name).
|
||||
export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean {
|
||||
return isSupportedExpressionWithTypeArgumentsRest(node.expression);
|
||||
}
|
||||
|
||||
function isSupportedExpressionWithTypeArgumentsRest(node: Expression): boolean {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
return true;
|
||||
}
|
||||
else if (isPropertyAccessExpression(node)) {
|
||||
return isSupportedExpressionWithTypeArgumentsRest(node.expression);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
|
||||
return node.kind === SyntaxKind.Identifier ||
|
||||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
|
||||
}
|
||||
|
||||
export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
@@ -2727,6 +2698,11 @@ namespace ts {
|
||||
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */
|
||||
export function tryExtractTypeScriptExtension(fileName: string): string | undefined {
|
||||
return find(supportedTypescriptExtensionsForExtractExtension, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace each instance of non-ascii characters by one, two, three, or four escape sequences
|
||||
* representing the UTF-8 encoding of the character, and return the expanded char code list.
|
||||
@@ -2806,7 +2782,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function stringifyObject(value: any) {
|
||||
return `{${reduceProperties(value, stringifyProperty, "")}}`;
|
||||
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
|
||||
}
|
||||
|
||||
function stringifyProperty(memo: string, value: any, key: string) {
|
||||
|
||||
+10
-218
@@ -1,8 +1,6 @@
|
||||
/// <reference path="harness.ts" />
|
||||
/// <reference path="runnerbase.ts" />
|
||||
/// <reference path="typeWriter.ts" />
|
||||
// In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
|
||||
const enum CompilerTestType {
|
||||
Conformance,
|
||||
@@ -52,7 +50,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
private makeUnitName(name: string, root: string) {
|
||||
const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
return path.replace(pathStart, "/");
|
||||
return pathStart ? path.replace(pathStart, "/") : path;
|
||||
};
|
||||
|
||||
public checkTestCodeOutput(fileName: string) {
|
||||
@@ -136,27 +134,16 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
otherFiles = undefined;
|
||||
});
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
|
||||
}
|
||||
|
||||
function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) {
|
||||
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
|
||||
}
|
||||
|
||||
// check errors
|
||||
it("Correct errors for " + fileName, () => {
|
||||
if (this.errors) {
|
||||
Harness.Baseline.runBaseline("Correct errors for " + fileName, justName.replace(/\.tsx?$/, ".errors.txt"), (): string => {
|
||||
if (result.errors.length === 0) return null;
|
||||
return getErrorBaseline(toBeCompiled, otherFiles, result);
|
||||
});
|
||||
Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors);
|
||||
}
|
||||
});
|
||||
|
||||
it (`Correct module resolution tracing for ${fileName}`, () => {
|
||||
if (options.traceResolution) {
|
||||
Harness.Baseline.runBaseline("Correct module resolution tracing for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
return JSON.stringify(result.traceResults || [], undefined, 4);
|
||||
});
|
||||
}
|
||||
@@ -165,11 +152,13 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
// Source maps?
|
||||
it("Correct sourcemap content for " + fileName, () => {
|
||||
if (options.sourceMap || options.inlineSourceMap) {
|
||||
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
|
||||
const record = result.getSourceMapRecord();
|
||||
if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) {
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required.
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
return record;
|
||||
});
|
||||
@@ -178,87 +167,12 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
it("Correct JS output for " + fileName, () => {
|
||||
if (hasNonDtsFiles && this.emit) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline("Correct JS output for " + fileName, justName.replace(/\.tsx?/, ".js"), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
tsCode += "//// [" + fileName + "] ////\r\n\r\n";
|
||||
}
|
||||
for (let i = 0; i < tsSources.length; i++) {
|
||||
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
|
||||
}
|
||||
|
||||
let jsCode = "";
|
||||
for (let i = 0; i < result.files.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.files[i]);
|
||||
jsCode += result.files[i].code;
|
||||
}
|
||||
|
||||
if (result.declFilesCode.length > 0) {
|
||||
jsCode += "\r\n\r\n";
|
||||
for (let i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
|
||||
jsCode += result.declFilesCode[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
jsCode += "\r\n\r\n";
|
||||
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
return tsCode + "\r\n\r\n" + jsCode;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, toBeCompiled, otherFiles, harnessSettings);
|
||||
}
|
||||
});
|
||||
|
||||
it("Correct Sourcemap output for " + fileName, () => {
|
||||
if (options.inlineSourceMap) {
|
||||
if (result.sourceMaps.length > 0) {
|
||||
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (options.sourceMap) {
|
||||
if (result.sourceMaps.length !== result.files.length) {
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline("Correct Sourcemap output for " + fileName, justName.replace(/\.tsx?/, ".js.map"), () => {
|
||||
if (options.noEmitOnError && result.errors.length !== 0 && result.sourceMaps.length === 0) {
|
||||
// We need to return null here or the runBaseLine will actually create a empty file.
|
||||
// Baselining isn't required here because there is no output.
|
||||
return null;
|
||||
}
|
||||
|
||||
let sourceMapCode = "";
|
||||
for (let i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
|
||||
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
|
||||
sourceMapCode += result.sourceMaps[i].code;
|
||||
}
|
||||
|
||||
return sourceMapCode;
|
||||
});
|
||||
}
|
||||
Harness.Compiler.doSourcemapBaseline(justName, options, result);
|
||||
});
|
||||
|
||||
it("Correct type/symbol baselines for " + fileName, () => {
|
||||
@@ -266,129 +180,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
return;
|
||||
}
|
||||
|
||||
// NEWTODO: Type baselines
|
||||
if (result.errors.length !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type displayed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
const program = result.program;
|
||||
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
|
||||
|
||||
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
|
||||
|
||||
const fullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
const pullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
|
||||
for (const sourceFile of allFiles) {
|
||||
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
}
|
||||
|
||||
// Produce baselines. The first gives the types for all expressions.
|
||||
// The second gives symbols for all identifiers.
|
||||
let e1: Error, e2: Error;
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ false);
|
||||
}
|
||||
catch (e) {
|
||||
e1 = e;
|
||||
}
|
||||
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ true);
|
||||
}
|
||||
catch (e) {
|
||||
e2 = e;
|
||||
}
|
||||
|
||||
if (e1 || e2) {
|
||||
throw e1 || e2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function checkBaseLines(isSymbolBaseLine: boolean) {
|
||||
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
|
||||
|
||||
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
|
||||
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
|
||||
|
||||
if (fullBaseLine !== pullBaseLine) {
|
||||
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
Harness.Baseline.runBaseline("Correct pull information for " + fileName, justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
|
||||
}
|
||||
else {
|
||||
Harness.Baseline.runBaseline("Correct information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
}
|
||||
}
|
||||
|
||||
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
|
||||
const typeLines: string[] = [];
|
||||
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
|
||||
allFiles.forEach(file => {
|
||||
const codeLines = file.content.split("\n");
|
||||
typeWriterResults[file.unitName].forEach(result => {
|
||||
if (isSymbolBaseline && !result.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
if (!typeMap[file.unitName]) {
|
||||
typeMap[file.unitName] = {};
|
||||
}
|
||||
|
||||
let typeInfo = [formattedLine];
|
||||
const existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
if (existingTypeInfo) {
|
||||
typeInfo = existingTypeInfo.concat(typeInfo);
|
||||
}
|
||||
typeMap[file.unitName][result.line] = typeInfo;
|
||||
});
|
||||
|
||||
typeLines.push("=== " + file.unitName + " ===\r\n");
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
const currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + "\r\n");
|
||||
if (typeMap[file.unitName]) {
|
||||
const typeInfo = typeMap[file.unitName][i];
|
||||
if (typeInfo) {
|
||||
typeInfo.forEach(ty => {
|
||||
typeLines.push(">" + ty + "\r\n");
|
||||
});
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
|
||||
}
|
||||
else {
|
||||
typeLines.push("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeLines.push("No type information for this code.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeLines.join("");
|
||||
}
|
||||
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(justName, result, toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+52
-91
@@ -95,14 +95,14 @@ namespace FourSlash {
|
||||
|
||||
export import IndentStyle = ts.IndentStyle;
|
||||
|
||||
const entityMap: ts.Map<string> = {
|
||||
const entityMap = ts.createMap({
|
||||
"&": "&",
|
||||
"\"": """,
|
||||
"'": "'",
|
||||
"/": "/",
|
||||
"<": "<",
|
||||
">": ">"
|
||||
};
|
||||
});
|
||||
|
||||
export function escapeXmlAttributeValue(s: string) {
|
||||
return s.replace(/[&<>"'\/]/g, ch => entityMap[ch]);
|
||||
@@ -204,7 +204,7 @@ namespace FourSlash {
|
||||
|
||||
public formatCodeOptions: ts.FormatCodeOptions;
|
||||
|
||||
private inputFiles: ts.Map<string> = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
|
||||
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
|
||||
|
||||
// Add input file which has matched file name with the given reference-file path.
|
||||
// This is necessary when resolveReference flag is specified
|
||||
@@ -249,6 +249,7 @@ namespace FourSlash {
|
||||
if (compilationOptions.typeRoots) {
|
||||
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
|
||||
}
|
||||
compilationOptions.skipDefaultLibCheck = true;
|
||||
|
||||
const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions);
|
||||
this.languageServiceAdapterHost = languageServiceAdapter.getHost();
|
||||
@@ -300,11 +301,11 @@ namespace FourSlash {
|
||||
}
|
||||
else {
|
||||
// resolveReference file-option is not specified then do not resolve any files and include all inputFiles
|
||||
ts.forEachKey(this.inputFiles, fileName => {
|
||||
for (const fileName in this.inputFiles) {
|
||||
if (!Harness.isDefaultLibraryFile(fileName)) {
|
||||
this.languageServiceAdapterHost.addScript(fileName, this.inputFiles[fileName], /*isRootFile*/ true);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName,
|
||||
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
|
||||
}
|
||||
@@ -376,7 +377,7 @@ namespace FourSlash {
|
||||
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
|
||||
const startMarker = this.getMarkerByName(startMarkerName);
|
||||
const endMarker = this.getMarkerByName(endMarkerName);
|
||||
const predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
const predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false;
|
||||
};
|
||||
|
||||
@@ -428,12 +429,12 @@ namespace FourSlash {
|
||||
let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean;
|
||||
|
||||
if (after) {
|
||||
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false;
|
||||
};
|
||||
}
|
||||
else {
|
||||
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false;
|
||||
};
|
||||
}
|
||||
@@ -458,7 +459,7 @@ namespace FourSlash {
|
||||
endPos = endMarker.position;
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
errors.forEach(function(error: ts.Diagnostic) {
|
||||
if (predicate(error.start, error.start + error.length, startPos, endPos)) {
|
||||
exists = true;
|
||||
}
|
||||
@@ -475,7 +476,7 @@ namespace FourSlash {
|
||||
Harness.IO.log("Unexpected error(s) found. Error list is:");
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
errors.forEach(function(error: ts.Diagnostic) {
|
||||
Harness.IO.log(" minChar: " + error.start +
|
||||
", limChar: " + (error.start + error.length) +
|
||||
", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n");
|
||||
@@ -593,9 +594,9 @@ namespace FourSlash {
|
||||
|
||||
public noItemsWithSameNameButDifferentKind(): void {
|
||||
const completions = this.getCompletionListAtCaret();
|
||||
const uniqueItems: ts.Map<string> = {};
|
||||
const uniqueItems = ts.createMap<string>();
|
||||
for (const item of completions.entries) {
|
||||
if (!ts.hasProperty(uniqueItems, item.name)) {
|
||||
if (!(item.name in uniqueItems)) {
|
||||
uniqueItems[item.name] = item.kind;
|
||||
}
|
||||
else {
|
||||
@@ -772,7 +773,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public verifyRangesWithSameTextReferenceEachOther() {
|
||||
ts.forEachValue(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
|
||||
ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
|
||||
}
|
||||
|
||||
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
|
||||
@@ -1130,12 +1131,10 @@ namespace FourSlash {
|
||||
|
||||
}
|
||||
Harness.Baseline.runBaseline(
|
||||
"Breakpoint Locations for " + this.activeFile.fileName,
|
||||
baselineFile,
|
||||
() => {
|
||||
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos));
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput() {
|
||||
@@ -1157,7 +1156,6 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(
|
||||
"Generate getEmitOutput baseline : " + emitFiles.join(" "),
|
||||
this.testData.globalOptions[metadataOptionNames.baselineFile],
|
||||
() => {
|
||||
let resultString = "";
|
||||
@@ -1183,8 +1181,7 @@ namespace FourSlash {
|
||||
});
|
||||
|
||||
return resultString;
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public printBreakpointLocation(pos: number) {
|
||||
@@ -1347,14 +1344,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
// Enters lines of text at the current caret position
|
||||
public type(text: string) {
|
||||
return this.typeHighFidelity(text);
|
||||
}
|
||||
|
||||
// Enters lines of text at the current caret position, invoking
|
||||
// language service APIs to mimic Visual Studio's behavior
|
||||
// as much as possible
|
||||
private typeHighFidelity(text: string) {
|
||||
public type(text: string, highFidelity = false) {
|
||||
let offset = this.currentCaretPosition;
|
||||
const prevChar = " ";
|
||||
const checkCadence = (text.length >> 2) + 1;
|
||||
@@ -1363,24 +1353,26 @@ namespace FourSlash {
|
||||
// Make the edit
|
||||
const ch = text.charAt(i);
|
||||
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, ch);
|
||||
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||
if (highFidelity) {
|
||||
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
||||
offset++;
|
||||
|
||||
if (ch === "(" || ch === ",") {
|
||||
/* Signature help*/
|
||||
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
if (highFidelity) {
|
||||
if (ch === "(" || ch === ",") {
|
||||
/* Signature help*/
|
||||
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
|
||||
if (i % checkCadence === 0) {
|
||||
this.checkPostEditInvariants();
|
||||
// this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
|
||||
// this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
|
||||
if (i % checkCadence === 0) {
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle post-keystroke formatting
|
||||
@@ -1388,14 +1380,12 @@ namespace FourSlash {
|
||||
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
|
||||
if (edits.length) {
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
|
||||
// this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move the caret to wherever we ended up
|
||||
this.currentCaretPosition = offset;
|
||||
|
||||
this.fixCaretPosition();
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
@@ -1414,7 +1404,6 @@ namespace FourSlash {
|
||||
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
|
||||
if (edits.length) {
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1642,10 +1631,11 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public rangesByText(): ts.Map<Range[]> {
|
||||
const result: ts.Map<Range[]> = {};
|
||||
const result = ts.createMap<Range[]>();
|
||||
for (const range of this.getRanges()) {
|
||||
const text = this.rangeText(range);
|
||||
(ts.getProperty(result, text) || (result[text] = [])).push(range);
|
||||
const ranges = result[text] || (result[text] = []);
|
||||
ranges.push(range);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1739,13 +1729,11 @@ namespace FourSlash {
|
||||
|
||||
public baselineCurrentFileNameOrDottedNameSpans() {
|
||||
Harness.Baseline.runBaseline(
|
||||
"Name OrDottedNameSpans for " + this.activeFile.fileName,
|
||||
this.testData.globalOptions[metadataOptionNames.baselineFile],
|
||||
() => {
|
||||
return this.baselineCurrentFileLocations(pos =>
|
||||
this.getNameOrDottedNameSpan(pos));
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public printNameOrDottedNameSpans(pos: number) {
|
||||
@@ -1938,7 +1926,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
|
||||
|
||||
const openBraceMap: ts.Map<ts.CharacterCodes> = {
|
||||
const openBraceMap = ts.createMap<ts.CharacterCodes>({
|
||||
"(": ts.CharacterCodes.openParen,
|
||||
"{": ts.CharacterCodes.openBrace,
|
||||
"[": ts.CharacterCodes.openBracket,
|
||||
@@ -1946,7 +1934,7 @@ namespace FourSlash {
|
||||
'"': ts.CharacterCodes.doubleQuote,
|
||||
"`": ts.CharacterCodes.backtick,
|
||||
"<": ts.CharacterCodes.lessThan
|
||||
};
|
||||
});
|
||||
|
||||
const charCode = openBraceMap[openingBrace];
|
||||
|
||||
@@ -2310,40 +2298,12 @@ namespace FourSlash {
|
||||
export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
|
||||
// Parse out the files and their metadata
|
||||
const testData = parseTestData(basePath, content, fileName);
|
||||
|
||||
const state = new TestState(basePath, testType, testData);
|
||||
|
||||
let result = "";
|
||||
const fourslashFile: Harness.Compiler.TestFile = {
|
||||
unitName: Harness.Compiler.fourslashFileName,
|
||||
content: undefined,
|
||||
};
|
||||
const testFile: Harness.Compiler.TestFile = {
|
||||
unitName: fileName,
|
||||
content: content
|
||||
};
|
||||
|
||||
const host = Harness.Compiler.createCompilerHost(
|
||||
[fourslashFile, testFile],
|
||||
(fn, contents) => result = contents,
|
||||
ts.ScriptTarget.Latest,
|
||||
Harness.IO.useCaseSensitiveFileNames(),
|
||||
Harness.IO.getCurrentDirectory());
|
||||
|
||||
const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
|
||||
|
||||
const sourceFile = host.getSourceFile(fileName, ts.ScriptTarget.ES3);
|
||||
|
||||
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
|
||||
if (diagnostics.length > 0) {
|
||||
throw new Error(`Error compiling ${fileName}: ` +
|
||||
diagnostics.map(e => ts.flattenDiagnosticMessageText(e.messageText, Harness.IO.newLine())).join("\r\n"));
|
||||
const output = ts.transpileModule(content, { reportDiagnostics: true });
|
||||
if (output.diagnostics.length > 0) {
|
||||
throw new Error(`Syntax error in ${basePath}: ${output.diagnostics[0].messageText}`);
|
||||
}
|
||||
|
||||
program.emit(sourceFile);
|
||||
|
||||
ts.Debug.assert(!!result);
|
||||
runCode(result, state);
|
||||
runCode(output.outputText, state);
|
||||
}
|
||||
|
||||
function runCode(code: string, state: TestState): void {
|
||||
@@ -2436,13 +2396,14 @@ ${code}
|
||||
// Comment line, check for global/file @options and record them
|
||||
const match = optionRegex.exec(line.substr(2));
|
||||
if (match) {
|
||||
const fileMetadataNamesIndex = fileMetadataNames.indexOf(match[1]);
|
||||
const [key, value] = match.slice(1);
|
||||
const fileMetadataNamesIndex = fileMetadataNames.indexOf(key);
|
||||
if (fileMetadataNamesIndex === -1) {
|
||||
// Check if the match is already existed in the global options
|
||||
if (globalOptions[match[1]] !== undefined) {
|
||||
throw new Error("Global Option : '" + match[1] + "' is already existed");
|
||||
if (globalOptions[key] !== undefined) {
|
||||
throw new Error(`Global option '${key}' already exists`);
|
||||
}
|
||||
globalOptions[match[1]] = match[2];
|
||||
globalOptions[key] = value;
|
||||
}
|
||||
else {
|
||||
if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) {
|
||||
@@ -2457,12 +2418,12 @@ ${code}
|
||||
resetLocalData();
|
||||
}
|
||||
|
||||
currentFileName = basePath + "/" + match[2];
|
||||
currentFileOptions[match[1]] = match[2];
|
||||
currentFileName = basePath + "/" + value;
|
||||
currentFileOptions[key] = value;
|
||||
}
|
||||
else {
|
||||
// Add other fileMetadata flag
|
||||
currentFileOptions[match[1]] = match[2];
|
||||
currentFileOptions[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2550,7 +2511,7 @@ ${code}
|
||||
}
|
||||
|
||||
const marker: Marker = {
|
||||
fileName: fileName,
|
||||
fileName,
|
||||
position: location.position,
|
||||
data: markerValue
|
||||
};
|
||||
@@ -2567,7 +2528,7 @@ ${code}
|
||||
|
||||
function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker {
|
||||
const marker: Marker = {
|
||||
fileName: fileName,
|
||||
fileName,
|
||||
position: location.position
|
||||
};
|
||||
|
||||
|
||||
+268
-70
@@ -750,7 +750,7 @@ namespace Harness {
|
||||
|
||||
export function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]) {
|
||||
const fs = new Utils.VirtualFileSystem(path, useCaseSensitiveFileNames());
|
||||
for (const file in listFiles(path)) {
|
||||
for (const file of listFiles(path)) {
|
||||
fs.addFile(file);
|
||||
}
|
||||
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), path => {
|
||||
@@ -848,9 +848,9 @@ namespace Harness {
|
||||
export const defaultLibFileName = "lib.d.ts";
|
||||
export const es2015DefaultLibFileName = "lib.es2015.d.ts";
|
||||
|
||||
const libFileNameSourceFileMap: ts.Map<ts.SourceFile> = {
|
||||
const libFileNameSourceFileMap= ts.createMap<ts.SourceFile>({
|
||||
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
|
||||
};
|
||||
});
|
||||
|
||||
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile {
|
||||
if (!isDefaultLibraryFile(fileName)) {
|
||||
@@ -1005,13 +1005,13 @@ namespace Harness {
|
||||
let optionsIndex: ts.Map<ts.CommandLineOption>;
|
||||
function getCommandLineOption(name: string): ts.CommandLineOption {
|
||||
if (!optionsIndex) {
|
||||
optionsIndex = {};
|
||||
optionsIndex = ts.createMap<ts.CommandLineOption>();
|
||||
const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations);
|
||||
for (const option of optionDeclarations) {
|
||||
optionsIndex[option.name.toLowerCase()] = option;
|
||||
}
|
||||
}
|
||||
return ts.lookUp(optionsIndex, name.toLowerCase());
|
||||
return optionsIndex[name.toLowerCase()];
|
||||
}
|
||||
|
||||
export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {
|
||||
@@ -1328,6 +1328,220 @@ namespace Harness {
|
||||
Harness.IO.newLine() + Harness.IO.newLine() + outputLines.join("\r\n");
|
||||
}
|
||||
|
||||
export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[]) {
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => {
|
||||
if (errors.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
return getErrorBaseline(inputFiles, errors);
|
||||
});
|
||||
}
|
||||
|
||||
export function doTypeAndSymbolBaseline(baselinePath: string, result: CompilerResult, allFiles: {unitName: string, content: string}[], opts?: Harness.Baseline.BaselineOptions) {
|
||||
if (result.errors.length !== 0) {
|
||||
return;
|
||||
}
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type displayed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
const program = result.program;
|
||||
|
||||
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
|
||||
|
||||
const fullResults = ts.createMap<TypeWriterResult[]>();
|
||||
|
||||
for (const sourceFile of allFiles) {
|
||||
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
}
|
||||
|
||||
// Produce baselines. The first gives the types for all expressions.
|
||||
// The second gives symbols for all identifiers.
|
||||
let e1: Error, e2: Error;
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ false);
|
||||
}
|
||||
catch (e) {
|
||||
e1 = e;
|
||||
}
|
||||
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ true);
|
||||
}
|
||||
catch (e) {
|
||||
e2 = e;
|
||||
}
|
||||
|
||||
if (e1 || e2) {
|
||||
throw e1 || e2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function checkBaseLines(isSymbolBaseLine: boolean) {
|
||||
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
|
||||
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
|
||||
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, fullExtension), () => fullBaseLine, opts);
|
||||
}
|
||||
|
||||
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
|
||||
const typeLines: string[] = [];
|
||||
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
|
||||
allFiles.forEach(file => {
|
||||
const codeLines = file.content.split("\n");
|
||||
typeWriterResults[file.unitName].forEach(result => {
|
||||
if (isSymbolBaseline && !result.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
if (!typeMap[file.unitName]) {
|
||||
typeMap[file.unitName] = {};
|
||||
}
|
||||
|
||||
let typeInfo = [formattedLine];
|
||||
const existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
if (existingTypeInfo) {
|
||||
typeInfo = existingTypeInfo.concat(typeInfo);
|
||||
}
|
||||
typeMap[file.unitName][result.line] = typeInfo;
|
||||
});
|
||||
|
||||
typeLines.push("=== " + file.unitName + " ===\r\n");
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
const currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + "\r\n");
|
||||
if (typeMap[file.unitName]) {
|
||||
const typeInfo = typeMap[file.unitName][i];
|
||||
if (typeInfo) {
|
||||
typeInfo.forEach(ty => {
|
||||
typeLines.push(">" + ty + "\r\n");
|
||||
});
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
|
||||
}
|
||||
else {
|
||||
typeLines.push("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeLines.push("No type information for this code.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeLines.join("");
|
||||
}
|
||||
}
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
|
||||
}
|
||||
|
||||
export function doSourcemapBaseline(baselinePath: string, options: ts.CompilerOptions, result: CompilerResult) {
|
||||
if (options.inlineSourceMap) {
|
||||
if (result.sourceMaps.length > 0) {
|
||||
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (options.sourceMap) {
|
||||
if (result.sourceMaps.length !== result.files.length) {
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js.map"), () => {
|
||||
if (options.noEmitOnError && result.errors.length !== 0 && result.sourceMaps.length === 0) {
|
||||
// We need to return null here or the runBaseLine will actually create a empty file.
|
||||
// Baselining isn't required here because there is no output.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
|
||||
let sourceMapCode = "";
|
||||
for (let i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
|
||||
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
|
||||
sourceMapCode += result.sourceMaps[i].code;
|
||||
}
|
||||
|
||||
return sourceMapCode;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js"), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
tsCode += "//// [" + header + "] ////\r\n\r\n";
|
||||
}
|
||||
for (let i = 0; i < tsSources.length; i++) {
|
||||
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
|
||||
}
|
||||
|
||||
let jsCode = "";
|
||||
for (let i = 0; i < result.files.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.files[i]);
|
||||
jsCode += result.files[i].code;
|
||||
}
|
||||
|
||||
if (result.declFilesCode.length > 0) {
|
||||
jsCode += "\r\n\r\n";
|
||||
for (let i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
|
||||
jsCode += result.declFilesCode[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
jsCode += "\r\n\r\n";
|
||||
jsCode += Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
return tsCode + "\r\n\r\n" + jsCode;
|
||||
}
|
||||
else {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string {
|
||||
// Collect, test, and sort the fileNames
|
||||
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
|
||||
@@ -1569,6 +1783,7 @@ namespace Harness {
|
||||
|
||||
/** Support class for baseline files */
|
||||
export namespace Baseline {
|
||||
const NoContent = "<no content>";
|
||||
|
||||
export interface BaselineOptions {
|
||||
Subfolder?: string;
|
||||
@@ -1603,7 +1818,42 @@ namespace Harness {
|
||||
}
|
||||
|
||||
const fileCache: { [idx: string]: boolean } = {};
|
||||
function generateActual(actualFileName: string, generateContent: () => string): string {
|
||||
function generateActual(generateContent: () => string): string {
|
||||
|
||||
const actual = generateContent();
|
||||
|
||||
if (actual === undefined) {
|
||||
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) {
|
||||
// actual is now either undefined (the generator had an error), null (no file requested),
|
||||
// or some real output of the function
|
||||
if (actual === undefined) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual === null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
actual = NoContent;
|
||||
}
|
||||
|
||||
let expected = "<no content>";
|
||||
if (IO.fileExists(refFileName)) {
|
||||
expected = IO.readFile(refFileName);
|
||||
}
|
||||
|
||||
return { expected, actual };
|
||||
}
|
||||
|
||||
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string) {
|
||||
// For now this is written using TypeScript, because sys is not available when running old test cases.
|
||||
// But we need to move to sys once we have
|
||||
// Creates the directory including its parent if not already present
|
||||
@@ -1629,77 +1879,25 @@ namespace Harness {
|
||||
IO.deleteFile(actualFileName);
|
||||
}
|
||||
|
||||
const actual = generateContent();
|
||||
|
||||
if (actual === undefined) {
|
||||
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
|
||||
}
|
||||
|
||||
// Store the content in the 'local' folder so we
|
||||
// can accept it later (manually)
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual !== null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
IO.writeFile(actualFileName, actual);
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) {
|
||||
// actual is now either undefined (the generator had an error), null (no file requested),
|
||||
// or some real output of the function
|
||||
if (actual === undefined) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual === null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
actual = "<no content>";
|
||||
}
|
||||
|
||||
let expected = "<no content>";
|
||||
if (IO.fileExists(refFileName)) {
|
||||
expected = IO.readFile(refFileName);
|
||||
}
|
||||
|
||||
return { expected, actual };
|
||||
}
|
||||
|
||||
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, descriptionForDescribe: string) {
|
||||
const encoded_actual = Utils.encodeString(actual);
|
||||
if (expected != encoded_actual) {
|
||||
// Overwrite & issue error
|
||||
const errMsg = "The baseline file " + relativeFileName + " has changed.";
|
||||
throw new Error(errMsg);
|
||||
if (expected !== encoded_actual) {
|
||||
if (actual === NoContent) {
|
||||
IO.writeFile(actualFileName + ".delete", "");
|
||||
}
|
||||
else {
|
||||
IO.writeFile(actualFileName, actual);
|
||||
}
|
||||
throw new Error(`The baseline file ${relativeFileName} has changed.`);
|
||||
}
|
||||
}
|
||||
|
||||
export function runBaseline(
|
||||
descriptionForDescribe: string,
|
||||
relativeFileName: string,
|
||||
generateContent: () => string,
|
||||
runImmediately = false,
|
||||
opts?: BaselineOptions): void {
|
||||
export function runBaseline(relativeFileName: string, generateContent: () => string, opts?: BaselineOptions): void {
|
||||
|
||||
let actual = <string>undefined;
|
||||
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
if (runImmediately) {
|
||||
actual = generateActual(actualFileName, generateContent);
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
|
||||
}
|
||||
else {
|
||||
actual = generateActual(actualFileName, generateContent);
|
||||
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
|
||||
}
|
||||
const actual = generateActual(generateContent);
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
export class LanguageServiceAdapterHost {
|
||||
protected fileNameToScript: ts.Map<ScriptInfo> = {};
|
||||
protected fileNameToScript = ts.createMap<ScriptInfo>();
|
||||
|
||||
constructor(protected cancellationToken = DefaultHostCancellationToken.Instance,
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
@@ -135,7 +135,7 @@ namespace Harness.LanguageService {
|
||||
|
||||
public getFilenames(): string[] {
|
||||
const fileNames: string[] = [];
|
||||
ts.forEachValue(this.fileNameToScript, (scriptInfo) => {
|
||||
ts.forEachProperty(this.fileNameToScript, (scriptInfo) => {
|
||||
if (scriptInfo.isRootFile) {
|
||||
// only include root files here
|
||||
// usually it means that we won't include lib.d.ts in the list of root files so it won't mess the computation of compilation root dir.
|
||||
@@ -146,7 +146,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getScriptInfo(fileName: string): ScriptInfo {
|
||||
return ts.lookUp(this.fileNameToScript, fileName);
|
||||
return this.fileNameToScript[fileName];
|
||||
}
|
||||
|
||||
public addScript(fileName: string, content: string, isRootFile: boolean): void {
|
||||
@@ -235,7 +235,7 @@ namespace Harness.LanguageService {
|
||||
this.getModuleResolutionsForFile = (fileName) => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
|
||||
const imports: ts.Map<string> = {};
|
||||
const imports = ts.createMap<string>();
|
||||
for (const module of preprocessInfo.importedFiles) {
|
||||
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
|
||||
if (resolutionInfo.resolvedModule) {
|
||||
@@ -248,7 +248,7 @@ namespace Harness.LanguageService {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
if (scriptInfo) {
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ false);
|
||||
const resolutions: ts.Map<ts.ResolvedTypeReferenceDirective> = {};
|
||||
const resolutions = ts.createMap<ts.ResolvedTypeReferenceDirective>();
|
||||
const settings = this.nativeHost.getCompilationSettings();
|
||||
for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) {
|
||||
const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost);
|
||||
|
||||
@@ -253,18 +253,15 @@ class ProjectRunner extends RunnerBase {
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
|
||||
};
|
||||
// Set the values specified using json
|
||||
const optionNameMap: ts.Map<ts.CommandLineOption> = {};
|
||||
ts.forEach(ts.optionDeclarations, option => {
|
||||
optionNameMap[option.name] = option;
|
||||
});
|
||||
const optionNameMap = ts.arrayToMap(ts.optionDeclarations, option => option.name);
|
||||
for (const name in testCase) {
|
||||
if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) {
|
||||
if (name !== "mapRoot" && name !== "sourceRoot" && name in optionNameMap) {
|
||||
const option = optionNameMap[name];
|
||||
const optType = option.type;
|
||||
let value = <any>testCase[name];
|
||||
if (typeof optType !== "string") {
|
||||
const key = value.toLowerCase();
|
||||
if (ts.hasProperty(optType, key)) {
|
||||
if (key in optType) {
|
||||
value = optType[key];
|
||||
}
|
||||
}
|
||||
@@ -462,7 +459,7 @@ class ProjectRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("Resolution information of (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline("Resolution information of (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".json", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".json", () => {
|
||||
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
|
||||
});
|
||||
});
|
||||
@@ -470,7 +467,7 @@ class ProjectRunner extends RunnerBase {
|
||||
|
||||
it("Errors for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".errors.txt", () => {
|
||||
return getErrorsBaseline(compilerResult);
|
||||
});
|
||||
}
|
||||
@@ -484,7 +481,7 @@ class ProjectRunner extends RunnerBase {
|
||||
// There may be multiple files with different baselines. Run all and report at the end, else
|
||||
// it stops copying the remaining emitted files from 'local/projectOutput' to 'local/project'.
|
||||
try {
|
||||
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
try {
|
||||
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
|
||||
}
|
||||
@@ -506,7 +503,7 @@ class ProjectRunner extends RunnerBase {
|
||||
|
||||
it("SourceMapRecord for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (compilerResult.sourceMapData) {
|
||||
Harness.Baseline.runBaseline("SourceMapRecord for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
|
||||
return Harness.SourceMapRecorder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
|
||||
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
|
||||
});
|
||||
@@ -519,7 +516,7 @@ class ProjectRunner extends RunnerBase {
|
||||
if (!compilerResult.errors.length && testCase.declaration) {
|
||||
const dTsCompileResult = compileCompileDTsFiles(compilerResult);
|
||||
if (dTsCompileResult && dTsCompileResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
|
||||
return getErrorsBaseline(dTsCompileResult);
|
||||
});
|
||||
}
|
||||
|
||||
+20
-14
@@ -158,55 +158,56 @@ namespace RWC {
|
||||
|
||||
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", baseName + ".output.js", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.output.js`, () => {
|
||||
return Harness.Compiler.collateOutputs(compilerResult.files);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
it("has the expected declaration file content", () => {
|
||||
Harness.Baseline.runBaseline("has the expected declaration file content", baseName + ".d.ts", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.d.ts`, () => {
|
||||
if (!compilerResult.declFilesCode.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.collateOutputs(compilerResult.declFilesCode);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
it("has the expected source maps", () => {
|
||||
Harness.Baseline.runBaseline("has the expected source maps", baseName + ".map", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.map`, () => {
|
||||
if (!compilerResult.sourceMaps.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.collateOutputs(compilerResult.sourceMaps);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
/*it("has correct source map record", () => {
|
||||
if (compilerOptions.sourceMap) {
|
||||
Harness.Baseline.runBaseline("has correct source map record", baseName + ".sourcemap.txt", () => {
|
||||
Harness.Baseline.runBaseline(baseName + ".sourcemap.txt", () => {
|
||||
return compilerResult.getSourceMapRecord();
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
}
|
||||
});*/
|
||||
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", baseName + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.errors.txt`, () => {
|
||||
if (compilerResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
// Do not include the library in the baselines to avoid noise
|
||||
const baselineFiles = inputFiles.concat(otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
|
||||
return Harness.Compiler.getErrorBaseline(baselineFiles, compilerResult.errors);
|
||||
}, false, baselineOpts);
|
||||
const errors = compilerResult.errors.filter(e => !Harness.isDefaultLibraryFile(e.file.fileName));
|
||||
return Harness.Compiler.getErrorBaseline(baselineFiles, errors);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
// Ideally, a generated declaration file will have no errors. But we allow generated
|
||||
// declaration file errors as part of the baseline.
|
||||
it("has the expected errors in generated declaration files", () => {
|
||||
if (compilerOptions.declaration && !compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.dts.errors.txt`, () => {
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
|
||||
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
|
||||
|
||||
@@ -217,11 +218,16 @@ namespace RWC {
|
||||
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
|
||||
Harness.IO.newLine() + Harness.IO.newLine() +
|
||||
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Type baselines (need to refactor out from compilerRunner)
|
||||
it("has the expected types", () => {
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(`${baseName}.types`, compilerResult, inputFiles
|
||||
.concat(otherFiles)
|
||||
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
|
||||
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,21 +67,21 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", testState.filename + ".output.js", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".output.js", () => {
|
||||
const files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath);
|
||||
return Harness.Compiler.collateOutputs(files);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", testState.filename + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".errors.txt", () => {
|
||||
const errors = testState.compilerResult.errors;
|
||||
if (errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(testState.inputFiles, errors);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it("satisfies invariants", () => {
|
||||
@@ -90,10 +90,10 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("has the expected AST", () => {
|
||||
Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".AST.txt", () => {
|
||||
const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
return Utils.sourceFileToJSON(sourceFile);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
"./unittests/convertCompilerOptionsFromJson.ts",
|
||||
"./unittests/convertTypingOptionsFromJson.ts",
|
||||
"./unittests/tsserverProjectSystem.ts",
|
||||
"./unittests/matchFiles.ts"
|
||||
"./unittests/matchFiles.ts",
|
||||
"./unittests/initializeTSConfig.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
|
||||
const existingDirectories: Map<boolean> = {};
|
||||
forEachValue(fileMap, v => {
|
||||
let dir = getDirectoryPath(v.name);
|
||||
const existingDirectories = createMap<boolean>();
|
||||
for (const name in fileMap) {
|
||||
let dir = getDirectoryPath(name);
|
||||
let previous: string;
|
||||
do {
|
||||
existingDirectories[dir] = true;
|
||||
previous = dir;
|
||||
dir = getDirectoryPath(dir);
|
||||
} while (dir !== previous);
|
||||
});
|
||||
}
|
||||
return {
|
||||
args: <string[]>[],
|
||||
newLine: "\r\n",
|
||||
@@ -24,7 +24,7 @@ namespace ts {
|
||||
write: (s: string) => {
|
||||
},
|
||||
readFile: (path: string, encoding?: string): string => {
|
||||
return hasProperty(fileMap, path) && fileMap[path].content;
|
||||
return path in fileMap ? fileMap[path].content : undefined;
|
||||
},
|
||||
writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => {
|
||||
throw new Error("NYI");
|
||||
@@ -33,10 +33,10 @@ namespace ts {
|
||||
throw new Error("NYI");
|
||||
},
|
||||
fileExists: (path: string): boolean => {
|
||||
return hasProperty(fileMap, path);
|
||||
return path in fileMap;
|
||||
},
|
||||
directoryExists: (path: string): boolean => {
|
||||
return hasProperty(existingDirectories, path);
|
||||
return existingDirectories[path] || false;
|
||||
},
|
||||
createDirectory: (path: string) => {
|
||||
},
|
||||
@@ -101,7 +101,7 @@ namespace ts {
|
||||
content: `foo()`
|
||||
};
|
||||
|
||||
const serverHost = createDefaultServerHost({ [root.name]: root, [imported.name]: imported });
|
||||
const serverHost = createDefaultServerHost(createMap({ [root.name]: root, [imported.name]: imported }));
|
||||
const { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
|
||||
// ensure that imported file was found
|
||||
@@ -193,7 +193,7 @@ namespace ts {
|
||||
content: `export var y = 1`
|
||||
};
|
||||
|
||||
const fileMap: Map<File> = { [root.name]: root };
|
||||
const fileMap = createMap({ [root.name]: root });
|
||||
const serverHost = createDefaultServerHost(fileMap);
|
||||
const originalFileExists = serverHost.fileExists;
|
||||
|
||||
|
||||
@@ -403,6 +403,7 @@ namespace ts {
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -429,6 +430,7 @@ namespace ts {
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
allowJs: false,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -450,7 +452,8 @@ namespace ts {
|
||||
{
|
||||
compilerOptions:
|
||||
{
|
||||
allowJs: true
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2
|
||||
},
|
||||
errors: [{
|
||||
file: undefined,
|
||||
@@ -469,7 +472,8 @@ namespace ts {
|
||||
{
|
||||
compilerOptions:
|
||||
{
|
||||
allowJs: true
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("initTSConfig", () => {
|
||||
function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) {
|
||||
describe(name, () => {
|
||||
const commandLine = parseCommandLine(commandLinesArgs);
|
||||
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames);
|
||||
const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
|
||||
|
||||
it(`Correct output for ${outputFileName}`, () => {
|
||||
Harness.Baseline.runBaseline(outputFileName, () => {
|
||||
if (initResult) {
|
||||
return JSON.stringify(initResult, undefined, 4);
|
||||
}
|
||||
else {
|
||||
// This can happen if compiler recieve invalid compiler-options
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initTSConfigCorrectly("Default initialized TSConfig", ["--init"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with files options", ["--init", "file0.st", "file1.ts", "file2.ts"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with boolean value compiler options", ["--init", "--noUnusedLocals"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with enum value compiler options", ["--init", "--target", "es5", "--jsx", "react"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with list compiler options", ["--init", "--types", "jquery,mocha"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with list compiler options with enum value", ["--init", "--lib", "es5,es2015.core"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option", ["--init", "--someNonExistOption"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option value", ["--init", "--lib", "nonExistLib,es5,es2015.promise"]);
|
||||
});
|
||||
}
|
||||
@@ -767,16 +767,9 @@ namespace ts {
|
||||
parsesCorrectly(
|
||||
"{null}",
|
||||
`{
|
||||
"kind": "JSDocTypeReference",
|
||||
"kind": "NullKeyword",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"originalKeywordKind": "NullKeyword",
|
||||
"text": "null"
|
||||
}
|
||||
"end": 5
|
||||
}`);
|
||||
});
|
||||
|
||||
@@ -784,16 +777,9 @@ namespace ts {
|
||||
parsesCorrectly(
|
||||
"{undefined}",
|
||||
`{
|
||||
"kind": "JSDocTypeReference",
|
||||
"kind": "UndefinedKeyword",
|
||||
"pos": 1,
|
||||
"end": 10,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 1,
|
||||
"end": 10,
|
||||
"originalKeywordKind": "UndefinedKeyword",
|
||||
"text": "undefined"
|
||||
}
|
||||
"end": 10
|
||||
}`);
|
||||
});
|
||||
|
||||
@@ -2379,4 +2365,4 @@ namespace ts {
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ts {
|
||||
const map = arrayToMap(files, f => f.name);
|
||||
|
||||
if (hasDirectoryExists) {
|
||||
const directories: Map<string> = {};
|
||||
const directories = createMap<string>();
|
||||
for (const f of files) {
|
||||
let name = getDirectoryPath(f.name);
|
||||
while (true) {
|
||||
@@ -25,19 +25,19 @@ namespace ts {
|
||||
return {
|
||||
readFile,
|
||||
directoryExists: path => {
|
||||
return hasProperty(directories, path);
|
||||
return path in directories;
|
||||
},
|
||||
fileExists: path => {
|
||||
assert.isTrue(hasProperty(directories, getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`);
|
||||
return hasProperty(map, path);
|
||||
assert.isTrue(getDirectoryPath(path) in directories, `'fileExists' '${path}' request in non-existing directory`);
|
||||
return path in map;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return { readFile, fileExists: path => hasProperty(map, path), };
|
||||
return { readFile, fileExists: path => path in map, };
|
||||
}
|
||||
function readFile(path: string): string {
|
||||
return hasProperty(map, path) ? map[path].content : undefined;
|
||||
return path in map ? map[path].content : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace ts {
|
||||
const host: CompilerHost = {
|
||||
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
return path in files ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
|
||||
@@ -298,7 +298,7 @@ namespace ts {
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
fileExists: fileName => {
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path);
|
||||
return path in files;
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
};
|
||||
@@ -318,7 +318,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
it("should find all modules", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c/first/shared.ts": `
|
||||
class A {}
|
||||
export = A`,
|
||||
@@ -332,23 +332,23 @@ import Shared = require('../first/shared');
|
||||
class C {}
|
||||
export = C;
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, "/a/b/c/first/second", ["class_a.ts"], 3, ["../../../c/third/class_c.ts"]);
|
||||
});
|
||||
|
||||
it("should find modules in node_modules", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/parent/node_modules/mod/index.d.ts": "export var x",
|
||||
"/parent/app/myapp.ts": `import {x} from "mod"`
|
||||
};
|
||||
});
|
||||
test(files, "/parent/app", ["myapp.ts"], 2, []);
|
||||
});
|
||||
|
||||
it("should find file referenced via absolute and relative names", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="b.ts"/>`,
|
||||
"/a/b/b.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, "/a/b", ["c.ts", "/a/b/b.ts"], 2, []);
|
||||
});
|
||||
});
|
||||
@@ -358,11 +358,7 @@ export = C;
|
||||
function test(files: Map<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void {
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
if (!useCaseSensitiveFileNames) {
|
||||
const f: Map<string> = {};
|
||||
for (const fileName in files) {
|
||||
f[getCanonicalFileName(fileName)] = files[fileName];
|
||||
}
|
||||
files = f;
|
||||
files = reduceProperties(files, (files, file, fileName) => (files[getCanonicalFileName(fileName)] = file, files), createMap<string>());
|
||||
}
|
||||
|
||||
const host: CompilerHost = {
|
||||
@@ -371,7 +367,7 @@ export = C;
|
||||
return library;
|
||||
}
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
return path in files ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
|
||||
@@ -382,7 +378,7 @@ export = C;
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
fileExists: fileName => {
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path);
|
||||
return path in files;
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
};
|
||||
@@ -395,77 +391,77 @@ export = C;
|
||||
}
|
||||
|
||||
it("should succeed when the same file is referenced using absolute and relative names", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `import {x} from "D"`,
|
||||
"/a/b/d.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"moduleA.ts": `import {x} from "./ModuleB"`,
|
||||
"moduleB.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files exist on disk that differs only in casing", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `import {x} from "D"`,
|
||||
"/a/b/D.ts": "export var x",
|
||||
"/a/b/d.ts": "export var y"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when module name in 'require' calls has inconsistent casing", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"moduleA.ts": `import a = require("./ModuleC")`,
|
||||
"moduleB.ts": `import a = require("./moduleC")`,
|
||||
"moduleC.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
|
||||
});
|
||||
|
||||
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/B/c/moduleA.ts": `import a = require("./ModuleC")`,
|
||||
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleC.ts": "export var x",
|
||||
"/a/B/c/moduleD.ts": `
|
||||
import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
|
||||
});
|
||||
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/B/c/moduleA.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleC.ts": "export var x",
|
||||
"/a/B/c/moduleD.ts": `
|
||||
import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
|
||||
});
|
||||
});
|
||||
@@ -1023,7 +1019,7 @@ import b = require("./moduleB.ts");
|
||||
const names = map(files, f => f.name);
|
||||
const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES6)), f => f.fileName);
|
||||
const compilerHost: CompilerHost = {
|
||||
fileExists : fileName => hasProperty(sourceFiles, fileName),
|
||||
fileExists : fileName => fileName in sourceFiles,
|
||||
getSourceFile: fileName => sourceFiles[fileName],
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile(file, text) {
|
||||
@@ -1034,7 +1030,7 @@ import b = require("./moduleB.ts");
|
||||
getCanonicalFileName: f => f.toLowerCase(),
|
||||
getNewLine: () => "\r\n",
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
readFile: fileName => hasProperty(sourceFiles, fileName) ? sourceFiles[fileName].text : undefined
|
||||
readFile: fileName => fileName in sourceFiles ? sourceFiles[fileName].text : undefined
|
||||
};
|
||||
const program1 = createProgram(names, {}, compilerHost);
|
||||
const diagnostics1 = program1.getFileProcessingDiagnostics().getDiagnostics();
|
||||
|
||||
@@ -95,13 +95,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createSourceFileWithText(fileName: string, sourceText: SourceText, target: ScriptTarget) {
|
||||
const file = <SourceFileWithText>createSourceFile(fileName, sourceText.getFullText(), target);
|
||||
file.sourceText = sourceText;
|
||||
return file;
|
||||
}
|
||||
|
||||
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget): CompilerHost {
|
||||
const files: Map<SourceFileWithText> = {};
|
||||
for (const t of texts) {
|
||||
const file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target);
|
||||
file.sourceText = t.text;
|
||||
files[t.name] = file;
|
||||
}
|
||||
const files = arrayToMap(texts, t => t.name, t => createSourceFileWithText(t.name, t.text, target));
|
||||
|
||||
return {
|
||||
getSourceFile(fileName): SourceFile {
|
||||
@@ -128,10 +129,9 @@ namespace ts {
|
||||
getNewLine(): string {
|
||||
return sys ? sys.newLine : newLine;
|
||||
},
|
||||
fileExists: fileName => hasProperty(files, fileName),
|
||||
fileExists: fileName => fileName in files,
|
||||
readFile: fileName => {
|
||||
const file = lookUp(files, fileName);
|
||||
return file && file.text;
|
||||
return fileName in files ? files[fileName].text : undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -152,29 +152,29 @@ namespace ts {
|
||||
return program;
|
||||
}
|
||||
|
||||
function getSizeOfMap(map: Map<any>): number {
|
||||
let size = 0;
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
size++;
|
||||
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return size;
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): void {
|
||||
assert.isTrue(actual !== undefined);
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
function checkResolvedTypeDirective(expected: ResolvedTypeReferenceDirective, actual: ResolvedTypeReferenceDirective): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedTypeDirective(expected: ResolvedTypeReferenceDirective, actual: ResolvedTypeReferenceDirective): void {
|
||||
assert.isTrue(actual !== undefined);
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => void): void {
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => boolean): void {
|
||||
const file = program.getSourceFile(fileName);
|
||||
assert.isTrue(file !== undefined, `cannot find file ${fileName}`);
|
||||
const cache = getCache(file);
|
||||
@@ -183,23 +183,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
assert.isTrue(cache !== undefined, `expected ${caption} to be set`);
|
||||
const actualCacheSize = getSizeOfMap(cache);
|
||||
const expectedSize = getSizeOfMap(expectedContent);
|
||||
assert.isTrue(actualCacheSize === expectedSize, `expected actual size: ${actualCacheSize} to be equal to ${expectedSize}`);
|
||||
|
||||
for (const id in expectedContent) {
|
||||
if (hasProperty(expectedContent, id)) {
|
||||
|
||||
if (expectedContent[id]) {
|
||||
const expected = expectedContent[id];
|
||||
const actual = cache[id];
|
||||
entryChecker(expected, actual);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert.isTrue(cache[id] === undefined);
|
||||
}
|
||||
}
|
||||
assert.isTrue(equalOwnProperties(expectedContent, cache, entryChecker), `contents of ${caption} did not match the expected contents.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +297,8 @@ namespace ts {
|
||||
});
|
||||
|
||||
it("resolution cache follows imports", () => {
|
||||
(<any>Error).stackTraceLimit = Infinity;
|
||||
|
||||
const files = [
|
||||
{ name: "a.ts", text: SourceText.New("", "import {_} from 'b'", "var x = 1") },
|
||||
{ name: "b.ts", text: SourceText.New("", "", "var y = 2") },
|
||||
@@ -320,7 +306,7 @@ namespace ts {
|
||||
const options: CompilerOptions = { target };
|
||||
|
||||
const program_1 = newProgram(files, ["a.ts"], options);
|
||||
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
@@ -329,7 +315,7 @@ namespace ts {
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
// imports has changed - program is not reused
|
||||
@@ -346,7 +332,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateImportsAndExports(newImports);
|
||||
});
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedModulesCache(program_4, "a.ts", { "b": { resolvedFileName: "b.ts" }, "c": undefined });
|
||||
checkResolvedModulesCache(program_4, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" }, "c": undefined }));
|
||||
});
|
||||
|
||||
it("resolved type directives cache follows type directives", () => {
|
||||
@@ -357,7 +343,7 @@ namespace ts {
|
||||
const options: CompilerOptions = { target, typeRoots: ["/types"] };
|
||||
|
||||
const program_1 = newProgram(files, ["/a.ts"], options);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
@@ -366,7 +352,7 @@ namespace ts {
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
// type reference directives has changed - program is not reused
|
||||
@@ -384,7 +370,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
});
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace ts.server {
|
||||
describe("onMessage", () => {
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
let i = 0;
|
||||
for (name in CommandNames) {
|
||||
for (const name in CommandNames) {
|
||||
if (!Object.prototype.hasOwnProperty.call(CommandNames, name)) {
|
||||
continue;
|
||||
}
|
||||
@@ -362,13 +362,13 @@ namespace ts.server {
|
||||
class InProcClient {
|
||||
private server: InProcSession;
|
||||
private seq = 0;
|
||||
private callbacks: ts.Map<(resp: protocol.Response) => void> = {};
|
||||
private eventHandlers: ts.Map<(args: any) => void> = {};
|
||||
private callbacks = createMap<(resp: protocol.Response) => void>();
|
||||
private eventHandlers = createMap<(args: any) => void>();
|
||||
|
||||
handle(msg: protocol.Message): void {
|
||||
if (msg.type === "response") {
|
||||
const response = <protocol.Response>msg;
|
||||
if (this.callbacks[response.request_seq]) {
|
||||
if (response.request_seq in this.callbacks) {
|
||||
this.callbacks[response.request_seq](response);
|
||||
delete this.callbacks[response.request_seq];
|
||||
}
|
||||
@@ -380,7 +380,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
emit(name: string, args: any): void {
|
||||
if (this.eventHandlers[name]) {
|
||||
if (name in this.eventHandlers) {
|
||||
this.eventHandlers[name](args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ts {
|
||||
});
|
||||
|
||||
it("Correct errors for " + justName, () => {
|
||||
Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".errors.txt"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), () => {
|
||||
if (transpileResult.diagnostics.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
@@ -75,7 +75,7 @@ namespace ts {
|
||||
|
||||
if (canUseOldTranspile) {
|
||||
it("Correct errors (old transpile) for " + justName, () => {
|
||||
Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => {
|
||||
if (oldTranspileDiagnostics.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
@@ -88,7 +88,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
it("Correct output for " + justName, () => {
|
||||
Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".js"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".js"), () => {
|
||||
if (transpileResult.outputText) {
|
||||
return transpileResult.outputText;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace ts {
|
||||
|
||||
if (canUseOldTranspile) {
|
||||
it("Correct output (old transpile) for " + justName, () => {
|
||||
Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => {
|
||||
return oldTranspileResult;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -181,5 +181,26 @@ namespace ts {
|
||||
["/d.ts", "/folder/e.ts"]
|
||||
);
|
||||
});
|
||||
|
||||
it("parse and re-emit tsconfig.json file with diagnostics", () => {
|
||||
const content = `{
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
// Some comments
|
||||
"outDir": "bin"
|
||||
}
|
||||
"files": ["file1.ts"]
|
||||
}`;
|
||||
const { configJsonObject, diagnostics } = parseAndReEmitConfigJSONFile(content);
|
||||
const expectedResult = {
|
||||
compilerOptions: {
|
||||
allowJs: true,
|
||||
outDir: "bin"
|
||||
},
|
||||
files: ["file1.ts"]
|
||||
};
|
||||
assert.isTrue(diagnostics.length === 2);
|
||||
assert.equal(JSON.stringify(configJsonObject), JSON.stringify(expectedResult));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,20 +68,10 @@ namespace ts {
|
||||
return entry;
|
||||
}
|
||||
|
||||
function sizeOfMap(map: Map<any>): number {
|
||||
let n = 0;
|
||||
for (const name in map) {
|
||||
if (hasProperty(map, name)) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
|
||||
assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
assert.equal(reduceProperties(map, count => count + 1, 0), expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
for (const name of expectedKeys) {
|
||||
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`);
|
||||
assert.isTrue(name in map, `${caption} is expected to contain ${name}, actual keys: ${Object.keys(map)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,8 +116,8 @@ namespace ts {
|
||||
private getCanonicalFileName: (s: string) => string;
|
||||
private toPath: (f: string) => Path;
|
||||
private callbackQueue: TimeOutCallback[] = [];
|
||||
readonly watchedDirectories: Map<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {};
|
||||
readonly watchedFiles: Map<FileWatcherCallback[]> = {};
|
||||
readonly watchedDirectories = createMap<{ cb: DirectoryWatcherCallback, recursive: boolean }[]>();
|
||||
readonly watchedFiles = createMap<FileWatcherCallback[]>();
|
||||
|
||||
constructor(public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: FileOrFolder[]) {
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
@@ -208,7 +198,7 @@ namespace ts {
|
||||
|
||||
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
|
||||
const path = this.toPath(directoryName);
|
||||
const callbacks = lookUp(this.watchedDirectories, path) || (this.watchedDirectories[path] = []);
|
||||
const callbacks = this.watchedDirectories[path] || (this.watchedDirectories[path] = []);
|
||||
callbacks.push({ cb: callback, recursive });
|
||||
return {
|
||||
referenceCount: 0,
|
||||
@@ -229,7 +219,7 @@ namespace ts {
|
||||
|
||||
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
|
||||
const path = this.toPath(directoryName);
|
||||
const callbacks = lookUp(this.watchedDirectories, path);
|
||||
const callbacks = this.watchedDirectories[path];
|
||||
if (callbacks) {
|
||||
for (const callback of callbacks) {
|
||||
callback.cb(fileName);
|
||||
@@ -239,7 +229,7 @@ namespace ts {
|
||||
|
||||
triggerFileWatcherCallback(fileName: string, removed?: boolean): void {
|
||||
const path = this.toPath(fileName);
|
||||
const callbacks = lookUp(this.watchedFiles, path);
|
||||
const callbacks = this.watchedFiles[path];
|
||||
if (callbacks) {
|
||||
for (const callback of callbacks) {
|
||||
callback(path, removed);
|
||||
@@ -249,7 +239,7 @@ namespace ts {
|
||||
|
||||
watchFile(fileName: string, callback: FileWatcherCallback) {
|
||||
const path = this.toPath(fileName);
|
||||
const callbacks = lookUp(this.watchedFiles, path) || (this.watchedFiles[path] = []);
|
||||
const callbacks = this.watchedFiles[path] || (this.watchedFiles[path] = []);
|
||||
callbacks.push(callback);
|
||||
return {
|
||||
close: () => {
|
||||
@@ -594,7 +584,7 @@ namespace ts {
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
},
|
||||
},
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
@@ -621,7 +611,7 @@ namespace ts {
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
},
|
||||
},
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
@@ -633,5 +623,23 @@ namespace ts {
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkNumberOfInferredProjects(projectService, 0);
|
||||
});
|
||||
|
||||
it("should tolerate config file errors and still try to build a project", () => {
|
||||
const configFile: FileOrFolder = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"allowAnything": true
|
||||
},
|
||||
"someOtherProperty": {}
|
||||
}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, libFile, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkConfiguredProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
Vendored
+55
-15
@@ -126,6 +126,7 @@ interface KeyAlgorithm {
|
||||
}
|
||||
|
||||
interface KeyboardEventInit extends EventModifierInit {
|
||||
code?: string;
|
||||
key?: string;
|
||||
location?: number;
|
||||
repeat?: boolean;
|
||||
@@ -2288,7 +2289,7 @@ declare var DeviceRotationRate: {
|
||||
new(): DeviceRotationRate;
|
||||
}
|
||||
|
||||
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent {
|
||||
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent, ParentNode {
|
||||
/**
|
||||
* Sets or gets the URL for the current document.
|
||||
*/
|
||||
@@ -3351,7 +3352,7 @@ declare var Document: {
|
||||
new(): Document;
|
||||
}
|
||||
|
||||
interface DocumentFragment extends Node, NodeSelector {
|
||||
interface DocumentFragment extends Node, NodeSelector, ParentNode {
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -3420,7 +3421,7 @@ declare var EXT_texture_filter_anisotropic: {
|
||||
readonly TEXTURE_MAX_ANISOTROPY_EXT: number;
|
||||
}
|
||||
|
||||
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode {
|
||||
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode, ParentNode {
|
||||
readonly classList: DOMTokenList;
|
||||
className: string;
|
||||
readonly clientHeight: number;
|
||||
@@ -3675,6 +3676,16 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
|
||||
getElementsByClassName(classNames: string): NodeListOf<Element>;
|
||||
matches(selector: string): boolean;
|
||||
closest(selector: string): Element | null;
|
||||
scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;
|
||||
scroll(options?: ScrollToOptions): void;
|
||||
scroll(x: number, y: number): void;
|
||||
scrollTo(options?: ScrollToOptions): void;
|
||||
scrollTo(x: number, y: number): void;
|
||||
scrollBy(options?: ScrollToOptions): void;
|
||||
scrollBy(x: number, y: number): void;
|
||||
insertAdjacentElement(position: string, insertedElement: Element): Element | null;
|
||||
insertAdjacentHTML(where: string, html: string): void;
|
||||
insertAdjacentText(where: string, text: string): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -4446,7 +4457,7 @@ interface HTMLCanvasElement extends HTMLElement {
|
||||
* @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.
|
||||
*/
|
||||
toDataURL(type?: string, ...args: any[]): string;
|
||||
toBlob(callback: (result: Blob | null) => void, ... arguments: any[]): void;
|
||||
toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void;
|
||||
}
|
||||
|
||||
declare var HTMLCanvasElement: {
|
||||
@@ -4621,11 +4632,7 @@ interface HTMLElement extends Element {
|
||||
click(): void;
|
||||
dragDrop(): boolean;
|
||||
focus(): void;
|
||||
insertAdjacentElement(position: string, insertedElement: Element): Element;
|
||||
insertAdjacentHTML(where: string, html: string): void;
|
||||
insertAdjacentText(where: string, text: string): void;
|
||||
msGetInputContext(): MSInputMethodContext;
|
||||
scrollIntoView(top?: boolean): void;
|
||||
setActive(): void;
|
||||
addEventListener(type: "MSContentZoom", listener: (this: this, ev: UIEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -5890,6 +5897,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle {
|
||||
*/
|
||||
type: string;
|
||||
import?: Document;
|
||||
integrity: string;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -6178,7 +6186,7 @@ interface HTMLMediaElement extends HTMLElement {
|
||||
*/
|
||||
canPlayType(type: string): string;
|
||||
/**
|
||||
* Fires immediately after the client loads the object.
|
||||
* Resets the audio or video object and loads a new media resource.
|
||||
*/
|
||||
load(): void;
|
||||
/**
|
||||
@@ -6751,6 +6759,7 @@ interface HTMLScriptElement extends HTMLElement {
|
||||
* Sets or retrieves the MIME type for the associated scripting engine.
|
||||
*/
|
||||
type: string;
|
||||
integrity: string;
|
||||
}
|
||||
|
||||
declare var HTMLScriptElement: {
|
||||
@@ -7756,6 +7765,7 @@ interface KeyboardEvent extends UIEvent {
|
||||
readonly repeat: boolean;
|
||||
readonly shiftKey: boolean;
|
||||
readonly which: number;
|
||||
readonly code: string;
|
||||
getModifierState(keyArg: string): boolean;
|
||||
initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;
|
||||
readonly DOM_KEY_LOCATION_JOYSTICK: number;
|
||||
@@ -9128,6 +9138,7 @@ interface PerformanceTiming {
|
||||
readonly responseStart: number;
|
||||
readonly unloadEventEnd: number;
|
||||
readonly unloadEventStart: number;
|
||||
readonly secureConnectionStart: number;
|
||||
toJSON(): any;
|
||||
}
|
||||
|
||||
@@ -11405,8 +11416,8 @@ declare var StereoPannerNode: {
|
||||
interface Storage {
|
||||
readonly length: number;
|
||||
clear(): void;
|
||||
getItem(key: string): string;
|
||||
key(index: number): string;
|
||||
getItem(key: string): string | null;
|
||||
key(index: number): string | null;
|
||||
removeItem(key: string): void;
|
||||
setItem(key: string, data: string): void;
|
||||
[key: string]: any;
|
||||
@@ -12947,7 +12958,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
|
||||
onunload: (this: this, ev: Event) => any;
|
||||
onvolumechange: (this: this, ev: Event) => any;
|
||||
onwaiting: (this: this, ev: Event) => any;
|
||||
readonly opener: Window;
|
||||
opener: any;
|
||||
orientation: string | number;
|
||||
readonly outerHeight: number;
|
||||
readonly outerWidth: number;
|
||||
@@ -13002,6 +13013,9 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
|
||||
webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
|
||||
scroll(options?: ScrollToOptions): void;
|
||||
scrollTo(options?: ScrollToOptions): void;
|
||||
scrollBy(options?: ScrollToOptions): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -14029,6 +14043,20 @@ interface ProgressEventInit extends EventInit {
|
||||
total?: number;
|
||||
}
|
||||
|
||||
interface ScrollOptions {
|
||||
behavior?: ScrollBehavior;
|
||||
}
|
||||
|
||||
interface ScrollToOptions extends ScrollOptions {
|
||||
left?: number;
|
||||
top?: number;
|
||||
}
|
||||
|
||||
interface ScrollIntoViewOptions extends ScrollOptions {
|
||||
block?: ScrollLogicalPosition;
|
||||
inline?: ScrollLogicalPosition;
|
||||
}
|
||||
|
||||
interface ClipboardEventInit extends EventInit {
|
||||
data?: string;
|
||||
dataType?: string;
|
||||
@@ -14072,7 +14100,7 @@ interface EcdsaParams extends Algorithm {
|
||||
}
|
||||
|
||||
interface EcKeyGenParams extends Algorithm {
|
||||
typedCurve: string;
|
||||
namedCurve: string;
|
||||
}
|
||||
|
||||
interface EcKeyAlgorithm extends KeyAlgorithm {
|
||||
@@ -14208,6 +14236,13 @@ interface JsonWebKey {
|
||||
k?: string;
|
||||
}
|
||||
|
||||
interface ParentNode {
|
||||
readonly children: HTMLCollection;
|
||||
readonly firstElementChild: Element;
|
||||
readonly lastElementChild: Element;
|
||||
readonly childElementCount: number;
|
||||
}
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface ErrorEventHandler {
|
||||
@@ -14278,7 +14313,7 @@ declare var location: Location;
|
||||
declare var locationbar: BarProp;
|
||||
declare var menubar: BarProp;
|
||||
declare var msCredentials: MSCredentials;
|
||||
declare var name: string;
|
||||
declare const name: never;
|
||||
declare var navigator: Navigator;
|
||||
declare var offscreenBuffering: string | boolean;
|
||||
declare var onabort: (this: Window, ev: UIEvent) => any;
|
||||
@@ -14372,7 +14407,7 @@ declare var ontouchstart: (ev: TouchEvent) => any;
|
||||
declare var onunload: (this: Window, ev: Event) => any;
|
||||
declare var onvolumechange: (this: Window, ev: Event) => any;
|
||||
declare var onwaiting: (this: Window, ev: Event) => any;
|
||||
declare var opener: Window;
|
||||
declare var opener: any;
|
||||
declare var orientation: string | number;
|
||||
declare var outerHeight: number;
|
||||
declare var outerWidth: number;
|
||||
@@ -14425,6 +14460,9 @@ declare function webkitCancelAnimationFrame(handle: number): void;
|
||||
declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
declare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
|
||||
declare function scroll(options?: ScrollToOptions): void;
|
||||
declare function scrollTo(options?: ScrollToOptions): void;
|
||||
declare function scrollBy(options?: ScrollToOptions): void;
|
||||
declare function toString(): string;
|
||||
declare function addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
declare function dispatchEvent(evt: Event): boolean;
|
||||
@@ -14580,6 +14618,8 @@ type MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload;
|
||||
type RTCIceGatherCandidate = RTCIceCandidate | RTCIceCandidateComplete;
|
||||
type RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport;
|
||||
type payloadtype = number;
|
||||
type ScrollBehavior = "auto" | "instant" | "smooth";
|
||||
type ScrollLogicalPosition = "start" | "center" | "end" | "nearest";
|
||||
type IDBValidKey = number | string | Date | IDBArrayKey;
|
||||
type BufferSource = ArrayBuffer | ArrayBufferView;
|
||||
type MouseWheelEvent = WheelEvent;
|
||||
Vendored
+28
@@ -68,6 +68,10 @@ interface ArrayConstructor {
|
||||
of<T>(...items: T[]): Array<T>;
|
||||
}
|
||||
|
||||
interface DateConstructor {
|
||||
new (value: Date): Date;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
/**
|
||||
* Returns the name of the function. Function names are read-only and can not be changed.
|
||||
@@ -343,6 +347,30 @@ interface ObjectConstructor {
|
||||
defineProperty(o: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): any;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T) => boolean, thisArg?: any): number;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
|
||||
|
||||
Vendored
+20
@@ -63,6 +63,26 @@ interface ArrayConstructor {
|
||||
from<T>(iterable: Iterable<T>): Array<T>;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
|
||||
interface IArguments {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<any>;
|
||||
|
||||
Vendored
+6
-1
@@ -1006,7 +1006,12 @@ interface ReadonlyArray<T> {
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(...items: T[]): T[];
|
||||
concat(...items: T[][]): T[];
|
||||
/**
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(...items: (T | T[])[]): T[];
|
||||
/**
|
||||
* Adds all the elements of an array separated by the specified separator string.
|
||||
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
||||
|
||||
Vendored
+1
-1
@@ -1000,7 +1000,7 @@ interface EcdsaParams extends Algorithm {
|
||||
}
|
||||
|
||||
interface EcKeyGenParams extends Algorithm {
|
||||
typedCurve: string;
|
||||
namedCurve: string;
|
||||
}
|
||||
|
||||
interface EcKeyAlgorithm extends KeyAlgorithm {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ts.server {
|
||||
|
||||
export class SessionClient implements LanguageService {
|
||||
private sequence: number = 0;
|
||||
private lineMaps: ts.Map<number[]> = {};
|
||||
private lineMaps: ts.Map<number[]> = ts.createMap<number[]>();
|
||||
private messages: string[] = [];
|
||||
private lastRenameEntry: RenameEntry;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getLineMap(fileName: string): number[] {
|
||||
let lineMap = ts.lookUp(this.lineMaps, fileName);
|
||||
let lineMap = this.lineMaps[fileName];
|
||||
if (!lineMap) {
|
||||
const scriptSnapshot = this.host.getScriptSnapshot(fileName);
|
||||
lineMap = this.lineMaps[fileName] = ts.computeLineStarts(scriptSnapshot.getText(0, scriptSnapshot.getLength()));
|
||||
|
||||
+126
-107
@@ -130,15 +130,15 @@ namespace ts.server {
|
||||
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
|
||||
const currentResolutionsInFile = cache.get(path);
|
||||
|
||||
const newResolutions: Map<T> = {};
|
||||
const newResolutions = createMap<T>();
|
||||
const resolvedModules: R[] = [];
|
||||
const compilerOptions = this.getCompilationSettings();
|
||||
|
||||
for (const name of names) {
|
||||
// check if this is a duplicate entry in the list
|
||||
let resolution = lookUp(newResolutions, name);
|
||||
let resolution = newResolutions[name];
|
||||
if (!resolution) {
|
||||
const existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, name);
|
||||
const existingResolution = currentResolutionsInFile && currentResolutionsInFile[name];
|
||||
if (moduleResolutionIsValid(existingResolution)) {
|
||||
// ok, it is safe to use existing name resolution results
|
||||
resolution = existingResolution;
|
||||
@@ -378,7 +378,7 @@ namespace ts.server {
|
||||
export interface ProjectOptions {
|
||||
// these fields can be present in the project file
|
||||
files?: string[];
|
||||
wildcardDirectories?: ts.Map<ts.WatchDirectoryFlags>;
|
||||
wildcardDirectories?: ts.MapLike<ts.WatchDirectoryFlags>;
|
||||
compilerOptions?: ts.CompilerOptions;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ namespace ts.server {
|
||||
// Used to keep track of what directories are watched for this project
|
||||
directoriesWatchedForTsconfig: string[] = [];
|
||||
program: ts.Program;
|
||||
filenameToSourceFile: ts.Map<ts.SourceFile> = {};
|
||||
filenameToSourceFile = ts.createMap<ts.SourceFile>();
|
||||
updateGraphSeq = 0;
|
||||
/** Used for configured projects which may have multiple open roots */
|
||||
openRefCount = 0;
|
||||
@@ -504,7 +504,7 @@ namespace ts.server {
|
||||
return;
|
||||
}
|
||||
|
||||
this.filenameToSourceFile = {};
|
||||
this.filenameToSourceFile = createMap<SourceFile>();
|
||||
const sourceFiles = this.program.getSourceFiles();
|
||||
for (let i = 0, len = sourceFiles.length; i < len; i++) {
|
||||
const normFilename = ts.normalizePath(sourceFiles[i].fileName);
|
||||
@@ -563,7 +563,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
let strBuilder = "";
|
||||
ts.forEachValue(this.filenameToSourceFile,
|
||||
ts.forEachProperty(this.filenameToSourceFile,
|
||||
sourceFile => { strBuilder += sourceFile.fileName + "\n"; });
|
||||
return strBuilder;
|
||||
}
|
||||
@@ -603,8 +603,11 @@ namespace ts.server {
|
||||
return projects.length > 1 ? deduplicate(result, areEqual) : result;
|
||||
}
|
||||
|
||||
export type ProjectServiceEvent =
|
||||
{ eventName: "context", data: { project: Project, fileName: string } } | { eventName: "configFileDiag", data: { triggerFile?: string, configFileName: string, diagnostics: Diagnostic[] } }
|
||||
|
||||
export interface ProjectServiceEventHandler {
|
||||
(eventName: string, project: Project, fileName: string): void;
|
||||
(event: ProjectServiceEvent): void;
|
||||
}
|
||||
|
||||
export interface HostConfiguration {
|
||||
@@ -613,7 +616,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
export class ProjectService {
|
||||
filenameToScriptInfo: ts.Map<ScriptInfo> = {};
|
||||
filenameToScriptInfo = ts.createMap<ScriptInfo>();
|
||||
// open, non-configured root files
|
||||
openFileRoots: ScriptInfo[] = [];
|
||||
// projects built from openFileRoots
|
||||
@@ -625,12 +628,12 @@ namespace ts.server {
|
||||
// open files that are roots of a configured project
|
||||
openFileRootsConfigured: ScriptInfo[] = [];
|
||||
// a path to directory watcher map that detects added tsconfig files
|
||||
directoryWatchersForTsconfig: ts.Map<FileWatcher> = {};
|
||||
directoryWatchersForTsconfig = ts.createMap<FileWatcher>();
|
||||
// count of how many projects are using the directory watcher. If the
|
||||
// number becomes 0 for a watcher, then we should close it.
|
||||
directoryWatchersRefCount: ts.Map<number> = {};
|
||||
directoryWatchersRefCount = ts.createMap<number>();
|
||||
hostConfiguration: HostConfiguration;
|
||||
timerForDetectingProjectFileListChanges: Map<any> = {};
|
||||
timerForDetectingProjectFileListChanges = createMap<any>();
|
||||
|
||||
constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) {
|
||||
// ts.disableIncrementalParsing = true;
|
||||
@@ -699,7 +702,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
handleProjectFileListChanges(project: Project) {
|
||||
const { projectOptions } = this.configFileToProjectOptions(project.projectFilename);
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
this.reportConfigFileDiagnostics(project.projectFilename, errors);
|
||||
|
||||
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
|
||||
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
|
||||
@@ -717,18 +721,32 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile?: string) {
|
||||
if (diagnostics && diagnostics.length > 0) {
|
||||
this.eventHandler({
|
||||
eventName: "configFileDiag",
|
||||
data: { configFileName, diagnostics, triggerFile }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the callback function when a watched directory has an added tsconfig file.
|
||||
*/
|
||||
directoryWatchedForTsconfigChanged(fileName: string) {
|
||||
if (ts.getBaseFileName(fileName) != "tsconfig.json") {
|
||||
if (ts.getBaseFileName(fileName) !== "tsconfig.json") {
|
||||
this.log(fileName + " is not tsconfig.json");
|
||||
return;
|
||||
}
|
||||
|
||||
this.log("Detected newly added tsconfig file: " + fileName);
|
||||
|
||||
const { projectOptions } = this.configFileToProjectOptions(fileName);
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(fileName);
|
||||
this.reportConfigFileDiagnostics(fileName, errors);
|
||||
|
||||
if (!projectOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootFilesInTsconfig = projectOptions.files.map(f => this.getCanonicalFileName(f));
|
||||
const openFileRoots = this.openFileRoots.map(s => this.getCanonicalFileName(s.fileName));
|
||||
@@ -748,10 +766,13 @@ namespace ts.server {
|
||||
return ts.normalizePath(name);
|
||||
}
|
||||
|
||||
watchedProjectConfigFileChanged(project: Project) {
|
||||
watchedProjectConfigFileChanged(project: Project): void {
|
||||
this.log("Config file changed: " + project.projectFilename);
|
||||
this.updateConfiguredProject(project);
|
||||
const configFileErrors = this.updateConfiguredProject(project);
|
||||
this.updateProjectStructure();
|
||||
if (configFileErrors && configFileErrors.length > 0) {
|
||||
this.eventHandler({ eventName: "configFileDiag", data: { triggerFile: project.projectFilename, configFileName: project.projectFilename, diagnostics: configFileErrors } });
|
||||
}
|
||||
}
|
||||
|
||||
log(msg: string, type = "Err") {
|
||||
@@ -828,13 +849,13 @@ namespace ts.server {
|
||||
for (let j = 0, flen = this.openFileRoots.length; j < flen; j++) {
|
||||
const openFile = this.openFileRoots[j];
|
||||
if (this.eventHandler) {
|
||||
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
|
||||
this.eventHandler({ eventName: "context", data: { project: openFile.defaultProject, fileName: openFile.fileName } });
|
||||
}
|
||||
}
|
||||
for (let j = 0, flen = this.openFilesReferenced.length; j < flen; j++) {
|
||||
const openFile = this.openFilesReferenced[j];
|
||||
if (this.eventHandler) {
|
||||
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
|
||||
this.eventHandler({ eventName: "context", data: { project: openFile.defaultProject, fileName: openFile.fileName } });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -857,7 +878,7 @@ namespace ts.server {
|
||||
if (project.isConfiguredProject()) {
|
||||
project.projectFileWatcher.close();
|
||||
project.directoryWatcher.close();
|
||||
forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
|
||||
forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
|
||||
delete project.directoriesWatchedForWildcards;
|
||||
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
|
||||
}
|
||||
@@ -1124,7 +1145,7 @@ namespace ts.server {
|
||||
|
||||
getScriptInfo(filename: string) {
|
||||
filename = ts.normalizePath(filename);
|
||||
return ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
return this.filenameToScriptInfo[filename];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1133,7 +1154,7 @@ namespace ts.server {
|
||||
*/
|
||||
openFile(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
|
||||
let info = this.filenameToScriptInfo[fileName];
|
||||
if (!info) {
|
||||
let content: string;
|
||||
if (this.host.fileExists(fileName)) {
|
||||
@@ -1218,7 +1239,7 @@ namespace ts.server {
|
||||
const project = this.findConfiguredProjectByConfigFile(configFileName);
|
||||
if (!project) {
|
||||
const configResult = this.openConfigFile(configFileName, fileName);
|
||||
if (!configResult.success) {
|
||||
if (!configResult.project) {
|
||||
return { configFileName, configFileErrors: configResult.errors };
|
||||
}
|
||||
else {
|
||||
@@ -1234,11 +1255,12 @@ namespace ts.server {
|
||||
else {
|
||||
this.updateConfiguredProject(project);
|
||||
}
|
||||
return { configFileName };
|
||||
}
|
||||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
return configFileName ? { configFileName } : {};
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1246,7 +1268,7 @@ namespace ts.server {
|
||||
* @param filename is absolute pathname
|
||||
*/
|
||||
closeClientFile(filename: string) {
|
||||
const info = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const info = this.filenameToScriptInfo[filename];
|
||||
if (info) {
|
||||
this.closeOpenFile(info);
|
||||
info.isOpen = false;
|
||||
@@ -1255,14 +1277,14 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getProjectForFile(filename: string) {
|
||||
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const scriptInfo = this.filenameToScriptInfo[filename];
|
||||
if (scriptInfo) {
|
||||
return scriptInfo.defaultProject;
|
||||
}
|
||||
}
|
||||
|
||||
printProjectsForFile(filename: string) {
|
||||
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const scriptInfo = this.filenameToScriptInfo[filename];
|
||||
if (scriptInfo) {
|
||||
this.psLogger.startGroup();
|
||||
this.psLogger.info("Projects for " + filename);
|
||||
@@ -1328,34 +1350,31 @@ namespace ts.server {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
configFileToProjectOptions(configFilename: string): { succeeded: boolean, projectOptions?: ProjectOptions, errors?: Diagnostic[] } {
|
||||
configFileToProjectOptions(configFilename: string): { projectOptions?: ProjectOptions, errors: Diagnostic[] } {
|
||||
configFilename = ts.normalizePath(configFilename);
|
||||
let errors: Diagnostic[] = [];
|
||||
// file references will be relative to dirPath (or absolute)
|
||||
const dirPath = ts.getDirectoryPath(configFilename);
|
||||
const contents = this.host.readFile(configFilename);
|
||||
const rawConfig: { config?: ProjectOptions; error?: Diagnostic; } = ts.parseConfigFileTextToJson(configFilename, contents);
|
||||
if (rawConfig.error) {
|
||||
return { succeeded: false, errors: [rawConfig.error] };
|
||||
const { configJsonObject, diagnostics } = ts.parseAndReEmitConfigJSONFile(contents);
|
||||
errors = concatenate(errors, diagnostics);
|
||||
const parsedCommandLine = ts.parseJsonConfigFileContent(configJsonObject, this.host, dirPath, /*existingOptions*/ {}, configFilename);
|
||||
errors = concatenate(errors, parsedCommandLine.errors);
|
||||
Debug.assert(!!parsedCommandLine.fileNames);
|
||||
|
||||
if (parsedCommandLine.fileNames.length === 0) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename));
|
||||
return { errors };
|
||||
}
|
||||
else {
|
||||
const parsedCommandLine = ts.parseJsonConfigFileContent(rawConfig.config, this.host, dirPath, /*existingOptions*/ {}, configFilename);
|
||||
Debug.assert(!!parsedCommandLine.fileNames);
|
||||
|
||||
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
|
||||
return { succeeded: false, errors: parsedCommandLine.errors };
|
||||
}
|
||||
else if (parsedCommandLine.fileNames.length === 0) {
|
||||
const error = createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename);
|
||||
return { succeeded: false, errors: [error] };
|
||||
}
|
||||
else {
|
||||
const projectOptions: ProjectOptions = {
|
||||
files: parsedCommandLine.fileNames,
|
||||
wildcardDirectories: parsedCommandLine.wildcardDirectories,
|
||||
compilerOptions: parsedCommandLine.options,
|
||||
};
|
||||
return { succeeded: true, projectOptions };
|
||||
}
|
||||
// if the project has some files, we can continue with the parsed options and tolerate
|
||||
// errors in the parsedCommandLine
|
||||
const projectOptions: ProjectOptions = {
|
||||
files: parsedCommandLine.fileNames,
|
||||
wildcardDirectories: parsedCommandLine.wildcardDirectories,
|
||||
compilerOptions: parsedCommandLine.options,
|
||||
};
|
||||
return { projectOptions, errors };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1377,64 +1396,63 @@ namespace ts.server {
|
||||
return false;
|
||||
}
|
||||
|
||||
openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } {
|
||||
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename);
|
||||
if (!succeeded) {
|
||||
return { success: false, errors };
|
||||
openConfigFile(configFilename: string, clientFileName?: string): { project?: Project, errors: Diagnostic[] } {
|
||||
const parseConfigFileResult = this.configFileToProjectOptions(configFilename);
|
||||
let errors = parseConfigFileResult.errors;
|
||||
if (!parseConfigFileResult.projectOptions) {
|
||||
return { errors };
|
||||
}
|
||||
else {
|
||||
if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
|
||||
const projectOptions = parseConfigFileResult.projectOptions;
|
||||
if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
|
||||
|
||||
// for configured projects with languageService disabled, we only watch its config file,
|
||||
// do not care about the directory changes in the folder.
|
||||
project.projectFileWatcher = this.host.watchFile(
|
||||
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
_ => this.watchedProjectConfigFileChanged(project));
|
||||
return { success: true, project };
|
||||
}
|
||||
// for configured projects with languageService disabled, we only watch its config file,
|
||||
// do not care about the directory changes in the folder.
|
||||
project.projectFileWatcher = this.host.watchFile(
|
||||
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
_ => this.watchedProjectConfigFileChanged(project));
|
||||
return { project, errors };
|
||||
}
|
||||
}
|
||||
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
for (const rootFilename of projectOptions.files) {
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else {
|
||||
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename));
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
|
||||
|
||||
const configDirectoryPath = ts.getDirectoryPath(configFilename);
|
||||
|
||||
this.log("Add recursive watcher for: " + configDirectoryPath);
|
||||
project.directoryWatcher = this.host.watchDirectory(
|
||||
configDirectoryPath,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
|
||||
project.directoriesWatchedForWildcards = reduceProperties(createMap(projectOptions.wildcardDirectories), (watchers, flag, directory) => {
|
||||
if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
|
||||
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
|
||||
this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);
|
||||
watchers[directory] = this.host.watchDirectory(
|
||||
directory,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
recursive
|
||||
);
|
||||
}
|
||||
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
let errors: Diagnostic[];
|
||||
for (const rootFilename of projectOptions.files) {
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else {
|
||||
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename));
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
|
||||
return watchers;
|
||||
}, <Map<FileWatcher>>{});
|
||||
|
||||
const configDirectoryPath = ts.getDirectoryPath(configFilename);
|
||||
|
||||
this.log("Add recursive watcher for: " + configDirectoryPath);
|
||||
project.directoryWatcher = this.host.watchDirectory(
|
||||
configDirectoryPath,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
|
||||
project.directoriesWatchedForWildcards = reduceProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
|
||||
if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
|
||||
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
|
||||
this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);
|
||||
watchers[directory] = this.host.watchDirectory(
|
||||
directory,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
recursive
|
||||
);
|
||||
}
|
||||
|
||||
return watchers;
|
||||
}, <Map<FileWatcher>>{});
|
||||
|
||||
return { success: true, project: project, errors };
|
||||
}
|
||||
return { project: project, errors };
|
||||
}
|
||||
|
||||
updateConfiguredProject(project: Project): Diagnostic[] {
|
||||
@@ -1443,15 +1461,15 @@ namespace ts.server {
|
||||
this.removeProject(project);
|
||||
}
|
||||
else {
|
||||
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
if (!succeeded) {
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
if (!projectOptions) {
|
||||
return errors;
|
||||
}
|
||||
else {
|
||||
if (projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit && this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
project.setProjectOptions(projectOptions);
|
||||
if (project.languageServiceDiabled) {
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
project.disableLanguageService();
|
||||
@@ -1459,7 +1477,7 @@ namespace ts.server {
|
||||
project.directoryWatcher.close();
|
||||
project.directoryWatcher = undefined;
|
||||
}
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (project.languageServiceDiabled) {
|
||||
@@ -1478,7 +1496,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
// if the project is too large, the root files might not have been all loaded if the total
|
||||
@@ -1524,6 +1542,7 @@ namespace ts.server {
|
||||
project.setProjectOptions(projectOptions);
|
||||
project.finishGraph();
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-10
@@ -153,16 +153,22 @@ namespace ts.server {
|
||||
private logger: Logger
|
||||
) {
|
||||
this.projectService =
|
||||
new ProjectService(host, logger, (eventName, project, fileName) => {
|
||||
this.handleEvent(eventName, project, fileName);
|
||||
new ProjectService(host, logger, event => {
|
||||
this.handleEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
private handleEvent(eventName: string, project: Project, fileName: string) {
|
||||
if (eventName == "context") {
|
||||
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
|
||||
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
|
||||
(n) => n === this.changeSeq, 100);
|
||||
private handleEvent(event: ProjectServiceEvent) {
|
||||
switch (event.eventName) {
|
||||
case "context":
|
||||
const { project, fileName } = event.data;
|
||||
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
|
||||
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
|
||||
(n) => n === this.changeSeq, 100);
|
||||
break;
|
||||
case "configFileDiag":
|
||||
const { triggerFile, configFileName, diagnostics } = event.data;
|
||||
this.configFileDiagnosticEvent(triggerFile, configFileName, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1061,7 +1067,7 @@ namespace ts.server {
|
||||
return { response, responseRequired: true };
|
||||
}
|
||||
|
||||
private handlers: Map<(request: protocol.Request) => { response?: any, responseRequired?: boolean }> = {
|
||||
private handlers = createMap<(request: protocol.Request) => { response?: any, responseRequired?: boolean }>({
|
||||
[CommandNames.Exit]: () => {
|
||||
this.exit();
|
||||
return { responseRequired: false };
|
||||
@@ -1198,9 +1204,10 @@ namespace ts.server {
|
||||
this.reloadProjects();
|
||||
return { responseRequired: false };
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => { response?: any, responseRequired: boolean }) {
|
||||
if (this.handlers[command]) {
|
||||
if (command in this.handlers) {
|
||||
throw new Error(`Protocol handler already exists for command "${command}"`);
|
||||
}
|
||||
this.handlers[command] = handler;
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ts.JsTyping {
|
||||
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
|
||||
|
||||
// A typing name to typing file path mapping
|
||||
const inferredTypings: Map<string> = {};
|
||||
const inferredTypings = createMap<string>();
|
||||
|
||||
if (!typingOptions || !typingOptions.enableAutoDiscovery) {
|
||||
return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
|
||||
@@ -58,12 +58,7 @@ namespace ts.JsTyping {
|
||||
|
||||
if (!safeList) {
|
||||
const result = readConfigFile(safeListPath, (path: string) => host.readFile(path));
|
||||
if (result.config) {
|
||||
safeList = result.config;
|
||||
}
|
||||
else {
|
||||
safeList = {};
|
||||
};
|
||||
safeList = createMap<string>(result.config);
|
||||
}
|
||||
|
||||
const filesToWatch: string[] = [];
|
||||
@@ -93,7 +88,7 @@ namespace ts.JsTyping {
|
||||
|
||||
// Add the cached typing locations for inferred typings that are already installed
|
||||
for (const name in packageNameToTypingLocation) {
|
||||
if (hasProperty(inferredTypings, name) && !inferredTypings[name]) {
|
||||
if (name in inferredTypings && !inferredTypings[name]) {
|
||||
inferredTypings[name] = packageNameToTypingLocation[name];
|
||||
}
|
||||
}
|
||||
@@ -124,7 +119,7 @@ namespace ts.JsTyping {
|
||||
}
|
||||
|
||||
for (const typing of typingNames) {
|
||||
if (!hasProperty(inferredTypings, typing)) {
|
||||
if (!(typing in inferredTypings)) {
|
||||
inferredTypings[typing] = undefined;
|
||||
}
|
||||
}
|
||||
@@ -139,16 +134,16 @@ namespace ts.JsTyping {
|
||||
const jsonConfig: PackageJson = result.config;
|
||||
filesToWatch.push(jsonPath);
|
||||
if (jsonConfig.dependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.dependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.dependencies));
|
||||
}
|
||||
if (jsonConfig.devDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.devDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.devDependencies));
|
||||
}
|
||||
if (jsonConfig.optionalDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.optionalDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.optionalDependencies));
|
||||
}
|
||||
if (jsonConfig.peerDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.peerDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.peerDependencies));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +162,7 @@ namespace ts.JsTyping {
|
||||
mergeTypings(cleanedTypingNames);
|
||||
}
|
||||
else {
|
||||
mergeTypings(filter(cleanedTypingNames, f => hasProperty(safeList, f)));
|
||||
mergeTypings(filter(cleanedTypingNames, f => f in safeList));
|
||||
}
|
||||
|
||||
const hasJsxFile = forEach(fileNames, f => scriptKindIs(f, /*LanguageServiceHost*/ undefined, ScriptKind.JSX));
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ts.NavigateTo {
|
||||
|
||||
const nameToDeclarations = sourceFile.getNamedDeclarations();
|
||||
for (const name in nameToDeclarations) {
|
||||
const declarations = getProperty(nameToDeclarations, name);
|
||||
const declarations = nameToDeclarations[name];
|
||||
if (declarations) {
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// last portion of the (possibly) dotted name they're searching for.
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace ts.NavigationBar {
|
||||
|
||||
/** Merge declarations of the same kind. */
|
||||
function mergeChildren(children: NavigationBarNode[]): void {
|
||||
const nameToItems: Map<NavigationBarNode | NavigationBarNode[]> = {};
|
||||
const nameToItems = createMap<NavigationBarNode | NavigationBarNode[]>();
|
||||
filterMutate(children, child => {
|
||||
const decl = <Declaration>child.node;
|
||||
const name = decl.name && nodeText(decl.name);
|
||||
@@ -243,7 +243,7 @@ namespace ts.NavigationBar {
|
||||
return true;
|
||||
}
|
||||
|
||||
const itemsWithSameName = getProperty(nameToItems, name);
|
||||
const itemsWithSameName = nameToItems[name];
|
||||
if (!itemsWithSameName) {
|
||||
nameToItems[name] = child;
|
||||
return true;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ts {
|
||||
// we see the name of a module that is used everywhere, or the name of an overload). As
|
||||
// such, we cache the information we compute about the candidate for the life of this
|
||||
// pattern matcher so we don't have to compute it multiple times.
|
||||
const stringToWordSpans: Map<TextSpan[]> = {};
|
||||
const stringToWordSpans = createMap<TextSpan[]>();
|
||||
|
||||
pattern = pattern.trim();
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWordSpans(word: string): TextSpan[] {
|
||||
if (!hasProperty(stringToWordSpans, word)) {
|
||||
if (!(word in stringToWordSpans)) {
|
||||
stringToWordSpans[word] = breakIntoWordSpans(word);
|
||||
}
|
||||
|
||||
|
||||
+66
-32
@@ -281,11 +281,14 @@ namespace ts {
|
||||
let pos = this.pos;
|
||||
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
const processNode = (node: Node) => {
|
||||
if (pos < node.pos) {
|
||||
const isJSDocTagNode = isJSDocTag(node);
|
||||
if (!isJSDocTagNode && pos < node.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
|
||||
}
|
||||
children.push(node);
|
||||
pos = node.end;
|
||||
if (!isJSDocTagNode) {
|
||||
pos = node.end;
|
||||
}
|
||||
};
|
||||
const processNodes = (nodes: NodeArray<Node>) => {
|
||||
if (pos < nodes.pos) {
|
||||
@@ -976,7 +979,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
private computeNamedDeclarations(): Map<Declaration[]> {
|
||||
const result: Map<Declaration[]> = {};
|
||||
const result = createMap<Declaration[]>();
|
||||
|
||||
forEachChild(this, visit);
|
||||
|
||||
@@ -991,7 +994,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDeclarations(name: string) {
|
||||
return getProperty(result, name) || (result[name] = []);
|
||||
return result[name] || (result[name] = []);
|
||||
}
|
||||
|
||||
function getDeclarationName(declaration: Declaration) {
|
||||
@@ -2044,7 +2047,7 @@ namespace ts {
|
||||
fileName?: string;
|
||||
reportDiagnostics?: boolean;
|
||||
moduleName?: string;
|
||||
renamedDependencies?: Map<string>;
|
||||
renamedDependencies?: MapLike<string>;
|
||||
}
|
||||
|
||||
export interface TranspileOutput {
|
||||
@@ -2061,7 +2064,7 @@ namespace ts {
|
||||
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
|
||||
// Lazily create this value to fix module loading errors.
|
||||
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
|
||||
typeof o.type === "object" && !forEachValue(<Map<any>>o.type, v => typeof v !== "number"));
|
||||
typeof o.type === "object" && !forEachProperty(o.type, v => typeof v !== "number"));
|
||||
|
||||
options = clone(options);
|
||||
|
||||
@@ -2077,7 +2080,7 @@ namespace ts {
|
||||
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
|
||||
}
|
||||
else {
|
||||
if (!forEachValue(opt.type, v => v === value)) {
|
||||
if (!forEachProperty(opt.type, v => v === value)) {
|
||||
// Supplied value isn't a valid enum value.
|
||||
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
|
||||
}
|
||||
@@ -2136,7 +2139,9 @@ namespace ts {
|
||||
sourceFile.moduleName = transpileOptions.moduleName;
|
||||
}
|
||||
|
||||
sourceFile.renamedDependencies = transpileOptions.renamedDependencies;
|
||||
if (transpileOptions.renamedDependencies) {
|
||||
sourceFile.renamedDependencies = createMap(transpileOptions.renamedDependencies);
|
||||
}
|
||||
|
||||
const newLine = getNewLineCharacter(options);
|
||||
|
||||
@@ -2262,7 +2267,7 @@ namespace ts {
|
||||
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
|
||||
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
|
||||
// for those settings.
|
||||
const buckets: Map<FileMap<DocumentRegistryEntry>> = {};
|
||||
const buckets = createMap<FileMap<DocumentRegistryEntry>>();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
@@ -2270,7 +2275,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
|
||||
let bucket = lookUp(buckets, key);
|
||||
let bucket = buckets[key];
|
||||
if (!bucket && createIfMissing) {
|
||||
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
|
||||
}
|
||||
@@ -2279,7 +2284,7 @@ namespace ts {
|
||||
|
||||
function reportStats() {
|
||||
const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => {
|
||||
const entries = lookUp(buckets, name);
|
||||
const entries = buckets[name];
|
||||
const sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
entries.forEachValue((key, entry) => {
|
||||
sourceFiles.push({
|
||||
@@ -3119,7 +3124,7 @@ namespace ts {
|
||||
oldSettings.allowJs !== newSettings.allowJs ||
|
||||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit ||
|
||||
oldSettings.baseUrl !== newSettings.baseUrl ||
|
||||
!mapIsEqualTo(oldSettings.paths, newSettings.paths));
|
||||
!equalOwnProperties(oldSettings.paths, newSettings.paths));
|
||||
|
||||
// Now create a new compiler
|
||||
const compilerHost: CompilerHost = {
|
||||
@@ -3134,7 +3139,6 @@ namespace ts {
|
||||
getCurrentDirectory: () => currentDirectory,
|
||||
fileExists: (fileName): boolean => {
|
||||
// stub missing host functionality
|
||||
Debug.assert(!host.resolveModuleNames || !host.resolveTypeReferenceDirectives);
|
||||
return hostCache.getOrCreateEntry(fileName) !== undefined;
|
||||
},
|
||||
readFile: (fileName): string => {
|
||||
@@ -3808,7 +3812,11 @@ namespace ts {
|
||||
// other than those within the declared type.
|
||||
isNewIdentifierLocation = true;
|
||||
|
||||
// If the object literal is being assigned to something of type 'null | { hello: string }',
|
||||
// it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible.
|
||||
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
|
||||
typeForObject = typeForObject && typeForObject.getNonNullableType();
|
||||
|
||||
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
||||
}
|
||||
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
@@ -3820,7 +3828,7 @@ namespace ts {
|
||||
// We don't want to complete using the type acquired by the shape
|
||||
// of the binding pattern; we are only interested in types acquired
|
||||
// through type declaration or inference.
|
||||
// Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed -
|
||||
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
|
||||
// type of parameter will flow in from the contextual type of the function
|
||||
let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type);
|
||||
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
|
||||
@@ -4122,7 +4130,7 @@ namespace ts {
|
||||
* do not occur at the current position and have not otherwise been typed.
|
||||
*/
|
||||
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] {
|
||||
const existingImportsOrExports: Map<boolean> = {};
|
||||
const existingImportsOrExports = createMap<boolean>();
|
||||
|
||||
for (const element of namedImportsOrExports) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
@@ -4134,11 +4142,11 @@ namespace ts {
|
||||
existingImportsOrExports[name.text] = true;
|
||||
}
|
||||
|
||||
if (isEmpty(existingImportsOrExports)) {
|
||||
if (!someProperties(existingImportsOrExports)) {
|
||||
return filter(exportsOfModule, e => e.name !== "default");
|
||||
}
|
||||
|
||||
return filter(exportsOfModule, e => e.name !== "default" && !lookUp(existingImportsOrExports, e.name));
|
||||
return filter(exportsOfModule, e => e.name !== "default" && !existingImportsOrExports[e.name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4152,7 +4160,7 @@ namespace ts {
|
||||
return contextualMemberSymbols;
|
||||
}
|
||||
|
||||
const existingMemberNames: Map<boolean> = {};
|
||||
const existingMemberNames = createMap<boolean>();
|
||||
for (const m of existingMembers) {
|
||||
// Ignore omitted expressions for missing members
|
||||
if (m.kind !== SyntaxKind.PropertyAssignment &&
|
||||
@@ -4185,7 +4193,7 @@ namespace ts {
|
||||
existingMemberNames[existingName] = true;
|
||||
}
|
||||
|
||||
return filter(contextualMemberSymbols, m => !lookUp(existingMemberNames, m.name));
|
||||
return filter(contextualMemberSymbols, m => !existingMemberNames[m.name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4195,7 +4203,7 @@ namespace ts {
|
||||
* do not occur at the current position and have not otherwise been typed.
|
||||
*/
|
||||
function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>): Symbol[] {
|
||||
const seenNames: Map<boolean> = {};
|
||||
const seenNames = createMap<boolean>();
|
||||
for (const attr of attributes) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
if (attr.getStart() <= position && position <= attr.getEnd()) {
|
||||
@@ -4207,7 +4215,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return filter(symbols, a => !lookUp(seenNames, a.name));
|
||||
return filter(symbols, a => !seenNames[a.name]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4267,7 +4275,7 @@ namespace ts {
|
||||
addRange(entries, keywordCompletions);
|
||||
}
|
||||
|
||||
return { isMemberCompletion, isNewIdentifierLocation, entries };
|
||||
return { isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation || isSourceFileJavaScript(sourceFile), entries };
|
||||
|
||||
function getJavaScriptCompletionEntries(sourceFile: SourceFile, position: number, uniqueNames: Map<string>): CompletionEntry[] {
|
||||
const entries: CompletionEntry[] = [];
|
||||
@@ -4337,13 +4345,13 @@ namespace ts {
|
||||
|
||||
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
|
||||
const start = timestamp();
|
||||
const uniqueNames: Map<string> = {};
|
||||
const uniqueNames = createMap<string>();
|
||||
if (symbols) {
|
||||
for (const symbol of symbols) {
|
||||
const entry = createCompletionEntry(symbol, location, performCharacterChecks);
|
||||
if (entry) {
|
||||
const id = escapeIdentifier(entry.name);
|
||||
if (!lookUp(uniqueNames, id)) {
|
||||
if (!uniqueNames[id]) {
|
||||
entries.push(entry);
|
||||
uniqueNames[id] = id;
|
||||
}
|
||||
@@ -4932,6 +4940,28 @@ namespace ts {
|
||||
|
||||
if (!documentation) {
|
||||
documentation = symbol.getDocumentationComment();
|
||||
if (documentation.length === 0 && symbol.flags & SymbolFlags.Property) {
|
||||
// For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo`
|
||||
// there documentation comments might be attached to the right hand side symbol of their declarations.
|
||||
// The pattern of such special property access is that the parent symbol is the symbol of the file.
|
||||
if (symbol.parent && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rhsSymbol = program.getTypeChecker().getSymbolAtLocation((<BinaryExpression>declaration.parent).right);
|
||||
if (!rhsSymbol) {
|
||||
continue;
|
||||
}
|
||||
|
||||
documentation = rhsSymbol.getDocumentationComment();
|
||||
if (documentation.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { displayParts, documentation, symbolKind };
|
||||
@@ -5171,7 +5201,7 @@ namespace ts {
|
||||
// Type reference directives
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const referenceFile = lookUp(program.getResolvedTypeReferenceDirectives(), typeReferenceDirective.fileName);
|
||||
const referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName];
|
||||
if (referenceFile && referenceFile.resolvedFileName) {
|
||||
return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
|
||||
}
|
||||
@@ -5338,12 +5368,12 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const fileNameToDocumentHighlights: Map<DocumentHighlights> = {};
|
||||
const fileNameToDocumentHighlights = createMap<DocumentHighlights>();
|
||||
const result: DocumentHighlights[] = [];
|
||||
for (const referencedSymbol of referencedSymbols) {
|
||||
for (const referenceEntry of referencedSymbol.references) {
|
||||
const fileName = referenceEntry.fileName;
|
||||
let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName);
|
||||
let documentHighlights = fileNameToDocumentHighlights[fileName];
|
||||
if (!documentHighlights) {
|
||||
documentHighlights = { fileName, highlightSpans: [] };
|
||||
|
||||
@@ -6088,7 +6118,7 @@ namespace ts {
|
||||
|
||||
const nameTable = getNameTable(sourceFile);
|
||||
|
||||
if (lookUp(nameTable, internedName) !== undefined) {
|
||||
if (nameTable[internedName] !== undefined) {
|
||||
result = result || [];
|
||||
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
||||
}
|
||||
@@ -6733,7 +6763,7 @@ namespace ts {
|
||||
|
||||
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {});
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6765,7 +6795,7 @@ namespace ts {
|
||||
// the function will add any found symbol of the property-name, then its sub-routine will call
|
||||
// getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already
|
||||
// visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol.
|
||||
if (hasProperty(previousIterationSymbolsCache, symbol.name)) {
|
||||
if (symbol.name in previousIterationSymbolsCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6854,7 +6884,7 @@ namespace ts {
|
||||
// see if any is in the list
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
const result: Symbol[] = [];
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {});
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
|
||||
}
|
||||
|
||||
@@ -7589,6 +7619,10 @@ namespace ts {
|
||||
* False will mean that node is not classified and traverse routine should recurse into node contents.
|
||||
*/
|
||||
function tryClassifyNode(node: Node): boolean {
|
||||
if (isJSDocTag(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nodeIsMissing(node)) {
|
||||
return true;
|
||||
}
|
||||
@@ -8363,7 +8397,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function initializeNameTable(sourceFile: SourceFile): void {
|
||||
const nameTable: Map<number> = {};
|
||||
const nameTable = createMap<number>();
|
||||
|
||||
walk(sourceFile);
|
||||
sourceFile.nameTable = nameTable;
|
||||
|
||||
@@ -314,9 +314,9 @@ namespace ts {
|
||||
// 'in' does not have this effect.
|
||||
if ("getModuleResolutionsForFile" in this.shimHost) {
|
||||
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
|
||||
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
return map(moduleNames, name => {
|
||||
const result = lookUp(resolutionsInFile, name);
|
||||
const result = getProperty(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result } : undefined;
|
||||
});
|
||||
};
|
||||
@@ -326,8 +326,8 @@ namespace ts {
|
||||
}
|
||||
if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) {
|
||||
this.resolveTypeReferenceDirectives = (typeDirectiveNames: string[], containingFile: string) => {
|
||||
const typeDirectivesForFile = <Map<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
|
||||
return map(typeDirectiveNames, name => lookUp(typeDirectivesForFile, name));
|
||||
const typeDirectivesForFile = <MapLike<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
|
||||
return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1222,6 +1222,6 @@ namespace TypeScript.Services {
|
||||
// TODO: it should be moved into a namespace though.
|
||||
|
||||
/* @internal */
|
||||
const toolsVersion = "1.9";
|
||||
const toolsVersion = "2.1";
|
||||
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace ts.SignatureHelp {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
const nameToDeclarations = sourceFile.getNamedDeclarations();
|
||||
const declarations = getProperty(nameToDeclarations, name.text);
|
||||
const declarations = nameToDeclarations[name.text];
|
||||
|
||||
if (declarations) {
|
||||
for (const declaration of declarations) {
|
||||
|
||||
@@ -925,4 +925,25 @@ namespace ts {
|
||||
}
|
||||
return ensureScriptKind(fileName, scriptKind);
|
||||
}
|
||||
|
||||
export function parseAndReEmitConfigJSONFile(content: string) {
|
||||
const options: TranspileOptions = {
|
||||
fileName: "config.js",
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES6,
|
||||
removeComments: true
|
||||
},
|
||||
reportDiagnostics: true
|
||||
};
|
||||
const { outputText, diagnostics } = ts.transpileModule("(" + content + ")", options);
|
||||
// Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1
|
||||
// also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these
|
||||
// as well
|
||||
const trimmedOutput = outputText.trim();
|
||||
const configJsonObject = JSON.parse(trimmedOutput.substring(1, trimmedOutput.length - 2));
|
||||
for (const diagnostic of diagnostics) {
|
||||
diagnostic.start = diagnostic.start - 1;
|
||||
}
|
||||
return { configJsonObject, diagnostics };
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ declare var path: any;
|
||||
import * as ts from "typescript";
|
||||
|
||||
function watch(rootFileNames: string[], options: ts.CompilerOptions) {
|
||||
const files: ts.Map<{ version: number }> = {};
|
||||
const files: ts.MapLike<{ version: number }> = {};
|
||||
|
||||
// initialize the list of files
|
||||
rootFileNames.forEach(fileName => {
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts(1,16): error TS7005: Variable '"jquery"' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts (1 errors) ====
|
||||
declare module "jquery";
|
||||
~~~~~~~~
|
||||
!!! error TS7005: Variable '"jquery"' implicitly has an 'any' type.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
//// [ambientShorthand_isImplicitAny.ts]
|
||||
declare module "jquery";
|
||||
|
||||
|
||||
//// [ambientShorthand_isImplicitAny.js]
|
||||
@@ -1,6 +1,7 @@
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts(9,7): error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts (1 errors) ====
|
||||
@@ -17,6 +18,7 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtypi
|
||||
!!! error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: String;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSuperty
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'U' is not assignable to type 'string'.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSupertype.ts (1 errors) ====
|
||||
@@ -19,5 +20,6 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSuperty
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'U' is not assignable to type 'string'.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: U;
|
||||
}
|
||||
@@ -39,8 +39,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'.
|
||||
Property 'length' is missing in type '{ 0: string; 1: number; }'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(29,5): error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
@@ -136,8 +135,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error
|
||||
var n1: [number, string] = x;
|
||||
~~
|
||||
!!! error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
var n2: [number, string] = y;
|
||||
~~
|
||||
!!! error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(10,5): error TS2322: Type 'undefined[]' is not assignable to type '[any, any, any]'.
|
||||
Property '0' is missing in type 'undefined[]'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,5): error TS2322: Type '[string, number, boolean]' is not assignable to type '[boolean, string, number]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'boolean'.
|
||||
Type 'string' is not assignable to type 'boolean'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'.
|
||||
Types of property 'pop' are incompatible.
|
||||
Type '() => string | number | boolean' is not assignable to type '() => number'.
|
||||
@@ -18,6 +17,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
Types of parameters 'items' and 'items' are incompatible.
|
||||
Type 'Number' is not assignable to type 'string | number'.
|
||||
Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts (6 errors) ====
|
||||
@@ -37,8 +37,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
var a1: [boolean, string, number] = ["string", 1, true]; // Error
|
||||
~~
|
||||
!!! error TS2322: Type '[string, number, boolean]' is not assignable to type '[boolean, string, number]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
|
||||
// The resulting type an array literal expression is determined as follows:
|
||||
// - If the array literal contains no spread elements and is an array assignment pattern in a destructuring assignment (section 4.17.1),
|
||||
@@ -81,4 +80,5 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
!!! error TS2322: Types of parameters 'items' and 'items' are incompatible.
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'string | number'.
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
Property 'b' is missing in type 'A'.
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts (2 errors) ====
|
||||
class A { a }
|
||||
class B extends A { b }
|
||||
class C<T> extends Array<T> { c }
|
||||
declare var ara: A[];
|
||||
declare var arb: B[];
|
||||
declare var cra: C<A>;
|
||||
declare var crb: C<B>;
|
||||
declare var rra: ReadonlyArray<A>;
|
||||
declare var rrb: ReadonlyArray<B>;
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
~~~
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
!!! error TS2322: Property 'b' is missing in type 'A'.
|
||||
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
~~~
|
||||
!!! error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//// [arrayOfSubtypeIsAssignableToReadonlyArray.ts]
|
||||
class A { a }
|
||||
class B extends A { b }
|
||||
class C<T> extends Array<T> { c }
|
||||
declare var ara: A[];
|
||||
declare var arb: B[];
|
||||
declare var cra: C<A>;
|
||||
declare var crb: C<B>;
|
||||
declare var rra: ReadonlyArray<A>;
|
||||
declare var rrb: ReadonlyArray<B>;
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
|
||||
|
||||
//// [arrayOfSubtypeIsAssignableToReadonlyArray.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = (function (_super) {
|
||||
__extends(B, _super);
|
||||
function B() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return B;
|
||||
}(A));
|
||||
var C = (function (_super) {
|
||||
__extends(C, _super);
|
||||
function C() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return C;
|
||||
}(Array));
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts(3,1): error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts(3
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
a = x;
|
||||
@@ -3,6 +3,7 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(
|
||||
Type '() => Object' is not assignable to type '() => boolean'.
|
||||
Type 'Object' is not assignable to type 'boolean'.
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(19,1): error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(20,1): error TS2322: Type 'NotBoolean' is not assignable to type 'boolean'.
|
||||
|
||||
|
||||
@@ -33,6 +34,7 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotBoolean' is not assignable to type 'boolean'.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts(3,1): error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts(3,1
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
a = x;
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(24,1): error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(25,1): error TS2322: Type 'NotNumber' is not assignable to type 'number'.
|
||||
|
||||
|
||||
@@ -29,6 +30,7 @@ tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(25
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotNumber' is not assignable to type 'number'.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts(3,1): error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts(3,1
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2322: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
a = x;
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(47,1): error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(48,1): error TS2322: Type 'NotString' is not assignable to type 'string'.
|
||||
|
||||
|
||||
@@ -52,6 +53,7 @@ tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(48
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2322: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotString' is not assignable to type 'string'.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//// [await_unaryExpression_es6.ts]
|
||||
|
||||
async function bar() {
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
+await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
-await 42; // OK
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
~await 42; // OK
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
!(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
+(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
-(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
~(yield 42); // OK
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : Symbol(bar, Decl(await_unaryExpression_es6.ts, 0, 0))
|
||||
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6.ts, 3, 1))
|
||||
|
||||
+await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6.ts, 7, 1))
|
||||
|
||||
-await 42; // OK
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : Symbol(bar4, Decl(await_unaryExpression_es6.ts, 11, 1))
|
||||
|
||||
~await 42; // OK
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : () => Promise<void>
|
||||
|
||||
!await 42; // OK
|
||||
>!await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
+await 42; // OK
|
||||
>+await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
-await 42; // OK
|
||||
>-await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : () => Promise<void>
|
||||
|
||||
~await 42; // OK
|
||||
>~await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//// [await_unaryExpression_es6_1.ts]
|
||||
|
||||
async function bar() {
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
void await 42;
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
+await 42;
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_1.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
!(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
void (yield 42);
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
+(yield 42);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_1.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : Symbol(bar, Decl(await_unaryExpression_es6_1.ts, 0, 0))
|
||||
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6_1.ts, 3, 1))
|
||||
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : Symbol(bar2, Decl(await_unaryExpression_es6_1.ts, 7, 1))
|
||||
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6_1.ts, 11, 1))
|
||||
|
||||
void await 42;
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : Symbol(bar4, Decl(await_unaryExpression_es6_1.ts, 15, 1))
|
||||
|
||||
+await 42;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_1.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : () => Promise<void>
|
||||
|
||||
!await 42; // OK
|
||||
>!await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
delete await 42; // OK
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : () => Promise<void>
|
||||
|
||||
delete await 42; // OK
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
void await 42;
|
||||
>void await 42 : undefined
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : () => Promise<void>
|
||||
|
||||
+await 42;
|
||||
>+await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//// [await_unaryExpression_es6_2.ts]
|
||||
|
||||
async function bar1() {
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
void await 42;
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_2.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42);
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42);
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
void (yield 42);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_2.ts ===
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6_2.ts, 0, 0))
|
||||
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : Symbol(bar2, Decl(await_unaryExpression_es6_2.ts, 3, 1))
|
||||
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6_2.ts, 7, 1))
|
||||
|
||||
void await 42;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_2.ts ===
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
delete await 42;
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : () => Promise<void>
|
||||
|
||||
delete await 42;
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
void await 42;
|
||||
>void await 42 : undefined
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts(3,7): error TS1109: Expression expected.
|
||||
tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts(7,7): error TS1109: Expression expected.
|
||||
|
||||
|
||||
==== tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts (2 errors) ====
|
||||
|
||||
async function bar1() {
|
||||
++await 42; // Error
|
||||
~~~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
--await 42; // Error
|
||||
~~~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
var x = 42;
|
||||
await x++; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
var x = 42;
|
||||
await x--; // OK but shouldn't need parenthesis
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//// [await_unaryExpression_es6_3.ts]
|
||||
|
||||
async function bar1() {
|
||||
++await 42; // Error
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
--await 42; // Error
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
var x = 42;
|
||||
await x++; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
var x = 42;
|
||||
await x--; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_3.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
++;
|
||||
yield 42; // Error
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
--;
|
||||
yield 42; // Error
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var x = 42;
|
||||
yield x++; // OK but shouldn't need parenthesis
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var x = 42;
|
||||
yield x--; // OK but shouldn't need parenthesis
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//// [castOfAwait.ts]
|
||||
async function f() {
|
||||
<number> await 0;
|
||||
typeof await 0;
|
||||
void await 0;
|
||||
await void <string> typeof <number> void await 0;
|
||||
await await 0;
|
||||
}
|
||||
|
||||
|
||||
//// [castOfAwait.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield 0;
|
||||
typeof (yield 0);
|
||||
void (yield 0);
|
||||
yield void typeof void (yield 0);
|
||||
yield yield 0;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/castOfAwait.ts ===
|
||||
async function f() {
|
||||
>f : Symbol(f, Decl(castOfAwait.ts, 0, 0))
|
||||
|
||||
<number> await 0;
|
||||
typeof await 0;
|
||||
void await 0;
|
||||
await void <string> typeof <number> void await 0;
|
||||
await await 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
=== tests/cases/compiler/castOfAwait.ts ===
|
||||
async function f() {
|
||||
>f : () => Promise<void>
|
||||
|
||||
<number> await 0;
|
||||
><number> await 0 : number
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
typeof await 0;
|
||||
>typeof await 0 : string
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
void await 0;
|
||||
>void await 0 : undefined
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
await void <string> typeof <number> void await 0;
|
||||
>await void <string> typeof <number> void await 0 : any
|
||||
>void <string> typeof <number> void await 0 : undefined
|
||||
><string> typeof <number> void await 0 : string
|
||||
>typeof <number> void await 0 : string
|
||||
><number> void await 0 : number
|
||||
>void await 0 : undefined
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
await await 0;
|
||||
>await await 0 : number
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
tests/cases/compiler/castOfYield.ts(4,14): error TS1109: Expression expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/castOfYield.ts (1 errors) ====
|
||||
function* f() {
|
||||
<number> (yield 0);
|
||||
// Unlike await, yield is not allowed to appear in a simple unary expression.
|
||||
<number> yield 0;
|
||||
~~~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
//// [castOfYield.ts]
|
||||
function* f() {
|
||||
<number> (yield 0);
|
||||
// Unlike await, yield is not allowed to appear in a simple unary expression.
|
||||
<number> yield 0;
|
||||
}
|
||||
|
||||
|
||||
//// [castOfYield.js]
|
||||
function f() {
|
||||
(yield 0);
|
||||
// Unlike await, yield is not allowed to appear in a simple unary expression.
|
||||
;
|
||||
yield 0;
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'.
|
||||
Types of property '1' are incompatible.
|
||||
Type 'string' is not comparable to type 'number'.
|
||||
Type 'string' is not comparable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'C' is not comparable to type 'A'.
|
||||
Property 'a' is missing in type 'C'.
|
||||
Type 'C' is not comparable to type 'A'.
|
||||
Property 'a' is missing in type 'C'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'.
|
||||
|
||||
@@ -40,14 +38,12 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot
|
||||
var t3 = <[number, number]>numStrTuple;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'.
|
||||
!!! error TS2352: Types of property '1' are incompatible.
|
||||
!!! error TS2352: Type 'string' is not comparable to type 'number'.
|
||||
!!! error TS2352: Type 'string' is not comparable to type 'number'.
|
||||
var t9 = <[A, I]>classCDTuple;
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'.
|
||||
!!! error TS2352: Types of property '0' are incompatible.
|
||||
!!! error TS2352: Type 'C' is not comparable to type 'A'.
|
||||
!!! error TS2352: Property 'a' is missing in type 'C'.
|
||||
!!! error TS2352: Type 'C' is not comparable to type 'A'.
|
||||
!!! error TS2352: Property 'a' is missing in type 'C'.
|
||||
var array1 = <number[]>numStrTuple;
|
||||
~~~~~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'.
|
||||
|
||||
@@ -13,14 +13,14 @@ let C = class extends class extends class {
|
||||
}
|
||||
}
|
||||
{
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.b = 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.c = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(3,5): error TS232
|
||||
Type 'true' is not assignable to type 'string | number'.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(15,1): error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS2322: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type '{}' is not assignable to type '{ a: string; }'.
|
||||
Property 'a' is missing in type '{}'.
|
||||
Type '{}' is not assignable to type '{ a: string; }'.
|
||||
Property 'a' is missing in type '{}'.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(19,1): error TS2322: Type '[number, string]' is not assignable to type '[number, string, boolean]'.
|
||||
Property '2' is missing in type '[number, string]'.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(20,5): error TS2322: Type '[string, string, number]' is not assignable to type '[string, string]'.
|
||||
@@ -18,9 +17,8 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(20,5): error TS23
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(24,1): error TS2322: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'.
|
||||
Property '2' is missing in type '[C, string | number]'.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
|
||||
Types of property '1' are incompatible.
|
||||
Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (7 errors) ====
|
||||
@@ -52,9 +50,8 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23
|
||||
objNumTuple = [ {}, 5];
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type '{}' is not assignable to type '{ a: string; }'.
|
||||
!!! error TS2322: Property 'a' is missing in type '{}'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type '{ a: string; }'.
|
||||
!!! error TS2322: Property 'a' is missing in type '{}'.
|
||||
numStrBoolTuple = numStrTuple;
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '[number, string]' is not assignable to type '[number, string, boolean]'.
|
||||
@@ -76,6 +73,5 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23
|
||||
numStrTuple = unionTuple3;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Types of property '1' are incompatible.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
@@ -11,8 +11,7 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(21,14): error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
|
||||
|
||||
@@ -57,8 +56,7 @@ tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTyp
|
||||
function g({ prop = [101, 1234] }: Tuples) {}
|
||||
~~~~
|
||||
!!! error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface StringUnion {
|
||||
prop: "foo" | "bar";
|
||||
|
||||
@@ -64,9 +64,9 @@ if (isNodeList(sourceObj)) {
|
||||
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
>sourceObj.length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27))
|
||||
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
|
||||
>length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
>length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27))
|
||||
}
|
||||
|
||||
if (isHTMLCollection(sourceObj)) {
|
||||
@@ -74,9 +74,9 @@ if (isHTMLCollection(sourceObj)) {
|
||||
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
>sourceObj.length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
|
||||
>length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
>length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33))
|
||||
}
|
||||
|
||||
if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
|
||||
|
||||
@@ -80,7 +80,7 @@ if (isNodeList(sourceObj)) {
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
>sourceObj : NodeList | HTMLCollection
|
||||
>sourceObj : NodeList
|
||||
>length : number
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ if (isHTMLCollection(sourceObj)) {
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
>sourceObj : NodeList | HTMLCollection
|
||||
>sourceObj : HTMLCollection
|
||||
>length : number
|
||||
}
|
||||
|
||||
@@ -102,11 +102,11 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
|
||||
>sourceObj : EventTargetLike
|
||||
>isHTMLCollection(sourceObj) : boolean
|
||||
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
|
||||
>sourceObj : { a: string; }
|
||||
>sourceObj : HTMLCollection | { a: string; }
|
||||
|
||||
sourceObj.length;
|
||||
>sourceObj.length : number
|
||||
>sourceObj : NodeList | HTMLCollection | ({ a: string; } & HTMLCollection)
|
||||
>sourceObj : NodeList | HTMLCollection
|
||||
>length : number
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,22 @@ function b() {
|
||||
}
|
||||
x; // string
|
||||
}
|
||||
function c<T>(data: string | T): T {
|
||||
if (typeof data === 'string') {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
function d<T extends string>(data: string | T): never {
|
||||
if (typeof data === 'string') {
|
||||
throw new Error('will always happen');
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [controlFlowIfStatement.js]
|
||||
@@ -72,3 +88,19 @@ function b() {
|
||||
}
|
||||
x; // string
|
||||
}
|
||||
function c(data) {
|
||||
if (typeof data === 'string') {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
function d(data) {
|
||||
if (typeof data === 'string') {
|
||||
throw new Error('will always happen');
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,4 +71,42 @@ function b() {
|
||||
x; // string
|
||||
>x : Symbol(x, Decl(controlFlowIfStatement.ts, 26, 7))
|
||||
}
|
||||
function c<T>(data: string | T): T {
|
||||
>c : Symbol(c, Decl(controlFlowIfStatement.ts, 35, 1))
|
||||
>T : Symbol(T, Decl(controlFlowIfStatement.ts, 36, 11))
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 36, 14))
|
||||
>T : Symbol(T, Decl(controlFlowIfStatement.ts, 36, 11))
|
||||
>T : Symbol(T, Decl(controlFlowIfStatement.ts, 36, 11))
|
||||
|
||||
if (typeof data === 'string') {
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 36, 14))
|
||||
|
||||
return JSON.parse(data);
|
||||
>JSON.parse : Symbol(JSON.parse, Decl(lib.d.ts, --, --))
|
||||
>JSON : Symbol(JSON, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>parse : Symbol(JSON.parse, Decl(lib.d.ts, --, --))
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 36, 14))
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 36, 14))
|
||||
}
|
||||
}
|
||||
function d<T extends string>(data: string | T): never {
|
||||
>d : Symbol(d, Decl(controlFlowIfStatement.ts, 43, 1))
|
||||
>T : Symbol(T, Decl(controlFlowIfStatement.ts, 44, 11))
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 44, 29))
|
||||
>T : Symbol(T, Decl(controlFlowIfStatement.ts, 44, 11))
|
||||
|
||||
if (typeof data === 'string') {
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 44, 29))
|
||||
|
||||
throw new Error('will always happen');
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
>data : Symbol(data, Decl(controlFlowIfStatement.ts, 44, 29))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,4 +90,51 @@ function b() {
|
||||
x; // string
|
||||
>x : string
|
||||
}
|
||||
function c<T>(data: string | T): T {
|
||||
>c : <T>(data: string | T) => T
|
||||
>T : T
|
||||
>data : string | T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
if (typeof data === 'string') {
|
||||
>typeof data === 'string' : boolean
|
||||
>typeof data : string
|
||||
>data : string | T
|
||||
>'string' : "string"
|
||||
|
||||
return JSON.parse(data);
|
||||
>JSON.parse(data) : any
|
||||
>JSON.parse : (text: string, reviver?: (key: any, value: any) => any) => any
|
||||
>JSON : JSON
|
||||
>parse : (text: string, reviver?: (key: any, value: any) => any) => any
|
||||
>data : string
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
>data : T
|
||||
}
|
||||
}
|
||||
function d<T extends string>(data: string | T): never {
|
||||
>d : <T extends string>(data: string | T) => never
|
||||
>T : T
|
||||
>data : string | T
|
||||
>T : T
|
||||
|
||||
if (typeof data === 'string') {
|
||||
>typeof data === 'string' : boolean
|
||||
>typeof data : string
|
||||
>data : string | T
|
||||
>'string' : "string"
|
||||
|
||||
throw new Error('will always happen');
|
||||
>new Error('will always happen') : Error
|
||||
>Error : ErrorConstructor
|
||||
>'will always happen' : string
|
||||
}
|
||||
else {
|
||||
return data;
|
||||
>data : never
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user