Merge remote-tracking branch 'origin/master' into import_completions_pr

This commit is contained in:
Richard Knoll 2016-08-15 15:20:22 -07:00
commit cc35bd5dca
314 changed files with 8832 additions and 29228 deletions

View file

@ -7,19 +7,33 @@ node_js:
sudo: false sudo: false
os: env:
- linux - workerCount=3
- osx
matrix: matrix:
fast_finish: true fast_finish: true
exclude: include:
- os: osx - os: osx
node_js: '4' node_js: stable
osx_image: xcode7.3
env: workerCount=2
allow_failures:
- os: osx - os: osx
node_js: '0.10'
branches: branches:
only: only:
- master - master
- transforms - transforms
install:
- npm uninstall typescript
- npm uninstall tslint
- npm install
- npm update
cache:
directories:
- node_modules
git:
depth: 1

View file

@ -34,7 +34,7 @@ import through2 = require("through2");
import merge2 = require("merge2"); import merge2 = require("merge2");
import intoStream = require("into-stream"); import intoStream = require("into-stream");
import * as os from "os"; import * as os from "os";
import Linter = require("tslint"); import fold = require("travis-fold");
const gulp = helpMaker(originalGulp); const gulp = helpMaker(originalGulp);
const mochaParallel = require("./scripts/mocha-parallel.js"); const mochaParallel = require("./scripts/mocha-parallel.js");
const {runTestsInParallel} = mochaParallel; const {runTestsInParallel} = mochaParallel;
@ -59,7 +59,6 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
browser: process.env.browser || process.env.b || "IE", browser: process.env.browser || process.env.b || "IE",
tests: process.env.test || process.env.tests || process.env.t, tests: process.env.test || process.env.tests || process.env.t,
light: process.env.light || false, light: process.env.light || false,
port: process.env.port || process.env.p || "8888",
reporter: process.env.reporter || process.env.r, reporter: process.env.reporter || process.env.r,
lint: process.env.lint || true, lint: process.env.lint || true,
files: process.env.f || process.env.file || process.env.files || "", files: process.env.f || process.env.file || process.env.files || "",
@ -450,7 +449,7 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
}); });
gulp.task("lssl", "Builds language service server library", [tsserverLibraryFile]); gulp.task("lssl", "Builds language service server library", [tsserverLibraryFile]);
gulp.task("local", "Builds the full compiler and services", [builtLocalCompiler, servicesFile, serverFile, builtGeneratedDiagnosticMessagesJSON]); gulp.task("local", "Builds the full compiler and services", [builtLocalCompiler, servicesFile, serverFile, builtGeneratedDiagnosticMessagesJSON, tsserverLibraryFile]);
gulp.task("tsc", "Builds only the compiler", [builtLocalCompiler]); gulp.task("tsc", "Builds only the compiler", [builtLocalCompiler]);
@ -504,7 +503,7 @@ gulp.task("VerifyLKG", false, [], () => {
return gulp.src(expectedFiles).pipe(gulp.dest(LKGDirectory)); return gulp.src(expectedFiles).pipe(gulp.dest(LKGDirectory));
}); });
gulp.task("LKGInternal", false, ["lib", "local", "lssl"]); gulp.task("LKGInternal", false, ["lib", "local"]);
gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUseDebugMode"], () => { gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUseDebugMode"], () => {
return runSequence("LKGInternal", "VerifyLKG"); return runSequence("LKGInternal", "VerifyLKG");
@ -766,7 +765,7 @@ function writeTestConfigFile(tests: string, light: boolean, taskConfigsFolder?:
} }
gulp.task("runtests-browser", "Runs the tests using the built run.js file like 'gulp runtests'. Syntax is gulp runtests-browser. Additional optional parameters --tests=[regex], --port=, --browser=[chrome|IE]", ["browserify", nodeServerOutFile], (done) => { gulp.task("runtests-browser", "Runs the tests using the built run.js file like 'gulp runtests'. Syntax is gulp runtests-browser. Additional optional parameters --tests=[regex], --browser=[chrome|IE]", ["browserify", nodeServerOutFile], (done) => {
cleanTestDirs((err) => { cleanTestDirs((err) => {
if (err) { console.error(err); done(err); process.exit(1); } if (err) { console.error(err); done(err); process.exit(1); }
host = "node"; host = "node";
@ -781,9 +780,6 @@ gulp.task("runtests-browser", "Runs the tests using the built run.js file like '
} }
const args = [nodeServerOutFile]; const args = [nodeServerOutFile];
if (cmdLineOptions["port"]) {
args.push(cmdLineOptions["port"]);
}
if (cmdLineOptions["browser"]) { if (cmdLineOptions["browser"]) {
args.push(cmdLineOptions["browser"]); args.push(cmdLineOptions["browser"]);
} }
@ -932,26 +928,6 @@ gulp.task("build-rules", "Compiles tslint rules to js", () => {
.pipe(gulp.dest(dest)); .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 = [ const lintTargets = [
"Gulpfile.ts", "Gulpfile.ts",
"src/compiler/**/*.ts", "src/compiler/**/*.ts",
@ -960,29 +936,75 @@ const lintTargets = [
"src/server/**/*.ts", "src/server/**/*.ts",
"scripts/tslint/**/*.ts", "scripts/tslint/**/*.ts",
"src/services/**/*.ts", "src/services/**/*.ts",
"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"], () => { gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
const fileMatcher = RegExp(cmdLineOptions["files"]); const fileMatcher = RegExp(cmdLineOptions["files"]);
const lintOptions = getLinterOptions(); if (fold.isTravis()) console.log(fold.start("lint"));
let failed = 0;
return gulp.src(lintTargets) let files: {stat: fs.Stats, path: string}[] = [];
.pipe(insert.transform((contents, file) => { return gulp.src(lintTargets, { read: false })
if (!fileMatcher.test(file.path)) return contents; .pipe(through2.obj((chunk, enc, cb) => {
const result = lintFile(lintOptions, file.path); files.push(chunk);
if (result.failureCount > 0) { cb();
console.log(result.output); }, (cb) => {
failed += result.failureCount; 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
})) let completed = 0;
.on("end", () => { let failures = 0;
if (failed > 0) { function finished(fails) {
console.error("Linter errors."); completed++;
process.exit(1); failures += fails;
if (completed === workerCount) {
if (fold.isTravis()) console.log(fold.end("lint"));
if (failures > 0) {
throw new Error(`Linter errors: ${failures}`);
}
else {
cb();
}
}
} }
}); }));
}); });

View file

@ -4,7 +4,7 @@ var fs = require("fs");
var os = require("os"); var os = require("os");
var path = require("path"); var path = require("path");
var child_process = require("child_process"); var child_process = require("child_process");
var Linter = require("tslint"); var fold = require("travis-fold");
var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel; var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
// Variables // Variables
@ -32,6 +32,28 @@ 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 = [ var compilerSources = [
"core.ts", "core.ts",
"performance.ts", "performance.ts",
@ -285,6 +307,7 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
*/ */
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts, callback) { function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts, callback) {
file(outFile, prereqs, function() { file(outFile, prereqs, function() {
var startCompileTime = mark();
opts = opts || {}; opts = opts || {};
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler; var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler;
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types " var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
@ -361,11 +384,13 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
callback(); callback();
} }
measure(startCompileTime);
complete(); complete();
}); });
ex.addListener("error", function() { ex.addListener("error", function() {
fs.unlinkSync(outFile); fs.unlinkSync(outFile);
fail("Compilation of " + outFile + " unsuccessful"); fail("Compilation of " + outFile + " unsuccessful");
measure(startCompileTime);
}); });
ex.run(); ex.run();
}, {async: true}); }, {async: true});
@ -551,7 +576,7 @@ var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibr
compileFile( compileFile(
tsserverLibraryFile, tsserverLibraryFile,
languageServiceLibrarySources, languageServiceLibrarySources,
[builtLocalDirectory, copyright].concat(languageServiceLibrarySources), [builtLocalDirectory, copyright, builtLocalCompiler].concat(languageServiceLibrarySources).concat(libraryTargets),
/*prefixes*/ [copyright], /*prefixes*/ [copyright],
/*useBuiltCompiler*/ true, /*useBuiltCompiler*/ true,
{ noOutFile: false, generateDeclarations: true }); { noOutFile: false, generateDeclarations: true });
@ -560,9 +585,19 @@ compileFile(
desc("Builds language service server library"); desc("Builds language service server library");
task("lssl", [tsserverLibraryFile, tsserverLibraryDefinitionFile]); 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 // Local target to build the compiler and services
desc("Builds the full compiler and services"); desc("Builds the full compiler and services");
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON]); task("local", ["build-fold-start", "generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON, "lssl", "build-fold-end"]);
// Local target to build only tsc.js // Local target to build only tsc.js
desc("Builds only the compiler"); desc("Builds only the compiler");
@ -617,7 +652,7 @@ 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 // 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"); desc("Makes a new LKG out of the built js files");
task("LKG", ["clean", "release", "local", "lssl"].concat(libraryTargets), function() { task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile].concat(libraryTargets); var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile].concat(libraryTargets);
var missingFiles = expectedFiles.filter(function (f) { var missingFiles = expectedFiles.filter(function (f) {
return !fs.existsSync(f); return !fs.existsSync(f);
@ -758,6 +793,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally // 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 // 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 + '"' : ''; tests = tests ? ' -g "' + tests + '"' : '';
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run; var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
console.log(cmd); console.log(cmd);
@ -766,10 +802,12 @@ function runConsoleTests(defaultReporter, runInParallel) {
process.env.NODE_ENV = "development"; process.env.NODE_ENV = "development";
exec(cmd, function () { exec(cmd, function () {
process.env.NODE_ENV = savedNodeEnv; process.env.NODE_ENV = savedNodeEnv;
measure(startTime);
runLinter(); runLinter();
finish(); finish();
}, function(e, status) { }, function(e, status) {
process.env.NODE_ENV = savedNodeEnv; process.env.NODE_ENV = savedNodeEnv;
measure(startTime);
finish(status); finish(status);
}); });
@ -777,9 +815,10 @@ function runConsoleTests(defaultReporter, runInParallel) {
else { else {
var savedNodeEnv = process.env.NODE_ENV; var savedNodeEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "development"; process.env.NODE_ENV = "development";
var startTime = mark();
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) { runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
process.env.NODE_ENV = savedNodeEnv; process.env.NODE_ENV = savedNodeEnv;
measure(startTime);
// last worker clean everything and runs linter in case if there were no errors // last worker clean everything and runs linter in case if there were no errors
deleteTemporaryProjectOutput(); deleteTemporaryProjectOutput();
jake.rmRf(taskConfigsFolder); jake.rmRf(taskConfigsFolder);
@ -847,11 +886,10 @@ task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function()
exec(cmd); 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], port=, browser=[chrome|IE]"); 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(); cleanTestDirs();
host = "node"; host = "node";
port = process.env.port || process.env.p || '8888';
browser = process.env.browser || process.env.b || "IE"; browser = process.env.browser || process.env.b || "IE";
tests = process.env.test || process.env.tests || process.env.t; tests = process.env.test || process.env.tests || process.env.t;
var light = process.env.light || false; var light = process.env.light || false;
@ -864,7 +902,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi
} }
tests = tests ? tests : ''; tests = tests ? tests : '';
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + JSON.stringify(tests); var cmd = host + " tests/webTestServer.js " + browser + " " + JSON.stringify(tests);
console.log(cmd); console.log(cmd);
exec(cmd); exec(cmd);
}, {async: true}); }, {async: true});
@ -999,41 +1037,21 @@ var tslintRulesOutFiles = tslintRules.map(function(p) {
return path.join(builtLocalDirectory, "tslint", p + ".js"); return path.join(builtLocalDirectory, "tslint", p + ".js");
}); });
desc("Compiles tslint rules to js"); desc("Compiles tslint rules to js");
task("build-rules", tslintRulesOutFiles); task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
tslintRulesFiles.forEach(function(ruleFile, i) { tslintRulesFiles.forEach(function(ruleFile, i) {
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, 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() { desc("Emit the start of the build-rules fold");
return { task("build-rules-start", [] , function() {
configuration: require("./tslint.json"), if (fold.isTravis()) console.log(fold.start("build-rules"));
formatter: "prose", });
formattersDirectory: undefined,
rulesDirectory: "built/local/tslint"
};
}
function lintFileContents(options, path, contents) { desc("Emit the end of the build-rules fold");
var ll = new Linter(path, contents, options); task("build-rules-end", [] , function() {
console.log("Linting '" + path + "'."); if (fold.isTravis()) console.log(fold.end("build-rules"));
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);
});
}
var lintTargets = compilerSources var lintTargets = compilerSources
.concat(harnessSources) .concat(harnessSources)
@ -1042,73 +1060,81 @@ var lintTargets = compilerSources
.concat(serverCoreSources) .concat(serverCoreSources)
.concat(tslintRulesFiles) .concat(tslintRulesFiles)
.concat(servicesSources) .concat(servicesSources)
.concat(["Gulpfile.ts"]); .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"); desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
task("lint", ["build-rules"], function() { task("lint", ["build-rules"], function() {
var lintOptions = getLinterOptions(); if (fold.isTravis()) console.log(fold.start("lint"));
var startTime = mark();
var failed = 0; var failed = 0;
var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || ""); var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || "");
var done = {}; var done = {};
for (var i in lintTargets) { for (var i in lintTargets) {
var target = lintTargets[i]; var target = lintTargets[i];
if (!done[target] && fileMatcher.test(target)) { if (!done[target] && fileMatcher.test(target)) {
var result = lintFile(lintOptions, target); done[target] = fs.statSync(target).size;
if (result.failureCount > 0) {
console.log(result.output);
failed += result.failureCount;
}
done[target] = true;
} }
} }
if (failed > 0) {
fail('Linter errors.', failed);
}
});
/** var workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
* 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 = {};
function lintWatchFile(filename) { var names = Object.keys(done).sort(function(namea, nameb) {
fs.watch(filename, {persistent: true}, function(event) { return done[namea] - done[nameb];
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.");
}
});
}
}); });
}
desc("Watches files for changes to rerun a lint pass"); for (var i = 0; i < workerCount; i++) {
task("lint-server", ["build-rules"], function() { spawnLintWorker(names, finished);
console.log("Watching ./src for changes to linted files");
for (var i = 0; i < lintTargets.length; i++) {
lintWatchFile(lintTargets[i]);
} }
});
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});

View file

@ -30,8 +30,8 @@
}, },
"devDependencies": { "devDependencies": {
"@types/browserify": "latest", "@types/browserify": "latest",
"@types/convert-source-map": "latest",
"@types/chai": "latest", "@types/chai": "latest",
"@types/convert-source-map": "latest",
"@types/del": "latest", "@types/del": "latest",
"@types/glob": "latest", "@types/glob": "latest",
"@types/gulp": "latest", "@types/gulp": "latest",
@ -72,13 +72,14 @@
"run-sequence": "latest", "run-sequence": "latest",
"sorcery": "latest", "sorcery": "latest",
"through2": "latest", "through2": "latest",
"travis-fold": "latest",
"ts-node": "latest", "ts-node": "latest",
"tslint": "next", "tslint": "next",
"typescript": "next" "typescript": "next"
}, },
"scripts": { "scripts": {
"pretest": "jake tests", "pretest": "jake tests",
"test": "jake runtests", "test": "jake runtests-parallel",
"build": "npm run build:compiler && npm run build:tests", "build": "npm run build:compiler && npm run build:tests",
"build:compiler": "jake local", "build:compiler": "jake local",
"build:tests": "jake tests", "build:tests": "jake tests",

45
scripts/parallel-lint.js Normal file
View file

@ -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;
}
});

View file

@ -69,7 +69,7 @@ function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosti
} }
function buildUniqueNameMap(names: string[]): ts.Map<string> { 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); var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);

View file

@ -1,7 +1,6 @@
import * as Lint from "tslint/lib/lint"; import * as Lint from "tslint/lib/lint";
import * as ts from "typescript"; import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule { 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.`; 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 { class PreferConstWalker extends Lint.RuleWalker {
private inScopeLetDeclarations: ts.Map<DeclarationUsages>[] = []; private inScopeLetDeclarations: ts.MapLike<DeclarationUsages>[] = [];
private errors: Lint.RuleFailure[] = []; private errors: Lint.RuleFailure[] = [];
private markAssignment(identifier: ts.Identifier) { private markAssignment(identifier: ts.Identifier) {
const name = identifier.text; const name = identifier.text;
@ -172,7 +171,7 @@ class PreferConstWalker extends Lint.RuleWalker {
} }
private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) { private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) {
const names: ts.Map<DeclarationUsages> = {}; const names: ts.MapLike<DeclarationUsages> = {};
if (isLet(node.initializer)) { if (isLet(node.initializer)) {
if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) {
this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names); this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names);
@ -194,7 +193,7 @@ class PreferConstWalker extends Lint.RuleWalker {
} }
visitBlock(node: ts.Block) { visitBlock(node: ts.Block) {
const names: ts.Map<DeclarationUsages> = {}; const names: ts.MapLike<DeclarationUsages> = {};
for (const statement of node.statements) { for (const statement of node.statements) {
if (statement.kind === ts.SyntaxKind.VariableStatement) { if (statement.kind === ts.SyntaxKind.VariableStatement) {
this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names); this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names);
@ -205,7 +204,7 @@ class PreferConstWalker extends Lint.RuleWalker {
this.popDeclarations(); 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) { for (const node of list.declarations) {
if (isLet(node) && !isExported(node)) { if (isLet(node) && !isExported(node)) {
this.collectNameIdentifiers(node, node.name, ret); 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) { if (node.kind === ts.SyntaxKind.Identifier) {
table[(node as ts.Identifier).text] = { declaration, usages: 0 }; 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) { for (const element of pattern.elements) {
this.collectNameIdentifiers(value, element.name, table); this.collectNameIdentifiers(value, element.name, table);
} }

View file

@ -22,3 +22,4 @@ declare module "into-stream" {
} }
declare module "sorcery"; declare module "sorcery";
declare module "travis-fold";

View file

@ -89,9 +89,10 @@ namespace ts {
const binder = createBinder(); const binder = createBinder();
export function bindSourceFile(file: SourceFile, options: CompilerOptions) { export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
const start = performance.mark(); performance.mark("beforeBind");
binder(file, options); binder(file, options);
performance.measure("Bind", start); performance.mark("afterBind");
performance.measure("Bind", "beforeBind", "afterBind");
} }
function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
@ -135,7 +136,7 @@ namespace ts {
options = opts; options = opts;
languageVersion = getEmitScriptTarget(options); languageVersion = getEmitScriptTarget(options);
inStrictMode = !!file.externalModuleIndicator; inStrictMode = !!file.externalModuleIndicator;
classifiableNames = {}; classifiableNames = createMap<string>();
symbolCount = 0; symbolCount = 0;
Symbol = objectAllocator.getSymbolConstructor(); Symbol = objectAllocator.getSymbolConstructor();
@ -183,11 +184,11 @@ namespace ts {
symbol.declarations.push(node); symbol.declarations.push(node);
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
symbol.exports = {}; symbol.exports = createMap<Symbol>();
} }
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
symbol.members = {}; symbol.members = createMap<Symbol>();
} }
if (symbolFlags & SymbolFlags.Value) { if (symbolFlags & SymbolFlags.Value) {
@ -318,9 +319,7 @@ namespace ts {
// Otherwise, we'll be merging into a compatible existing symbol (for example when // 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 // 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. // just add this node into the declarations list of the symbol.
symbol = hasProperty(symbolTable, name) symbol = symbolTable[name] || (symbolTable[name] = createSymbol(SymbolFlags.None, name));
? symbolTable[name]
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
if (name && (includes & SymbolFlags.Classifiable)) { if (name && (includes & SymbolFlags.Classifiable)) {
classifiableNames[name] = name; classifiableNames[name] = name;
@ -434,7 +433,7 @@ namespace ts {
if (containerFlags & ContainerFlags.IsContainer) { if (containerFlags & ContainerFlags.IsContainer) {
container = blockScopeContainer = node; container = blockScopeContainer = node;
if (containerFlags & ContainerFlags.HasLocals) { if (containerFlags & ContainerFlags.HasLocals) {
container.locals = {}; container.locals = createMap<Symbol>();
} }
addToContainerChain(container); addToContainerChain(container);
} }
@ -1399,7 +1398,8 @@ namespace ts {
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = { [symbol.name]: symbol }; typeLiteralSymbol.members = createMap<Symbol>();
typeLiteralSymbol.members[symbol.name] = symbol;
} }
function bindObjectLiteralExpression(node: ObjectLiteralExpression) { function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
@ -1409,7 +1409,7 @@ namespace ts {
} }
if (inStrictMode) { if (inStrictMode) {
const seen: Map<ElementKind> = {}; const seen = createMap<ElementKind>();
for (const prop of node.properties) { for (const prop of node.properties) {
if (prop.name.kind !== SyntaxKind.Identifier) { if (prop.name.kind !== SyntaxKind.Identifier) {
@ -1465,7 +1465,7 @@ namespace ts {
// fall through. // fall through.
default: default:
if (!blockScopeContainer.locals) { if (!blockScopeContainer.locals) {
blockScopeContainer.locals = {}; blockScopeContainer.locals = createMap<Symbol>();
addToContainerChain(blockScopeContainer); addToContainerChain(blockScopeContainer);
} }
declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes);
@ -1887,18 +1887,17 @@ namespace ts {
} }
function bindExportAssignment(node: ExportAssignment | BinaryExpression) { function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (<ExportAssignment>node).expression : (<BinaryExpression>node).right;
if (!container.symbol || !container.symbol.exports) { if (!container.symbol || !container.symbol.exports) {
// Export assignment in some sort of block construct // Export assignment in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); 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 { else {
// An export default clause with an expression exports a value const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node)
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); // 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 +1924,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); declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
} }
@ -1978,7 +1977,7 @@ namespace ts {
else { else {
return; return;
} }
assignee.symbol.members = assignee.symbol.members || {}; assignee.symbol.members = assignee.symbol.members || createMap<Symbol>();
// It's acceptable for multiple 'this' assignments of the same identifier to occur // 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); declareSymbol(assignee.symbol.members, assignee.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
} }
@ -2004,7 +2003,7 @@ namespace ts {
// Set up the members collection if it doesn't exist already // Set up the members collection if it doesn't exist already
if (!funcSymbol.members) { if (!funcSymbol.members) {
funcSymbol.members = {}; funcSymbol.members = createMap<Symbol>();
} }
// Declare the method/property // Declare the method/property
@ -2053,7 +2052,7 @@ namespace ts {
// module might have an exported variable called 'prototype'. We can't allow that as // 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. // that would clash with the built-in 'prototype' for the class.
const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype"); const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
if (hasProperty(symbol.exports, prototypeSymbol.name)) { if (symbol.exports[prototypeSymbol.name]) {
if (node.name) { if (node.name) {
node.name.parent = node; node.name.parent = node;
} }

File diff suppressed because it is too large Load diff

View file

@ -470,8 +470,8 @@ namespace ts {
return optionNameMapCache; return optionNameMapCache;
} }
const optionNameMap: Map<CommandLineOption> = {}; const optionNameMap = createMap<CommandLineOption>();
const shortOptionNames: Map<string> = {}; const shortOptionNames = createMap<string>();
forEach(optionDeclarations, option => { forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option; optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) { if (option.shortName) {
@ -958,12 +958,12 @@ namespace ts {
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a // 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 // file map with a possibly case insensitive key. We use this map later when when including
// wildcard paths. // wildcard paths.
const literalFileMap: Map<string> = {}; const literalFileMap = createMap<string>();
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a // 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 // file map with a possibly case insensitive key. We use this map to store paths matched
// via wildcard, and to handle extension priority. // via wildcard, and to handle extension priority.
const wildcardFileMap: Map<string> = {}; const wildcardFileMap = createMap<string>();
if (include) { if (include) {
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false); include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
@ -1063,7 +1063,7 @@ namespace ts {
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z // /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude"); const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i"); const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
const wildcardDirectories: Map<WatchDirectoryFlags> = {}; const wildcardDirectories = createMap<WatchDirectoryFlags>();
if (include !== undefined) { if (include !== undefined) {
const recursiveKeys: string[] = []; const recursiveKeys: string[] = [];
for (const file of include) { for (const file of include) {

View file

@ -19,8 +19,24 @@ namespace ts {
True = -1 True = -1
} }
const createObject = Object.create;
export function createMap<T>(): Map<T> {
/* tslint:disable:no-null-keyword */
const map: Map<T> = createObject(null);
/* tslint:enable: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["__"];
return map;
}
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> { export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
let files: Map<T> = {}; let files = createMap<T>();
return { return {
get, get,
set, set,
@ -55,7 +71,7 @@ namespace ts {
} }
function clear() { function clear() {
files = {}; files = createMap<T>();
} }
function toKey(path: Path): string { function toKey(path: Path): string {
@ -81,7 +97,7 @@ namespace ts {
* returns a truthy value, then returns that value. * 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. * 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) { if (array) {
for (let i = 0, len = array.length; i < len; i++) { for (let i = 0, len = array.length; i < len; i++) {
const result = callback(array[i], i); const result = callback(array[i], i);
@ -93,6 +109,17 @@ namespace ts {
return undefined; return undefined;
} }
/** Like `forEach`, but assumes existence of array and fails if no truthy value is found. */
export function find<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 { export function contains<T>(array: T[], value: T): boolean {
if (array) { if (array) {
for (const v of array) { for (const v of array) {
@ -136,17 +163,29 @@ namespace ts {
return count; 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[] { export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
let result: T[];
if (array) { if (array) {
result = []; const len = array.length;
for (const item of array) { let i = 0;
if (f(item)) { while (i < len && f(array[i])) i++;
result.push(item); 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 filterMutate<T>(array: T[], f: (x: T) => boolean): void { export function filterMutate<T>(array: T[], f: (x: T) => boolean): void {
@ -311,11 +350,11 @@ namespace ts {
const hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwnProperty = Object.prototype.hasOwnProperty;
export function hasProperty<T>(map: Map<T>, key: string): boolean { export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
return hasOwnProperty.call(map, key); return hasOwnProperty.call(map, key);
} }
export function getKeys<T>(map: Map<T>): string[] { export function getKeys<T>(map: MapLike<T>): string[] {
const keys: string[] = []; const keys: string[] = [];
for (const key in map) { for (const key in map) {
keys.push(key); keys.push(key);
@ -323,11 +362,15 @@ namespace ts {
return keys; return keys;
} }
export function getProperty<T>(map: Map<T>, key: string): T { export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasOwnProperty.call(map, key) ? map[key] : undefined; return hasProperty(map, key) ? map[key] : undefined;
} }
export function isEmpty<T>(map: Map<T>) { export function getOrUpdateProperty<T>(map: MapLike<T>, key: string, makeValue: () => T): T {
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
}
export function isEmpty<T>(map: MapLike<T>) {
for (const id in map) { for (const id in map) {
if (hasProperty(map, id)) { if (hasProperty(map, id)) {
return false; return false;
@ -344,7 +387,7 @@ namespace ts {
return <T>result; return <T>result;
} }
export function extend<T1 extends Map<{}>, T2 extends Map<{}>>(first: T1 , second: T2): T1 & T2 { export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{}; const result: T1 & T2 = <any>{};
for (const id in first) { for (const id in first) {
(result as any)[id] = first[id]; (result as any)[id] = first[id];
@ -357,7 +400,7 @@ namespace ts {
return result; return result;
} }
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U { export function forEachValue<T, U>(map: MapLike<T>, callback: (value: T) => U): U {
let result: U; let result: U;
for (const id in map) { for (const id in map) {
if (result = callback(map[id])) break; if (result = callback(map[id])) break;
@ -365,7 +408,7 @@ namespace ts {
return result; return result;
} }
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U { export function forEachKey<T, U>(map: MapLike<T>, callback: (key: string) => U): U {
let result: U; let result: U;
for (const id in map) { for (const id in map) {
if (result = callback(id)) break; if (result = callback(id)) break;
@ -373,11 +416,11 @@ namespace ts {
return result; return result;
} }
export function lookUp<T>(map: Map<T>, key: string): T { export function lookUp<T>(map: MapLike<T>, key: string): T {
return hasProperty(map, key) ? map[key] : undefined; return hasProperty(map, key) ? map[key] : undefined;
} }
export function copyMap<T>(source: Map<T>, target: Map<T>): void { export function copyMap<T>(source: MapLike<T>, target: MapLike<T>): void {
for (const p in source) { for (const p in source) {
target[p] = source[p]; target[p] = source[p];
} }
@ -394,7 +437,7 @@ namespace ts {
* index in the array will be the one associated with the produced key. * 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> { export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
const result: Map<T> = {}; const result = createMap<T>();
forEach(array, value => { forEach(array, value => {
result[makeKey(value)] = value; result[makeKey(value)] = value;
@ -410,7 +453,7 @@ namespace ts {
* @param callback An aggregation function that is called for each entry in the map * @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction. * @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 { export function reduceProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial; let result = initial;
if (map) { if (map) {
for (const key in map) { for (const key in map) {
@ -450,9 +493,7 @@ namespace ts {
export let localizedDiagnosticMessages: Map<string> = undefined; export let localizedDiagnosticMessages: Map<string> = undefined;
export function getLocaleSpecificMessage(message: DiagnosticMessage) { export function getLocaleSpecificMessage(message: DiagnosticMessage) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
? localizedDiagnosticMessages[message.key]
: message.message;
} }
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
@ -941,7 +982,7 @@ namespace ts {
* [^./] # matches everything up to the first . character (excluding directory seperators) * [^./] # matches everything up to the first . character (excluding directory seperators)
* (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
*/ */
const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*"; const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*";
const singleAsteriskRegexFragmentOther = "[^/]*"; const singleAsteriskRegexFragmentOther = "[^/]*";
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") { export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {

View file

@ -269,7 +269,7 @@ namespace ts {
} }
if (!usedTypeDirectiveReferences) { if (!usedTypeDirectiveReferences) {
usedTypeDirectiveReferences = {}; usedTypeDirectiveReferences = createMap<string>();
} }
for (const directive of typeReferenceDirectives) { for (const directive of typeReferenceDirectives) {
if (!hasProperty(usedTypeDirectiveReferences, directive)) { if (!hasProperty(usedTypeDirectiveReferences, directive)) {
@ -441,7 +441,7 @@ namespace ts {
} }
} }
function emitEntityName(entityName: EntityName | PropertyAccessExpression) { function emitEntityName(entityName: EntityNameOrEntityNameExpression) {
const visibilityResult = resolver.isEntityNameVisible(entityName, const visibilityResult = resolver.isEntityNameVisible(entityName,
// Aliases can be written asynchronously so use correct enclosing declaration // Aliases can be written asynchronously so use correct enclosing declaration
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration); entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
@ -452,9 +452,9 @@ namespace ts {
} }
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
if (isSupportedExpressionWithTypeArguments(node)) { if (isEntityNameExpression(node.expression)) {
Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression); Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
emitEntityName(<Identifier | PropertyAccessExpression>node.expression); emitEntityName(node.expression);
if (node.typeArguments) { if (node.typeArguments) {
write("<"); write("<");
emitCommaList(node.typeArguments, emitType); emitCommaList(node.typeArguments, emitType);
@ -1019,7 +1019,7 @@ namespace ts {
} }
function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) { function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) {
if (isSupportedExpressionWithTypeArguments(node)) { if (isEntityNameExpression(node.expression)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
} }
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) { else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {

View file

@ -1947,6 +1947,10 @@
"category": "Error", "category": "Error",
"code": 2689 "code": 2689
}, },
"A class must be declared after its base class.": {
"category": "Error",
"code": 2690
},
"Import declaration '{0}' is using private name '{1}'.": { "Import declaration '{0}' is using private name '{1}'.": {
"category": "Error", "category": "Error",
"code": 4000 "code": 4000

View file

@ -24,7 +24,7 @@ namespace ts {
Return = 1 << 3 Return = 1 << 3
} }
const entities: Map<number> = { const entities: MapLike<number> = {
"quot": 0x0022, "quot": 0x0022,
"amp": 0x0026, "amp": 0x0026,
"apos": 0x0027, "apos": 0x0027,
@ -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 { function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void {
if (isBreak) { if (isBreak) {
if (!state.labeledNonLocalBreaks) { if (!state.labeledNonLocalBreaks) {
state.labeledNonLocalBreaks = {}; state.labeledNonLocalBreaks = createMap<string>();
} }
state.labeledNonLocalBreaks[labelText] = labelMarker; state.labeledNonLocalBreaks[labelText] = labelMarker;
} }
else { else {
if (!state.labeledNonLocalContinues) { if (!state.labeledNonLocalContinues) {
state.labeledNonLocalContinues = {}; state.labeledNonLocalContinues = createMap<string>();
} }
state.labeledNonLocalContinues[labelText] = labelMarker; state.labeledNonLocalContinues[labelText] = labelMarker;
} }
@ -531,7 +531,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
let currentText: string; let currentText: string;
let currentLineMap: number[]; let currentLineMap: number[];
let currentFileIdentifiers: Map<string>; let currentFileIdentifiers: Map<string>;
let renamedDependencies: Map<string>; let renamedDependencies: MapLike<string>;
let isEs6Module: boolean; let isEs6Module: boolean;
let isCurrentFileExternalModule: boolean; let isCurrentFileExternalModule: boolean;
@ -577,7 +577,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { }; const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { };
const moduleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = { const moduleEmitDelegates: MapLike<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
[ModuleKind.ES6]: emitES6Module, [ModuleKind.ES6]: emitES6Module,
[ModuleKind.AMD]: emitAMDModule, [ModuleKind.AMD]: emitAMDModule,
[ModuleKind.System]: emitSystemModule, [ModuleKind.System]: emitSystemModule,
@ -585,7 +585,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
[ModuleKind.CommonJS]: emitCommonJSModule, [ModuleKind.CommonJS]: emitCommonJSModule,
}; };
const bundleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = { const bundleEmitDelegates: MapLike<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
[ModuleKind.ES6]() {}, [ModuleKind.ES6]() {},
[ModuleKind.AMD]: emitAMDModule, [ModuleKind.AMD]: emitAMDModule,
[ModuleKind.System]: emitSystemModule, [ModuleKind.System]: emitSystemModule,
@ -597,7 +597,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function doEmit(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) { function doEmit(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
generatedNameSet = {}; generatedNameSet = createMap<string>();
nodeToGeneratedName = []; nodeToGeneratedName = [];
decoratedClassAliases = []; decoratedClassAliases = [];
isOwnFileEmit = !isBundledEmit; isOwnFileEmit = !isBundledEmit;
@ -2578,7 +2578,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
operand = (<TypeAssertion | NonNullExpression>operand).expression; operand = (<TypeAssertion | NonNullExpression>operand).expression;
} }
// We have an expression of the form: (<Type>SubExpr) // We have an expression of the form: (<Type>SubExpr) or (SubExpr as Type)
// Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is. // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
// Omitting the parentheses, however, could cause change in the semantics of the generated // Omitting the parentheses, however, could cause change in the semantics of the generated
// code if the casted expression has a lower precedence than the rest of the expression, e.g.: // code if the casted expression has a lower precedence than the rest of the expression, e.g.:
@ -2592,6 +2592,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
operand.kind !== SyntaxKind.DeleteExpression && operand.kind !== SyntaxKind.DeleteExpression &&
operand.kind !== SyntaxKind.PostfixUnaryExpression && operand.kind !== SyntaxKind.PostfixUnaryExpression &&
operand.kind !== SyntaxKind.NewExpression && operand.kind !== SyntaxKind.NewExpression &&
!(operand.kind === SyntaxKind.BinaryExpression && node.expression.kind === SyntaxKind.AsExpression) &&
!(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) && !(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
!(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression) && !(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression) &&
!(operand.kind === SyntaxKind.NumericLiteral && node.parent.kind === SyntaxKind.PropertyAccessExpression)) { !(operand.kind === SyntaxKind.NumericLiteral && node.parent.kind === SyntaxKind.PropertyAccessExpression)) {
@ -3256,7 +3257,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// Don't initialize seen unless we have at least one element. // Don't initialize seen unless we have at least one element.
// Emit a comma to separate for all but the first element. // Emit a comma to separate for all but the first element.
if (!seen) { if (!seen) {
seen = {}; seen = createMap<string>();
} }
else { else {
write(", "); write(", ");
@ -3855,7 +3856,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (convertedLoopState) { if (convertedLoopState) {
if (!convertedLoopState.labels) { if (!convertedLoopState.labels) {
convertedLoopState.labels = {}; convertedLoopState.labels = createMap<string>();
} }
convertedLoopState.labels[node.label.text] = node.label.text; convertedLoopState.labels[node.label.text] = node.label.text;
} }
@ -6802,7 +6803,7 @@ const _super = (function (geti, seti) {
function collectExternalModuleInfo(sourceFile: SourceFile) { function collectExternalModuleInfo(sourceFile: SourceFile) {
externalImports = []; externalImports = [];
exportSpecifiers = {}; exportSpecifiers = createMap<ExportSpecifier[]>();
exportEquals = undefined; exportEquals = undefined;
hasExportStarsToExportValues = false; hasExportStarsToExportValues = false;
for (const node of sourceFile.statements) { for (const node of sourceFile.statements) {
@ -6841,7 +6842,7 @@ const _super = (function (geti, seti) {
// export { x, y } // export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) { for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
const name = (specifier.propertyName || specifier.name).text; const name = (specifier.propertyName || specifier.name).text;
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier); getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
} }
} }
break; break;
@ -7080,7 +7081,7 @@ const _super = (function (geti, seti) {
if (hoistedVars) { if (hoistedVars) {
writeLine(); writeLine();
write("var "); write("var ");
const seen: Map<string> = {}; const seen = createMap<string>();
for (let i = 0; i < hoistedVars.length; i++) { for (let i = 0; i < hoistedVars.length; i++) {
const local = hoistedVars[i]; const local = hoistedVars[i];
const name = local.kind === SyntaxKind.Identifier const name = local.kind === SyntaxKind.Identifier
@ -7446,7 +7447,7 @@ const _super = (function (geti, seti) {
writeModuleName(node, emitRelativePathAsModuleName); writeModuleName(node, emitRelativePathAsModuleName);
write("["); write("[");
const groupIndices: Map<number> = {}; const groupIndices = createMap<number>();
const dependencyGroups: DependencyGroup[] = []; const dependencyGroups: DependencyGroup[] = [];
for (let i = 0; i < externalImports.length; i++) { for (let i = 0; i < externalImports.length; i++) {

View file

@ -421,10 +421,10 @@ namespace ts {
} }
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { 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); const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
performance.mark("afterParse");
performance.measure("Parse", start); performance.measure("Parse", "beforeParse", "afterParse");
return result; return result;
} }
@ -595,7 +595,7 @@ namespace ts {
parseDiagnostics = []; parseDiagnostics = [];
parsingContext = 0; parsingContext = 0;
identifiers = {}; identifiers = createMap<string>();
identifierCount = 0; identifierCount = 0;
nodeCount = 0; nodeCount = 0;
@ -1084,7 +1084,7 @@ namespace ts {
function internIdentifier(text: string): string { function internIdentifier(text: string): string {
text = escapeIdentifier(text); 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 // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues

View file

@ -6,71 +6,57 @@ namespace ts {
} }
/*@internal*/ /*@internal*/
/** Performance measurements for the compiler. */
namespace ts.performance { namespace ts.performance {
/** Performance measurements for the compiler. */
declare const onProfilerEvent: { (markName: string): void; profiler: boolean; }; 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>; let measures: Map<number>;
/** /**
* Emit a performance event if ts-profiler is connected. This is primarily used * Marks a performance event.
* to generate heap snapshots.
* *
* @param eventName A name for the event. * @param markName The name of the mark.
*/ */
export function emit(eventName: string) { export function mark(markName: string) {
if (profilerEvent) { if (enabled) {
profilerEvent(eventName); 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. * Adds a performance measurement with the specified name.
* *
* @param measureName The name of the performance measurement. * @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) { export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
if (measures) { if (enabled) {
measures[measureName] = (getProperty(measures, measureName) || 0) + (timestamp() - marker); 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 * Gets the number of times a marker was encountered.
* *
* @param cb The action to perform for each measure * @param markName The name of the mark.
*/ */
export function forEachMeasure(cb: (measureName: string, duration: number) => void) { export function getCount(markName: string) {
return forEachKey(measures, key => cb(key, measures[key])); return counts && counts[markName] || 0;
} }
/** /**
@ -79,31 +65,31 @@ namespace ts.performance {
* @param measureName The name of the measure whose durations should be accumulated. * @param measureName The name of the measure whose durations should be accumulated.
*/ */
export function getDuration(measureName: string) { 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. */ /** Enables (and resets) performance measurements for the compiler. */
export function enable() { export function enable() {
counters = { }; counts = createMap<number>();
measures = { marks = createMap<number>();
"I/O Read": 0, measures = createMap<number>();
"I/O Write": 0, enabled = true;
"Program": 0, profilerStart = timestamp();
"Parse": 0,
"Bind": 0,
"Check": 0,
"Emit": 0,
};
profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
? onProfilerEvent
: undefined;
} }
/** Disables (and clears) performance measurements for the compiler. */ /** Disables performance measurements for the compiler. */
export function disable() { export function disable() {
counters = undefined; enabled = false;
measures = undefined;
profilerEvent = undefined;
} }
} }

View file

@ -119,49 +119,31 @@ namespace ts {
} }
function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string { function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
let jsonContent: { typings?: string, types?: string, main?: string }; const jsonContent = readJson(packageJsonPath, state.host);
try {
const jsonText = state.host.readFile(packageJsonPath); function tryReadFromField(fieldName: string) {
jsonContent = jsonText ? <{ typings?: string, types?: string, main?: string }>JSON.parse(jsonText) : {}; if (hasProperty(jsonContent, fieldName)) {
} const typesFile = (<any>jsonContent)[fieldName];
catch (e) { if (typeof typesFile === "string") {
// gracefully handle if readFile fails or returns not JSON const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
jsonContent = {}; 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; const typesFilePath = tryReadFromField("typings") || tryReadFromField("types");
let fieldName: string; if (typesFilePath) {
// 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);
}
return typesFilePath; return typesFilePath;
} }
// Use the main module for inferring types if no types package specified and the allowJs is set // 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.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") {
if (state.traceEnabled) { if (state.traceEnabled) {
@ -173,6 +155,17 @@ namespace ts {
return undefined; 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"]; const typeReferenceExtensions = [".d.ts"];
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) { function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
@ -717,7 +710,7 @@ namespace ts {
} }
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string { 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); const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
if (directoryExists && state.host.fileExists(packageJsonPath)) { if (directoryExists && state.host.fileExists(packageJsonPath)) {
if (state.traceEnabled) { if (state.traceEnabled) {
@ -747,6 +740,10 @@ namespace ts {
return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); 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 { function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolder = combinePaths(directory, "node_modules");
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
@ -846,7 +843,7 @@ namespace ts {
} }
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
const existingDirectories: Map<boolean> = {}; const existingDirectories = createMap<boolean>();
function getCanonicalFileName(fileName: string): string { 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. // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
@ -860,9 +857,10 @@ namespace ts {
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string; let text: string;
try { try {
const start = performance.mark(); performance.mark("beforeIORead");
text = sys.readFile(fileName, options.charset); text = sys.readFile(fileName, options.charset);
performance.measure("I/O Read", start); performance.mark("afterIORead");
performance.measure("I/O Read", "beforeIORead", "afterIORead");
} }
catch (e) { catch (e) {
if (onError) { if (onError) {
@ -899,7 +897,7 @@ namespace ts {
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void { function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
if (!outputFingerprints) { if (!outputFingerprints) {
outputFingerprints = {}; outputFingerprints = createMap<OutputFingerprint>();
} }
const hash = sys.createHash(data); const hash = sys.createHash(data);
@ -929,7 +927,7 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try { try {
const start = performance.mark(); performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) { if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
@ -939,7 +937,8 @@ namespace ts {
sys.writeFile(fileName, data, writeByteOrderMark); sys.writeFile(fileName, data, writeByteOrderMark);
} }
performance.measure("I/O Write", start); performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
} }
catch (e) { catch (e) {
if (onError) { if (onError) {
@ -1040,7 +1039,7 @@ namespace ts {
return []; return [];
} }
const resolutions: T[] = []; const resolutions: T[] = [];
const cache: Map<T> = {}; const cache = createMap<T>();
for (const name of names) { for (const name of names) {
let result: T; let result: T;
if (hasProperty(cache, name)) { if (hasProperty(cache, name)) {
@ -1055,32 +1054,37 @@ namespace ts {
return resolutions; return resolutions;
} }
function getInferredTypesRoot(options: CompilerOptions, rootFiles: string[], host: CompilerHost) {
return computeCommonSourceDirectoryOfFilenames(rootFiles, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
}
/** /**
* Given a set of options and a set of root files, returns the set of type directive names * Given a set of options, returns the set of type directive names
* that should be included for this program automatically. * that should be included for this program automatically.
* This list could either come from the config file, * This list could either come from the config file,
* or from enumerating the types root + initial secondary types lookup location. * or from enumerating the types root + initial secondary types lookup location.
* More type directives might appear in the program later as a result of loading actual source files; * More type directives might appear in the program later as a result of loading actual source files;
* this list is only the set of defaults that are implicitly included. * this list is only the set of defaults that are implicitly included.
*/ */
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, rootFiles: string[], host: CompilerHost): string[] { export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[] {
// Use explicit type list from tsconfig.json // Use explicit type list from tsconfig.json
if (options.types) { if (options.types) {
return options.types; return options.types;
} }
// Walk the primary type lookup locations // Walk the primary type lookup locations
let result: string[] = []; const result: string[] = [];
if (host.directoryExists && host.getDirectories) { if (host.directoryExists && host.getDirectories) {
const typeRoots = getEffectiveTypeRoots(options, host); const typeRoots = getEffectiveTypeRoots(options, host);
if (typeRoots) { if (typeRoots) {
for (const root of typeRoots) { for (const root of typeRoots) {
if (host.directoryExists(root)) { if (host.directoryExists(root)) {
result = result.concat(host.getDirectories(root)); for (const typeDirectivePath of host.getDirectories(root)) {
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));
}
}
} }
} }
} }
@ -1096,7 +1100,7 @@ namespace ts {
let noDiagnosticsTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>; let classifiableNames: Map<string>;
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {}; let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
let fileProcessingDiagnostics = createDiagnosticCollection(); 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. // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
@ -1111,12 +1115,12 @@ namespace ts {
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track // 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. // 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. // 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); host = host || createCompilerHost(options);
@ -1155,11 +1159,11 @@ namespace ts {
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false)); forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, rootNames, host); const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
if (typeReferences) { if (typeReferences) {
const inferredRoot = getInferredTypesRoot(options, rootNames, host); // This containingFilename needs to match with the one used in managed-side
const containingFilename = combinePaths(inferredRoot, "__inferred type names__.ts"); const containingFilename = combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts");
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename);
for (let i = 0; i < typeReferences.length; i++) { for (let i = 0; i < typeReferences.length; i++) {
processTypeReferenceDirective(typeReferences[i], resolutions[i]); processTypeReferenceDirective(typeReferences[i], resolutions[i]);
@ -1214,8 +1218,8 @@ namespace ts {
}; };
verifyCompilerOptions(); verifyCompilerOptions();
performance.mark("afterProgram");
performance.measure("Program", start); performance.measure("Program", "beforeProgram", "afterProgram");
return program; return program;
@ -1242,7 +1246,7 @@ namespace ts {
if (!classifiableNames) { if (!classifiableNames) {
// Initialize a checker so that all our files are bound. // Initialize a checker so that all our files are bound.
getTypeChecker(); getTypeChecker();
classifiableNames = {}; classifiableNames = createMap<string>();
for (const sourceFile of files) { for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames); copyMap(sourceFile.classifiableNames, classifiableNames);
@ -1458,14 +1462,15 @@ namespace ts {
// checked is to not pass the file to getEmitResolver. // checked is to not pass the file to getEmitResolver.
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
const start = performance.mark(); performance.mark("beforeEmit");
const emitResult = emitFiles( const emitResult = emitFiles(
emitResolver, emitResolver,
getEmitHost(writeFileCallback), getEmitHost(writeFileCallback),
sourceFile); sourceFile);
performance.measure("Emit", start); performance.mark("afterEmit");
performance.measure("Emit", "beforeEmit", "afterEmit");
return emitResult; return emitResult;
} }
@ -2083,7 +2088,7 @@ namespace ts {
function processImportedModules(file: SourceFile, basePath: string) { function processImportedModules(file: SourceFile, basePath: string) {
collectExternalModuleReferences(file); collectExternalModuleReferences(file);
if (file.imports.length || file.moduleAugmentations.length) { if (file.imports.length || file.moduleAugmentations.length) {
file.resolvedModules = {}; file.resolvedModules = createMap<ResolvedModule>();
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory)); const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
for (let i = 0; i < moduleNames.length; i++) { for (let i = 0; i < moduleNames.length; i++) {

View file

@ -55,7 +55,7 @@ namespace ts {
tryScan<T>(callback: () => T): T; tryScan<T>(callback: () => T): T;
} }
const textToToken: Map<SyntaxKind> = { const textToToken: MapLike<SyntaxKind> = {
"abstract": SyntaxKind.AbstractKeyword, "abstract": SyntaxKind.AbstractKeyword,
"any": SyntaxKind.AnyKeyword, "any": SyntaxKind.AnyKeyword,
"as": SyntaxKind.AsKeyword, "as": SyntaxKind.AsKeyword,
@ -271,7 +271,7 @@ namespace ts {
lookupInUnicodeMap(code, unicodeES3IdentifierPart); lookupInUnicodeMap(code, unicodeES3IdentifierPart);
} }
function makeReverseMap(source: Map<number>): string[] { function makeReverseMap(source: MapLike<number>): string[] {
const result: string[] = []; const result: string[] = [];
for (const name in source) { for (const name in source) {
if (source.hasOwnProperty(name)) { if (source.hasOwnProperty(name)) {

View file

@ -46,6 +46,7 @@ namespace ts {
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
const compilerOptions = host.getCompilerOptions(); const compilerOptions = host.getCompilerOptions();
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
let currentSourceFile: SourceFile; let currentSourceFile: SourceFile;
let sourceMapDir: string; // The directory in which sourcemap will be let sourceMapDir: string; // The directory in which sourcemap will be
let stopOverridingSpan = false; let stopOverridingSpan = false;
@ -240,7 +241,9 @@ namespace ts {
return; return;
} }
const start = performance.mark(); if (extendedDiagnostics) {
performance.mark("beforeSourcemap");
}
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos); const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
@ -282,7 +285,10 @@ namespace ts {
updateLastEncodedAndRecordedSpans(); updateLastEncodedAndRecordedSpans();
performance.measure("Source Map", start); if (extendedDiagnostics) {
performance.mark("afterSourcemap");
performance.measure("Source Map", "beforeSourcemap", "afterSourcemap");
}
} }
function getStartPos(range: TextRange) { function getStartPos(range: TextRange) {

View file

@ -233,15 +233,15 @@ namespace ts {
const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"]; const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"];
function createWatchedFileSet() { function createWatchedFileSet() {
const dirWatchers: Map<DirectoryWatcher> = {}; const dirWatchers = createMap<DirectoryWatcher>();
// One file can have multiple watchers // One file can have multiple watchers
const fileWatcherCallbacks: Map<FileWatcherCallback[]> = {}; const fileWatcherCallbacks = createMap<FileWatcherCallback[]>();
return { addFile, removeFile }; return { addFile, removeFile };
function reduceDirWatcherRefCountForFile(fileName: string) { function reduceDirWatcherRefCountForFile(fileName: string) {
const dirName = getDirectoryPath(fileName); const dirName = getDirectoryPath(fileName);
if (hasProperty(dirWatchers, dirName)) { const watcher = dirWatchers[dirName];
const watcher = dirWatchers[dirName]; if (watcher) {
watcher.referenceCount -= 1; watcher.referenceCount -= 1;
if (watcher.referenceCount <= 0) { if (watcher.referenceCount <= 0) {
watcher.close(); watcher.close();
@ -251,13 +251,12 @@ namespace ts {
} }
function addDirWatcher(dirPath: string): void { function addDirWatcher(dirPath: string): void {
if (hasProperty(dirWatchers, dirPath)) { let watcher = dirWatchers[dirPath];
const watcher = dirWatchers[dirPath]; if (watcher) {
watcher.referenceCount += 1; watcher.referenceCount += 1;
return; return;
} }
watcher = _fs.watch(
const watcher: DirectoryWatcher = _fs.watch(
dirPath, dirPath,
{ persistent: true }, { persistent: true },
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath) (eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
@ -268,12 +267,7 @@ namespace ts {
} }
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void { function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
if (hasProperty(fileWatcherCallbacks, filePath)) { (fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback);
fileWatcherCallbacks[filePath].push(callback);
}
else {
fileWatcherCallbacks[filePath] = [callback];
}
} }
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
@ -289,8 +283,9 @@ namespace ts {
} }
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) { function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
if (hasProperty(fileWatcherCallbacks, filePath)) { const callbacks = fileWatcherCallbacks[filePath];
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks[filePath]); if (callbacks) {
const newCallbacks = copyListRemovingItem(callback, callbacks);
if (newCallbacks.length === 0) { if (newCallbacks.length === 0) {
delete fileWatcherCallbacks[filePath]; delete fileWatcherCallbacks[filePath];
} }
@ -306,7 +301,7 @@ namespace ts {
? undefined ? undefined
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath); : ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
// Some applications save a working file via rename operations // 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]) { for (const fileCallback of fileWatcherCallbacks[fileName]) {
fileCallback(fileName); fileCallback(fileName);
} }

View file

@ -122,7 +122,7 @@ namespace ts {
const gutterSeparator = " "; const gutterSeparator = " ";
const resetEscapeSequence = "\u001b[0m"; const resetEscapeSequence = "\u001b[0m";
const ellipsis = "..."; const ellipsis = "...";
const categoryFormatMap: Map<string> = { const categoryFormatMap: MapLike<string> = {
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence, [DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
[DiagnosticCategory.Error]: redForegroundEscapeSequence, [DiagnosticCategory.Error]: redForegroundEscapeSequence,
[DiagnosticCategory.Message]: blueForegroundEscapeSequence, [DiagnosticCategory.Message]: blueForegroundEscapeSequence,
@ -432,7 +432,7 @@ namespace ts {
} }
// reset the cache of existing files // reset the cache of existing files
cachedExistingFiles = {}; cachedExistingFiles = createMap<boolean>();
const compileResult = compile(rootFileNames, compilerOptions, compilerHost); const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
@ -676,7 +676,7 @@ namespace ts {
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here. const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
const descriptionColumn: string[] = []; 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++) { for (let i = 0; i < optsList.length; i++) {
const option = optsList[i]; const option = optsList[i];
@ -786,7 +786,7 @@ namespace ts {
return; return;
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> { function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
const result: Map<string | number | boolean> = {}; const result = createMap<string | number | boolean>();
const optionsNameMap = getOptionNameMap().optionNameMap; const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) { for (const name in options) {

View file

@ -1,9 +1,13 @@
namespace ts { namespace ts {
export interface Map<T> {
export interface MapLike<T> {
[index: string]: T; [index: string]: T;
} }
export interface Map<T> extends MapLike<T> {
__mapBrand: any;
}
// branded string type used to store absolute, normalized and canonicalized paths // branded string type used to store absolute, normalized and canonicalized paths
// arbitrary file name can be converted to Path via toPath function // arbitrary file name can be converted to Path via toPath function
export type Path = string & { __pathBrand: any }; export type Path = string & { __pathBrand: any };
@ -982,13 +986,19 @@ namespace ts {
multiLine?: boolean; multiLine?: boolean;
} }
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
// @kind(SyntaxKind.PropertyAccessExpression) // @kind(SyntaxKind.PropertyAccessExpression)
export interface PropertyAccessExpression extends MemberExpression, Declaration { export interface PropertyAccessExpression extends MemberExpression, Declaration {
expression: LeftHandSideExpression; expression: LeftHandSideExpression;
name: Identifier; name: Identifier;
} }
/** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */
export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression; export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression {
_propertyAccessExpressionLikeQualifiedNameBrand?: any;
expression: EntityNameExpression;
}
// @kind(SyntaxKind.ElementAccessExpression) // @kind(SyntaxKind.ElementAccessExpression)
export interface ElementAccessExpression extends MemberExpression { export interface ElementAccessExpression extends MemberExpression {
@ -1606,6 +1616,16 @@ namespace ts {
antecedent: FlowNode; antecedent: FlowNode;
} }
export type FlowType = Type | IncompleteType;
// Incomplete types occur during control flow analysis of loops. An IncompleteType
// is distinguished from a regular type by a flags value of zero. Incomplete type
// objects are internal to the getFlowTypeOfRefecence function and never escape it.
export interface IncompleteType {
flags: TypeFlags; // No flags set
type: Type; // The type marked incomplete
}
export interface AmdDependency { export interface AmdDependency {
path: string; path: string;
name: string; name: string;
@ -1630,7 +1650,7 @@ namespace ts {
// this map is used by transpiler to supply alternative names for dependencies (i.e. in case of bundling) // this map is used by transpiler to supply alternative names for dependencies (i.e. in case of bundling)
/* @internal */ /* @internal */
renamedDependencies?: Map<string>; renamedDependencies?: MapLike<string>;
/** /**
* lib.d.ts should have a reference comment like * lib.d.ts should have a reference comment like
@ -2022,7 +2042,7 @@ namespace ts {
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, 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; 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 // Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
getReferencedValueDeclaration(reference: Identifier): Declaration; getReferencedValueDeclaration(reference: Identifier): Declaration;
@ -2031,7 +2051,7 @@ namespace ts {
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
isArgumentsLocalBinding(node: Identifier): boolean; isArgumentsLocalBinding(node: Identifier): boolean;
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile; getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile;
getTypeReferenceDirectivesForEntityName(name: EntityName | PropertyAccessExpression): string[]; getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
} }
@ -2151,6 +2171,8 @@ namespace ts {
mapper?: TypeMapper; // Type mapper for instantiation alias mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value referenced?: boolean; // True if alias symbol has been referenced as a value
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property 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 resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked exportsChecked?: boolean; // True if exports of external module have been checked
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
@ -2161,9 +2183,7 @@ namespace ts {
/* @internal */ /* @internal */
export interface TransientSymbol extends Symbol, SymbolLinks { } export interface TransientSymbol extends Symbol, SymbolLinks { }
export interface SymbolTable { export type SymbolTable = Map<Symbol>;
[index: string]: Symbol;
}
/** Represents a "prefix*suffix" pattern. */ /** Represents a "prefix*suffix" pattern. */
/* @internal */ /* @internal */
@ -2360,6 +2380,7 @@ namespace ts {
export interface TupleType extends ObjectType { export interface TupleType extends ObjectType {
elementTypes: Type[]; // Element types elementTypes: Type[]; // Element types
thisType?: Type; // This-type of tuple (only needed for tuples that are constraints of type parameters)
} }
export interface UnionOrIntersectionType extends Type { export interface UnionOrIntersectionType extends Type {
@ -2546,7 +2567,7 @@ namespace ts {
} }
export type RootPaths = string[]; export type RootPaths = string[];
export type PathSubstitutions = Map<string[]>; export type PathSubstitutions = MapLike<string[]>;
export type TsConfigOnlyOptions = RootPaths | PathSubstitutions; export type TsConfigOnlyOptions = RootPaths | PathSubstitutions;
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions; export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions;
@ -2706,7 +2727,7 @@ namespace ts {
fileNames: string[]; fileNames: string[];
raw?: any; raw?: any;
errors: Diagnostic[]; errors: Diagnostic[];
wildcardDirectories?: Map<WatchDirectoryFlags>; wildcardDirectories?: MapLike<WatchDirectoryFlags>;
} }
export const enum WatchDirectoryFlags { export const enum WatchDirectoryFlags {
@ -2716,13 +2737,13 @@ namespace ts {
export interface ExpandResult { export interface ExpandResult {
fileNames: string[]; fileNames: string[];
wildcardDirectories: Map<WatchDirectoryFlags>; wildcardDirectories: MapLike<WatchDirectoryFlags>;
} }
/* @internal */ /* @internal */
export interface CommandLineOptionBase { export interface CommandLineOptionBase {
name: string; name: string;
type: "string" | "number" | "boolean" | "object" | "list" | Map<number | string>; // a value of a primitive type, or an object literal mapping named values to actual values type: "string" | "number" | "boolean" | "object" | "list" | MapLike<number | string>; // a value of a primitive type, or an object literal mapping named values to actual values
isFilePath?: boolean; // True if option value is a path or fileName isFilePath?: boolean; // True if option value is a path or fileName
shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
description?: DiagnosticMessage; // The message describing what the command line switch does description?: DiagnosticMessage; // The message describing what the command line switch does
@ -2738,7 +2759,7 @@ namespace ts {
/* @internal */ /* @internal */
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase { export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
type: Map<number | string>; // an object literal mapping named values to actual values type: MapLike<number | string>; // an object literal mapping named values to actual values
} }
/* @internal */ /* @internal */
@ -2901,6 +2922,7 @@ namespace ts {
directoryExists?(directoryName: string): boolean; directoryExists?(directoryName: string): boolean;
realpath?(path: string): string; realpath?(path: string): string;
getCurrentDirectory?(): string; getCurrentDirectory?(): string;
getDirectories?(path: string): string[];
} }
export interface ResolvedModule { export interface ResolvedModule {

View file

@ -87,14 +87,14 @@ namespace ts {
return node.end - node.pos; return node.end - node.pos;
} }
export function mapIsEqualTo<T>(map1: Map<T>, map2: Map<T>): boolean { export function mapIsEqualTo<T>(map1: MapLike<T>, map2: MapLike<T>): boolean {
if (!map1 || !map2) { if (!map1 || !map2) {
return map1 === map2; return map1 === map2;
} }
return containsAll(map1, map2) && containsAll(map2, map1); return containsAll(map1, map2) && containsAll(map2, map1);
} }
function containsAll<T>(map: Map<T>, other: Map<T>): boolean { function containsAll<T>(map: MapLike<T>, other: MapLike<T>): boolean {
for (const key in map) { for (const key in map) {
if (!hasProperty(map, key)) { if (!hasProperty(map, key)) {
continue; continue;
@ -126,7 +126,7 @@ namespace ts {
} }
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean { 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 { export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
@ -135,7 +135,7 @@ namespace ts {
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void { export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
if (!sourceFile.resolvedModules) { if (!sourceFile.resolvedModules) {
sourceFile.resolvedModules = {}; sourceFile.resolvedModules = createMap<ResolvedModule>();
} }
sourceFile.resolvedModules[moduleNameText] = resolvedModule; sourceFile.resolvedModules[moduleNameText] = resolvedModule;
@ -143,7 +143,7 @@ namespace ts {
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void { export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
if (!sourceFile.resolvedTypeReferenceDirectiveNames) { if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
sourceFile.resolvedTypeReferenceDirectiveNames = {}; sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
} }
sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective; sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective;
@ -166,7 +166,7 @@ namespace ts {
} }
for (let i = 0; i < names.length; i++) { for (let i = 0; i < names.length; i++) {
const newResolution = newResolutions[i]; const newResolution = newResolutions[i];
const oldResolution = oldResolutions && hasProperty(oldResolutions, names[i]) ? oldResolutions[names[i]] : undefined; const oldResolution = oldResolutions && oldResolutions[names[i]];
const changed = const changed =
oldResolution oldResolution
? !newResolution || !comparer(oldResolution, newResolution) ? !newResolution || !comparer(oldResolution, newResolution)
@ -1033,14 +1033,14 @@ namespace ts {
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword; && (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
} }
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
if (node) { if (node) {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.TypeReference: case SyntaxKind.TypeReference:
return (<TypeReferenceNode>node).typeName; return (<TypeReferenceNode>node).typeName;
case SyntaxKind.ExpressionWithTypeArguments: case SyntaxKind.ExpressionWithTypeArguments:
return (<ExpressionWithTypeArguments>node).expression; Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
case SyntaxKind.Identifier: case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName: case SyntaxKind.QualifiedName:
return (<EntityName><Node>node); return (<EntityName><Node>node);
@ -1569,6 +1569,7 @@ namespace ts {
case SyntaxKind.MethodSignature: case SyntaxKind.MethodSignature:
case SyntaxKind.ModuleDeclaration: case SyntaxKind.ModuleDeclaration:
case SyntaxKind.NamespaceImport: case SyntaxKind.NamespaceImport:
case SyntaxKind.NamespaceExportDeclaration:
case SyntaxKind.Parameter: case SyntaxKind.Parameter:
case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertyDeclaration:
@ -1693,8 +1694,8 @@ namespace ts {
// import * as <symbol> from ... // import * as <symbol> from ...
// import { x as <symbol> } from ... // import { x as <symbol> } from ...
// export { x as <symbol> } from ... // export { x as <symbol> } from ...
// export = ... // export = <EntityNameExpression>
// export default ... // export default <EntityNameExpression>
export function isAliasSymbolDeclaration(node: Node): boolean { export function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration || return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.NamespaceExportDeclaration || node.kind === SyntaxKind.NamespaceExportDeclaration ||
@ -1702,7 +1703,11 @@ namespace ts {
node.kind === SyntaxKind.NamespaceImport || node.kind === SyntaxKind.NamespaceImport ||
node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier || 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) { export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
@ -1965,7 +1970,7 @@ namespace ts {
export function createDiagnosticCollection(): DiagnosticCollection { export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics: Diagnostic[] = []; let nonFileDiagnostics: Diagnostic[] = [];
const fileDiagnostics: Map<Diagnostic[]> = {}; const fileDiagnostics = createMap<Diagnostic[]>();
let diagnosticsModified = false; let diagnosticsModified = false;
let modificationCount = 0; let modificationCount = 0;
@ -1983,12 +1988,11 @@ namespace ts {
} }
function reattachFileDiagnostics(newFile: SourceFile): void { function reattachFileDiagnostics(newFile: SourceFile): void {
if (!hasProperty(fileDiagnostics, newFile.fileName)) { const diagnostics = fileDiagnostics[newFile.fileName];
return; if (diagnostics) {
} for (const diagnostic of diagnostics) {
diagnostic.file = newFile;
for (const diagnostic of fileDiagnostics[newFile.fileName]) { }
diagnostic.file = newFile;
} }
} }
@ -2029,9 +2033,7 @@ namespace ts {
forEach(nonFileDiagnostics, pushDiagnostic); forEach(nonFileDiagnostics, pushDiagnostic);
for (const key in fileDiagnostics) { for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) { forEach(fileDiagnostics[key], pushDiagnostic);
forEach(fileDiagnostics[key], pushDiagnostic);
}
} }
return sortAndDeduplicateDiagnostics(allDiagnostics); return sortAndDeduplicateDiagnostics(allDiagnostics);
@ -2046,9 +2048,7 @@ namespace ts {
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics); nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
for (const key in fileDiagnostics) { for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) { fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
}
} }
} }
} }
@ -2059,7 +2059,7 @@ namespace ts {
// the map below must be updated. Note that this regexp *does not* include the 'delete' character. // 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. // 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 escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
const escapedCharsMap: Map<string> = { const escapedCharsMap: MapLike<string> = {
"\0": "\\0", "\0": "\\0",
"\t": "\\t", "\t": "\\t",
"\v": "\\v", "\v": "\\v",
@ -2680,22 +2680,9 @@ namespace ts {
isClassLike(node.parent.parent); isClassLike(node.parent.parent);
} }
// Returns false if this heritage clause element's expression contains something unsupported export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
// (i.e. not a name or dotted name). return node.kind === SyntaxKind.Identifier ||
export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean { node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
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 isRightSideOfQualifiedNameOrPropertyAccess(node: Node) { export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {

View file

@ -52,7 +52,7 @@ class CompilerBaselineRunner extends RunnerBase {
private makeUnitName(name: string, root: string) { private makeUnitName(name: string, root: string) {
const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName)); const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", (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) { public checkTestCodeOutput(fileName: string) {
@ -291,8 +291,8 @@ class CompilerBaselineRunner extends RunnerBase {
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
const fullResults: ts.Map<TypeWriterResult[]> = {}; const fullResults: ts.MapLike<TypeWriterResult[]> = {};
const pullResults: ts.Map<TypeWriterResult[]> = {}; const pullResults: ts.MapLike<TypeWriterResult[]> = {};
for (const sourceFile of allFiles) { for (const sourceFile of allFiles) {
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName); fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
@ -338,7 +338,7 @@ class CompilerBaselineRunner extends RunnerBase {
} }
} }
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string { function generateBaseLine(typeWriterResults: ts.MapLike<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
const typeLines: string[] = []; const typeLines: string[] = [];
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {}; const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};

View file

@ -95,7 +95,7 @@ namespace FourSlash {
export import IndentStyle = ts.IndentStyle; export import IndentStyle = ts.IndentStyle;
const entityMap: ts.Map<string> = { const entityMap: ts.MapLike<string> = {
"&": "&amp;", "&": "&amp;",
"\"": "&quot;", "\"": "&quot;",
"'": "&#39;", "'": "&#39;",
@ -204,7 +204,7 @@ namespace FourSlash {
public formatCodeOptions: ts.FormatCodeOptions; 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.MapLike<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. // Add input file which has matched file name with the given reference-file path.
// This is necessary when resolveReference flag is specified // This is necessary when resolveReference flag is specified
@ -246,6 +246,7 @@ namespace FourSlash {
// Create a new Services Adapter // Create a new Services Adapter
this.cancellationToken = new TestCancellationToken(); this.cancellationToken = new TestCancellationToken();
let compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); let compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions);
compilationOptions.skipDefaultLibCheck = true;
// Initialize the language service with all the scripts // Initialize the language service with all the scripts
let startResolveFileRef: FourSlashFile; let startResolveFileRef: FourSlashFile;
@ -394,7 +395,7 @@ namespace FourSlash {
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) { public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
const startMarker = this.getMarkerByName(startMarkerName); const startMarker = this.getMarkerByName(startMarkerName);
const endMarker = this.getMarkerByName(endMarkerName); 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; return ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false;
}; };
@ -446,12 +447,12 @@ namespace FourSlash {
let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean; let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean;
if (after) { 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; return ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false;
}; };
} }
else { 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; return ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false;
}; };
} }
@ -476,7 +477,7 @@ namespace FourSlash {
endPos = endMarker.position; 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)) { if (predicate(error.start, error.start + error.length, startPos, endPos)) {
exists = true; exists = true;
} }
@ -493,7 +494,7 @@ namespace FourSlash {
Harness.IO.log("Unexpected error(s) found. Error list is:"); 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 + Harness.IO.log(" minChar: " + error.start +
", limChar: " + (error.start + error.length) + ", limChar: " + (error.start + error.length) +
", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n"); ", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n");
@ -643,7 +644,7 @@ namespace FourSlash {
public noItemsWithSameNameButDifferentKind(): void { public noItemsWithSameNameButDifferentKind(): void {
const completions = this.getCompletionListAtCaret(); const completions = this.getCompletionListAtCaret();
const uniqueItems: ts.Map<string> = {}; const uniqueItems: ts.MapLike<string> = {};
for (const item of completions.entries) { for (const item of completions.entries) {
if (!ts.hasProperty(uniqueItems, item.name)) { if (!ts.hasProperty(uniqueItems, item.name)) {
uniqueItems[item.name] = item.kind; uniqueItems[item.name] = item.kind;
@ -1440,14 +1441,7 @@ namespace FourSlash {
} }
// Enters lines of text at the current caret position // Enters lines of text at the current caret position
public type(text: string) { public type(text: string, highFidelity = false) {
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) {
let offset = this.currentCaretPosition; let offset = this.currentCaretPosition;
const prevChar = " "; const prevChar = " ";
const checkCadence = (text.length >> 2) + 1; const checkCadence = (text.length >> 2) + 1;
@ -1456,24 +1450,26 @@ namespace FourSlash {
// Make the edit // Make the edit
const ch = text.charAt(i); const ch = text.charAt(i);
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, ch); 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); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
offset++; offset++;
if (ch === "(" || ch === ",") { if (highFidelity) {
/* Signature help*/ if (ch === "(" || ch === ",") {
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset); /* Signature help*/
} this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
else if (prevChar === " " && /A-Za-z_/.test(ch)) { }
/* Completions */ else if (prevChar === " " && /A-Za-z_/.test(ch)) {
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset); /* Completions */
} this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
}
if (i % checkCadence === 0) { if (i % checkCadence === 0) {
this.checkPostEditInvariants(); this.checkPostEditInvariants();
// this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); }
// this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
} }
// Handle post-keystroke formatting // Handle post-keystroke formatting
@ -1481,14 +1477,12 @@ namespace FourSlash {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
if (edits.length) { if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
} }
} }
} }
// Move the caret to wherever we ended up // Move the caret to wherever we ended up
this.currentCaretPosition = offset; this.currentCaretPosition = offset;
this.fixCaretPosition(); this.fixCaretPosition();
this.checkPostEditInvariants(); this.checkPostEditInvariants();
} }
@ -1507,7 +1501,6 @@ namespace FourSlash {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
if (edits.length) { if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.checkPostEditInvariants();
} }
} }
@ -1730,8 +1723,8 @@ namespace FourSlash {
return this.testData.ranges; return this.testData.ranges;
} }
public rangesByText(): ts.Map<Range[]> { public rangesByText(): ts.MapLike<Range[]> {
const result: ts.Map<Range[]> = {}; const result: ts.MapLike<Range[]> = {};
for (const range of this.getRanges()) { for (const range of this.getRanges()) {
const text = this.rangeText(range); const text = this.rangeText(range);
(ts.getProperty(result, text) || (result[text] = [])).push(range); (ts.getProperty(result, text) || (result[text] = [])).push(range);
@ -1989,7 +1982,7 @@ namespace FourSlash {
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) { public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
const openBraceMap: ts.Map<ts.CharacterCodes> = { const openBraceMap: ts.MapLike<ts.CharacterCodes> = {
"(": ts.CharacterCodes.openParen, "(": ts.CharacterCodes.openParen,
"{": ts.CharacterCodes.openBrace, "{": ts.CharacterCodes.openBrace,
"[": ts.CharacterCodes.openBracket, "[": ts.CharacterCodes.openBracket,
@ -2361,40 +2354,12 @@ namespace FourSlash {
export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
// Parse out the files and their metadata // Parse out the files and their metadata
const testData = parseTestData(basePath, content, fileName); const testData = parseTestData(basePath, content, fileName);
const state = new TestState(basePath, testType, testData); const state = new TestState(basePath, testType, testData);
const output = ts.transpileModule(content, { reportDiagnostics: true });
let result = ""; if (output.diagnostics.length > 0) {
const fourslashFile: Harness.Compiler.TestFile = { throw new Error(`Syntax error in ${basePath}: ${output.diagnostics[0].messageText}`);
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"));
} }
runCode(output.outputText, state);
program.emit(sourceFile);
ts.Debug.assert(!!result);
runCode(result, state);
} }
function runCode(code: string, state: TestState): void { function runCode(code: string, state: TestState): void {
@ -2487,13 +2452,14 @@ ${code}
// Comment line, check for global/file @options and record them // Comment line, check for global/file @options and record them
const match = optionRegex.exec(line.substr(2)); const match = optionRegex.exec(line.substr(2));
if (match) { if (match) {
const fileMetadataNamesIndex = fileMetadataNames.indexOf(match[1]); const [key, value] = match.slice(1);
const fileMetadataNamesIndex = fileMetadataNames.indexOf(key);
if (fileMetadataNamesIndex === -1) { if (fileMetadataNamesIndex === -1) {
// Check if the match is already existed in the global options // Check if the match is already existed in the global options
if (globalOptions[match[1]] !== undefined) { if (globalOptions[key] !== undefined) {
throw new Error("Global Option : '" + match[1] + "' is already existed"); throw new Error(`Global option '${key}' already exists`);
} }
globalOptions[match[1]] = match[2]; globalOptions[key] = value;
} }
else { else {
if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) { if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) {
@ -2508,12 +2474,12 @@ ${code}
resetLocalData(); resetLocalData();
} }
currentFileName = basePath + "/" + match[2]; currentFileName = basePath + "/" + value;
currentFileOptions[match[1]] = match[2]; currentFileOptions[key] = value;
} }
else { else {
// Add other fileMetadata flag // Add other fileMetadata flag
currentFileOptions[match[1]] = match[2]; currentFileOptions[key] = value;
} }
} }
} }
@ -2601,7 +2567,7 @@ ${code}
} }
const marker: Marker = { const marker: Marker = {
fileName: fileName, fileName,
position: location.position, position: location.position,
data: markerValue data: markerValue
}; };
@ -2618,7 +2584,7 @@ ${code}
function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker {
const marker: Marker = { const marker: Marker = {
fileName: fileName, fileName,
position: location.position position: location.position
}; };
@ -2864,7 +2830,7 @@ namespace FourSlashInterface {
return this.state.getRanges(); return this.state.getRanges();
} }
public rangesByText(): ts.Map<FourSlash.Range[]> { public rangesByText(): ts.MapLike<FourSlash.Range[]> {
return this.state.rangesByText(); return this.state.rangesByText();
} }

View file

@ -750,7 +750,7 @@ namespace Harness {
export function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]) { export function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]) {
const fs = new Utils.VirtualFileSystem<string>(path, useCaseSensitiveFileNames()); const fs = new Utils.VirtualFileSystem<string>(path, useCaseSensitiveFileNames());
for (const file in listFiles(path)) { for (const file of listFiles(path)) {
fs.addFile(file); fs.addFile(file);
} }
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), path => { return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), path => {
@ -848,7 +848,7 @@ namespace Harness {
export const defaultLibFileName = "lib.d.ts"; export const defaultLibFileName = "lib.d.ts";
export const es2015DefaultLibFileName = "lib.es2015.d.ts"; export const es2015DefaultLibFileName = "lib.es2015.d.ts";
const libFileNameSourceFileMap: ts.Map<ts.SourceFile> = { const libFileNameSourceFileMap: ts.MapLike<ts.SourceFile> = {
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
}; };
@ -1002,7 +1002,7 @@ namespace Harness {
{ name: "symlink", type: "string" } { name: "symlink", type: "string" }
]; ];
let optionsIndex: ts.Map<ts.CommandLineOption>; let optionsIndex: ts.MapLike<ts.CommandLineOption>;
function getCommandLineOption(name: string): ts.CommandLineOption { function getCommandLineOption(name: string): ts.CommandLineOption {
if (!optionsIndex) { if (!optionsIndex) {
optionsIndex = {}; optionsIndex = {};

View file

@ -277,7 +277,7 @@ namespace Harness.LanguageService {
this.getModuleResolutionsForFile = (fileName) => { this.getModuleResolutionsForFile = (fileName) => {
const scriptInfo = this.getScriptInfo(fileName); const scriptInfo = this.getScriptInfo(fileName);
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true); const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
const imports: ts.Map<string> = {}; const imports: ts.MapLike<string> = {};
for (const module of preprocessInfo.importedFiles) { for (const module of preprocessInfo.importedFiles) {
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost); const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
if (resolutionInfo.resolvedModule) { if (resolutionInfo.resolvedModule) {
@ -290,7 +290,7 @@ namespace Harness.LanguageService {
const scriptInfo = this.getScriptInfo(fileName); const scriptInfo = this.getScriptInfo(fileName);
if (scriptInfo) { if (scriptInfo) {
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ false); const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ false);
const resolutions: ts.Map<ts.ResolvedTypeReferenceDirective> = {}; const resolutions: ts.MapLike<ts.ResolvedTypeReferenceDirective> = {};
const settings = this.nativeHost.getCompilationSettings(); const settings = this.nativeHost.getCompilationSettings();
for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) { for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) {
const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost); const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost);

View file

@ -253,7 +253,7 @@ class ProjectRunner extends RunnerBase {
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
}; };
// Set the values specified using json // Set the values specified using json
const optionNameMap: ts.Map<ts.CommandLineOption> = {}; const optionNameMap: ts.MapLike<ts.CommandLineOption> = {};
ts.forEach(ts.optionDeclarations, option => { ts.forEach(ts.optionDeclarations, option => {
optionNameMap[option.name] = option; optionNameMap[option.name] = option;
}); });

View file

@ -6,8 +6,8 @@ namespace ts {
content: string; content: string;
} }
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost { function createDefaultServerHost(fileMap: MapLike<File>): server.ServerHost {
const existingDirectories: Map<boolean> = {}; const existingDirectories: MapLike<boolean> = {};
forEachValue(fileMap, v => { forEachValue(fileMap, v => {
let dir = getDirectoryPath(v.name); let dir = getDirectoryPath(v.name);
let previous: string; let previous: string;
@ -193,7 +193,7 @@ namespace ts {
content: `export var y = 1` content: `export var y = 1`
}; };
const fileMap: Map<File> = { [root.name]: root }; const fileMap: MapLike<File> = { [root.name]: root };
const serverHost = createDefaultServerHost(fileMap); const serverHost = createDefaultServerHost(fileMap);
const originalFileExists = serverHost.fileExists; const originalFileExists = serverHost.fileExists;

View file

@ -10,7 +10,7 @@ namespace ts {
const map = arrayToMap(files, f => f.name); const map = arrayToMap(files, f => f.name);
if (hasDirectoryExists) { if (hasDirectoryExists) {
const directories: Map<string> = {}; const directories: MapLike<string> = {};
for (const f of files) { for (const f of files) {
let name = getDirectoryPath(f.name); let name = getDirectoryPath(f.name);
while (true) { while (true) {
@ -282,7 +282,7 @@ namespace ts {
}); });
describe("Module resolution - relative imports", () => { describe("Module resolution - relative imports", () => {
function test(files: Map<string>, currentDirectory: string, rootFiles: string[], expectedFilesCount: number, relativeNamesToCheck: string[]) { function test(files: MapLike<string>, currentDirectory: string, rootFiles: string[], expectedFilesCount: number, relativeNamesToCheck: string[]) {
const options: CompilerOptions = { module: ModuleKind.CommonJS }; const options: CompilerOptions = { module: ModuleKind.CommonJS };
const host: CompilerHost = { const host: CompilerHost = {
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => { getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
@ -318,7 +318,7 @@ namespace ts {
} }
it("should find all modules", () => { it("should find all modules", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c/first/shared.ts": ` "/a/b/c/first/shared.ts": `
class A {} class A {}
export = A`, export = A`,
@ -337,7 +337,7 @@ export = C;
}); });
it("should find modules in node_modules", () => { it("should find modules in node_modules", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/parent/node_modules/mod/index.d.ts": "export var x", "/parent/node_modules/mod/index.d.ts": "export var x",
"/parent/app/myapp.ts": `import {x} from "mod"` "/parent/app/myapp.ts": `import {x} from "mod"`
}; };
@ -345,7 +345,7 @@ export = C;
}); });
it("should find file referenced via absolute and relative names", () => { it("should find file referenced via absolute and relative names", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c.ts": `/// <reference path="b.ts"/>`, "/a/b/c.ts": `/// <reference path="b.ts"/>`,
"/a/b/b.ts": "var x" "/a/b/b.ts": "var x"
}; };
@ -355,10 +355,10 @@ export = C;
describe("Files with different casing", () => { describe("Files with different casing", () => {
const library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5); const library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5);
function test(files: Map<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void { function test(files: MapLike<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void {
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
if (!useCaseSensitiveFileNames) { if (!useCaseSensitiveFileNames) {
const f: Map<string> = {}; const f: MapLike<string> = {};
for (const fileName in files) { for (const fileName in files) {
f[getCanonicalFileName(fileName)] = files[fileName]; f[getCanonicalFileName(fileName)] = files[fileName];
} }
@ -395,7 +395,7 @@ export = C;
} }
it("should succeed when the same file is referenced using absolute and relative names", () => { it("should succeed when the same file is referenced using absolute and relative names", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c.ts": `/// <reference path="d.ts"/>`, "/a/b/c.ts": `/// <reference path="d.ts"/>`,
"/a/b/d.ts": "var x" "/a/b/d.ts": "var x"
}; };
@ -403,7 +403,7 @@ export = C;
}); });
it("should fail when two files used in program differ only in casing (tripleslash references)", () => { it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c.ts": `/// <reference path="D.ts"/>`, "/a/b/c.ts": `/// <reference path="D.ts"/>`,
"/a/b/d.ts": "var x" "/a/b/d.ts": "var x"
}; };
@ -411,7 +411,7 @@ export = C;
}); });
it("should fail when two files used in program differ only in casing (imports)", () => { it("should fail when two files used in program differ only in casing (imports)", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c.ts": `import {x} from "D"`, "/a/b/c.ts": `import {x} from "D"`,
"/a/b/d.ts": "export var x" "/a/b/d.ts": "export var x"
}; };
@ -419,7 +419,7 @@ export = C;
}); });
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => { it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
const files: Map<string> = { const files: MapLike<string> = {
"moduleA.ts": `import {x} from "./ModuleB"`, "moduleA.ts": `import {x} from "./ModuleB"`,
"moduleB.ts": "export var x" "moduleB.ts": "export var x"
}; };
@ -427,7 +427,7 @@ export = C;
}); });
it("should fail when two files exist on disk that differs only in casing", () => { it("should fail when two files exist on disk that differs only in casing", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/b/c.ts": `import {x} from "D"`, "/a/b/c.ts": `import {x} from "D"`,
"/a/b/D.ts": "export var x", "/a/b/D.ts": "export var x",
"/a/b/d.ts": "export var y" "/a/b/d.ts": "export var y"
@ -436,7 +436,7 @@ export = C;
}); });
it("should fail when module name in 'require' calls has inconsistent casing", () => { it("should fail when module name in 'require' calls has inconsistent casing", () => {
const files: Map<string> = { const files: MapLike<string> = {
"moduleA.ts": `import a = require("./ModuleC")`, "moduleA.ts": `import a = require("./ModuleC")`,
"moduleB.ts": `import a = require("./moduleC")`, "moduleB.ts": `import a = require("./moduleC")`,
"moduleC.ts": "export var x" "moduleC.ts": "export var x"
@ -445,7 +445,7 @@ export = C;
}); });
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => { it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
const files: Map<string> = { const files: MapLike<string> = {
"/a/B/c/moduleA.ts": `import a = require("./ModuleC")`, "/a/B/c/moduleA.ts": `import a = require("./ModuleC")`,
"/a/B/c/moduleB.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/moduleC.ts": "export var x",
@ -457,7 +457,7 @@ import b = require("./moduleB.ts");
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]); 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", () => { 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: MapLike<string> = {
"/a/B/c/moduleA.ts": `import a = require("./moduleC")`, "/a/B/c/moduleA.ts": `import a = require("./moduleC")`,
"/a/B/c/moduleB.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/moduleC.ts": "export var x",

View file

@ -96,7 +96,7 @@ namespace ts {
} }
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget): CompilerHost { function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget): CompilerHost {
const files: Map<SourceFileWithText> = {}; const files: MapLike<SourceFileWithText> = {};
for (const t of texts) { for (const t of texts) {
const file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target); const file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target);
file.sourceText = t.text; file.sourceText = t.text;
@ -152,7 +152,7 @@ namespace ts {
return program; return program;
} }
function getSizeOfMap(map: Map<any>): number { function getSizeOfMap(map: MapLike<any>): number {
let size = 0; let size = 0;
for (const id in map) { for (const id in map) {
if (hasProperty(map, id)) { if (hasProperty(map, id)) {
@ -174,7 +174,7 @@ namespace ts {
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`); 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: MapLike<T>, getCache: (f: SourceFile) => MapLike<T>, entryChecker: (expected: T, original: T) => void): void {
const file = program.getSourceFile(fileName); const file = program.getSourceFile(fileName);
assert.isTrue(file !== undefined, `cannot find file ${fileName}`); assert.isTrue(file !== undefined, `cannot find file ${fileName}`);
const cache = getCache(file); const cache = getCache(file);
@ -203,11 +203,11 @@ namespace ts {
} }
} }
function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map<ResolvedModule>): void { function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: MapLike<ResolvedModule>): void {
checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, checkResolvedModule); checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, checkResolvedModule);
} }
function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: Map<ResolvedTypeReferenceDirective>): void { function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: MapLike<ResolvedTypeReferenceDirective>): void {
checkCache("resolved type directives", program, fileName, expectedContent, f => f.resolvedTypeReferenceDirectiveNames, checkResolvedTypeDirective); checkCache("resolved type directives", program, fileName, expectedContent, f => f.resolvedTypeReferenceDirectiveNames, checkResolvedTypeDirective);
} }

View file

@ -106,7 +106,7 @@ namespace ts.server {
describe("onMessage", () => { describe("onMessage", () => {
it("should not throw when commands are executed with invalid arguments", () => { it("should not throw when commands are executed with invalid arguments", () => {
let i = 0; let i = 0;
for (name in CommandNames) { for (const name in CommandNames) {
if (!Object.prototype.hasOwnProperty.call(CommandNames, name)) { if (!Object.prototype.hasOwnProperty.call(CommandNames, name)) {
continue; continue;
} }
@ -362,8 +362,8 @@ namespace ts.server {
class InProcClient { class InProcClient {
private server: InProcSession; private server: InProcSession;
private seq = 0; private seq = 0;
private callbacks: ts.Map<(resp: protocol.Response) => void> = {}; private callbacks: ts.MapLike<(resp: protocol.Response) => void> = {};
private eventHandlers: ts.Map<(args: any) => void> = {}; private eventHandlers: ts.MapLike<(args: any) => void> = {};
handle(msg: protocol.Message): void { handle(msg: protocol.Message): void {
if (msg.type === "response") { if (msg.type === "response") {

View file

@ -68,7 +68,7 @@ namespace ts {
return entry; return entry;
} }
function sizeOfMap(map: Map<any>): number { function sizeOfMap(map: MapLike<any>): number {
let n = 0; let n = 0;
for (const name in map) { for (const name in map) {
if (hasProperty(map, name)) { if (hasProperty(map, name)) {
@ -78,7 +78,7 @@ namespace ts {
return n; return n;
} }
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) { function checkMapKeys(caption: string, map: MapLike<any>, expectedKeys: string[]) {
assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`); assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`);
for (const name of expectedKeys) { for (const name of expectedKeys) {
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`); assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`);
@ -126,8 +126,8 @@ namespace ts {
private getCanonicalFileName: (s: string) => string; private getCanonicalFileName: (s: string) => string;
private toPath: (f: string) => Path; private toPath: (f: string) => Path;
private callbackQueue: TimeOutCallback[] = []; private callbackQueue: TimeOutCallback[] = [];
readonly watchedDirectories: Map<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {}; readonly watchedDirectories: MapLike<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {};
readonly watchedFiles: Map<FileWatcherCallback[]> = {}; readonly watchedFiles: MapLike<FileWatcherCallback[]> = {};
constructor(public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: FileOrFolder[]) { constructor(public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: FileOrFolder[]) {
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);

View file

@ -226,7 +226,7 @@ interface NumberConstructor {
/** /**
* The value of the largest integer n such that n and n + 1 are both exactly representable as * The value of the largest integer n such that n and n + 1 are both exactly representable as
* a Number value. * a Number value.
* The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 1. * The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 1.
*/ */
readonly MAX_SAFE_INTEGER: number; readonly MAX_SAFE_INTEGER: number;
@ -343,6 +343,30 @@ interface ObjectConstructor {
defineProperty(o: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): any; 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 { interface RegExp {
/** /**
* Returns a string indicating the flags of the regular expression in question. This field is read-only. * Returns a string indicating the flags of the regular expression in question. This field is read-only.

View file

@ -63,6 +63,26 @@ interface ArrayConstructor {
from<T>(iterable: Iterable<T>): Array<T>; 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 { interface IArguments {
/** Iterator */ /** Iterator */
[Symbol.iterator](): IterableIterator<any>; [Symbol.iterator](): IterableIterator<any>;

5
src/lib/es5.d.ts vendored
View file

@ -1108,6 +1108,11 @@ interface Array<T> {
* Removes the last element from an array and returns it. * Removes the last element from an array and returns it.
*/ */
pop(): T | undefined; pop(): T | undefined;
/**
* Combines two or more arrays.
* @param items Additional items to add to the end of array1.
*/
concat(...items: T[][]): T[];
/** /**
* Combines two or more arrays. * Combines two or more arrays.
* @param items Additional items to add to the end of array1. * @param items Additional items to add to the end of array1.

View file

@ -21,7 +21,7 @@ namespace ts.server {
export class SessionClient implements LanguageService { export class SessionClient implements LanguageService {
private sequence: number = 0; private sequence: number = 0;
private lineMaps: ts.Map<number[]> = {}; private lineMaps: ts.Map<number[]> = ts.createMap<number[]>();
private messages: string[] = []; private messages: string[] = [];
private lastRenameEntry: RenameEntry; private lastRenameEntry: RenameEntry;

View file

@ -115,6 +115,9 @@ namespace ts.server {
readFile: fileName => this.host.readFile(fileName), readFile: fileName => this.host.readFile(fileName),
directoryExists: directoryName => this.host.directoryExists(directoryName) directoryExists: directoryName => this.host.directoryExists(directoryName)
}; };
if (this.host.realpath) {
this.moduleResolutionHost.realpath = path => this.host.realpath(path);
}
} }
private resolveNamesWithLocalCache<T extends Timestamped & { failedLookupLocations: string[] }, R>( private resolveNamesWithLocalCache<T extends Timestamped & { failedLookupLocations: string[] }, R>(
@ -127,7 +130,7 @@ namespace ts.server {
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const currentResolutionsInFile = cache.get(path); const currentResolutionsInFile = cache.get(path);
const newResolutions: Map<T> = {}; const newResolutions = createMap<T>();
const resolvedModules: R[] = []; const resolvedModules: R[] = [];
const compilerOptions = this.getCompilationSettings(); const compilerOptions = this.getCompilationSettings();
@ -383,7 +386,7 @@ namespace ts.server {
export interface ProjectOptions { export interface ProjectOptions {
// these fields can be present in the project file // these fields can be present in the project file
files?: string[]; files?: string[];
wildcardDirectories?: ts.Map<ts.WatchDirectoryFlags>; wildcardDirectories?: ts.MapLike<ts.WatchDirectoryFlags>;
compilerOptions?: ts.CompilerOptions; compilerOptions?: ts.CompilerOptions;
} }
@ -396,7 +399,7 @@ namespace ts.server {
// Used to keep track of what directories are watched for this project // Used to keep track of what directories are watched for this project
directoriesWatchedForTsconfig: string[] = []; directoriesWatchedForTsconfig: string[] = [];
program: ts.Program; program: ts.Program;
filenameToSourceFile: ts.Map<ts.SourceFile> = {}; filenameToSourceFile = ts.createMap<ts.SourceFile>();
updateGraphSeq = 0; updateGraphSeq = 0;
/** Used for configured projects which may have multiple open roots */ /** Used for configured projects which may have multiple open roots */
openRefCount = 0; openRefCount = 0;
@ -509,7 +512,7 @@ namespace ts.server {
return; return;
} }
this.filenameToSourceFile = {}; this.filenameToSourceFile = createMap<SourceFile>();
const sourceFiles = this.program.getSourceFiles(); const sourceFiles = this.program.getSourceFiles();
for (let i = 0, len = sourceFiles.length; i < len; i++) { for (let i = 0, len = sourceFiles.length; i < len; i++) {
const normFilename = ts.normalizePath(sourceFiles[i].fileName); const normFilename = ts.normalizePath(sourceFiles[i].fileName);
@ -618,7 +621,7 @@ namespace ts.server {
} }
export class ProjectService { export class ProjectService {
filenameToScriptInfo: ts.Map<ScriptInfo> = {}; filenameToScriptInfo = ts.createMap<ScriptInfo>();
// open, non-configured root files // open, non-configured root files
openFileRoots: ScriptInfo[] = []; openFileRoots: ScriptInfo[] = [];
// projects built from openFileRoots // projects built from openFileRoots
@ -630,12 +633,12 @@ namespace ts.server {
// open files that are roots of a configured project // open files that are roots of a configured project
openFileRootsConfigured: ScriptInfo[] = []; openFileRootsConfigured: ScriptInfo[] = [];
// a path to directory watcher map that detects added tsconfig files // 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 // count of how many projects are using the directory watcher. If the
// number becomes 0 for a watcher, then we should close it. // number becomes 0 for a watcher, then we should close it.
directoryWatchersRefCount: ts.Map<number> = {}; directoryWatchersRefCount = ts.createMap<number>();
hostConfiguration: HostConfiguration; hostConfiguration: HostConfiguration;
timerForDetectingProjectFileListChanges: Map<any> = {}; timerForDetectingProjectFileListChanges = createMap<any>();
constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) { constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) {
// ts.disableIncrementalParsing = true; // ts.disableIncrementalParsing = true;

View file

@ -1062,7 +1062,7 @@ namespace ts.server {
return { response, responseRequired: true }; return { response, responseRequired: true };
} }
private handlers: Map<(request: protocol.Request) => { response?: any, responseRequired?: boolean }> = { private handlers: MapLike<(request: protocol.Request) => { response?: any, responseRequired?: boolean }> = {
[CommandNames.Exit]: () => { [CommandNames.Exit]: () => {
this.exit(); this.exit();
return { responseRequired: false }; return { responseRequired: false };

View file

@ -10,6 +10,8 @@
"types": [] "types": []
}, },
"files": [ "files": [
"../services/shims.ts",
"../services/utilities.ts",
"editorServices.ts", "editorServices.ts",
"protocol.d.ts", "protocol.d.ts",
"session.ts" "session.ts"

View file

@ -453,9 +453,9 @@ namespace ts.formatting {
case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodDeclaration:
if ((<MethodDeclaration>node).asteriskToken) { if ((<MethodDeclaration>node).asteriskToken) {
return SyntaxKind.AsteriskToken; return SyntaxKind.AsteriskToken;
} }/*
// fall-through fall-through
*/
case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertyDeclaration:
case SyntaxKind.Parameter: case SyntaxKind.Parameter:
return (<Declaration>node).name.kind; return (<Declaration>node).name.kind;
@ -732,7 +732,7 @@ namespace ts.formatting {
else { else {
// indent token only if end line of previous range does not match start line of the token // indent token only if end line of previous range does not match start line of the token
const prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; const prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line;
indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine;
} }
} }
} }
@ -892,7 +892,7 @@ namespace ts.formatting {
} }
function indentationIsDifferent(indentationString: string, startLinePosition: number): boolean { function indentationIsDifferent(indentationString: string, startLinePosition: number): boolean {
return indentationString !== sourceFile.text.substr(startLinePosition , indentationString.length); return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length);
} }
function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean) { function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean) {
@ -936,7 +936,7 @@ namespace ts.formatting {
// shift all parts on the delta size // shift all parts on the delta size
const delta = indentation - nonWhitespaceColumnInFirstPart.column; const delta = indentation - nonWhitespaceColumnInFirstPart.column;
for (let i = startIndex, len = parts.length; i < len; i++, startLine++) { for (let i = startIndex, len = parts.length; i < len; i++ , startLine++) {
const startLinePos = getStartPositionOfLine(startLine, sourceFile); const startLinePos = getStartPositionOfLine(startLine, sourceFile);
const nonWhitespaceCharacterAndColumn = const nonWhitespaceCharacterAndColumn =
i === 0 i === 0

View file

@ -231,6 +231,13 @@ namespace ts.formatting {
public NoSpaceBeforeCloseBraceInJsxExpression: Rule; public NoSpaceBeforeCloseBraceInJsxExpression: Rule;
public SpaceBeforeCloseBraceInJsxExpression: Rule; public SpaceBeforeCloseBraceInJsxExpression: Rule;
// JSX opening elements
public SpaceBeforeJsxAttribute: Rule;
public SpaceBeforeSlashInJsxOpeningElement: Rule;
public NoSpaceBeforeGreaterThanTokenInJsxOpeningElement: Rule;
public NoSpaceBeforeEqualInJsxAttribute: Rule;
public NoSpaceAfterEqualInJsxAttribute: Rule;
constructor() { constructor() {
/// ///
/// Common Rules /// Common Rules
@ -322,7 +329,7 @@ namespace ts.formatting {
// Add a space between statements. All keywords except (do,else,case) has open/close parens after them. // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
// So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext, Rules.IsNotForContext), RuleAction.Space)); this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), RuleAction.Space));
// This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
this.SpaceAfterTryFinally = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword]), SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); this.SpaceAfterTryFinally = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword]), SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space));
@ -386,6 +393,13 @@ namespace ts.formatting {
// template string // template string
this.NoSpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete));
// jsx opening element
this.SpaceBeforeJsxAttribute = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), RuleAction.Space));
this.SpaceBeforeSlashInJsxOpeningElement = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SlashToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Space));
this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new Rule(RuleDescriptor.create1(SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete));
this.NoSpaceBeforeEqualInJsxAttribute = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.EqualsToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete));
this.NoSpaceAfterEqualInJsxAttribute = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete));
// These rules are higher in priority than user-configurable rules. // These rules are higher in priority than user-configurable rules.
this.HighPriorityCommonRules = [ this.HighPriorityCommonRules = [
this.IgnoreBeforeComment, this.IgnoreAfterLineComment, this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
@ -413,6 +427,8 @@ namespace ts.formatting {
this.SpaceAfterVoidOperator, this.SpaceAfterVoidOperator,
this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword,
this.NoSpaceBetweenTagAndTemplateString, this.NoSpaceBetweenTagAndTemplateString,
this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement,
this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute,
// TypeScript-specific rules // TypeScript-specific rules
this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport, this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
@ -450,8 +466,8 @@ namespace ts.formatting {
/// ///
// Insert space after comma delimiter // Insert space after comma delimiter
this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), RuleAction.Space)); this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), RuleAction.Space));
this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext), RuleAction.Delete)); this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), RuleAction.Delete));
// Insert space before and after binary operators // Insert space before and after binary operators
this.SpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); this.SpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
@ -498,10 +514,10 @@ namespace ts.formatting {
this.SpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); this.SpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space));
// No space after { and before } in JSX expression // No space after { and before } in JSX expression
this.NoSpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Delete)); this.NoSpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Delete));
this.SpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Space)); this.SpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Space));
this.NoSpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Delete)); this.NoSpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Delete));
this.SpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Space)); this.SpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Space));
// Insert space after function keyword for anonymous functions // Insert space after function keyword for anonymous functions
this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space));
@ -741,14 +757,26 @@ namespace ts.formatting {
return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText;
} }
static isNonJsxElementContext(context: FormattingContext): boolean { static IsNonJsxElementContext(context: FormattingContext): boolean {
return context.contextNode.kind !== SyntaxKind.JsxElement; return context.contextNode.kind !== SyntaxKind.JsxElement;
} }
static isJsxExpressionContext(context: FormattingContext): boolean { static IsJsxExpressionContext(context: FormattingContext): boolean {
return context.contextNode.kind === SyntaxKind.JsxExpression; return context.contextNode.kind === SyntaxKind.JsxExpression;
} }
static IsNextTokenParentJsxAttribute(context: FormattingContext): boolean {
return context.nextTokenParent.kind === SyntaxKind.JsxAttribute;
}
static IsJsxAttributeContext(context: FormattingContext): boolean {
return context.contextNode.kind === SyntaxKind.JsxAttribute;
}
static IsJsxSelfClosingElementContext(context: FormattingContext): boolean {
return context.contextNode.kind === SyntaxKind.JsxSelfClosingElement;
}
static IsNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean { static IsNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean {
return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context);
} }

View file

@ -47,7 +47,7 @@ namespace ts.JsTyping {
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } { { cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
// A typing name to typing file path mapping // A typing name to typing file path mapping
const inferredTypings: Map<string> = {}; const inferredTypings = createMap<string>();
if (!typingOptions || !typingOptions.enableAutoDiscovery) { if (!typingOptions || !typingOptions.enableAutoDiscovery) {
return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
@ -62,7 +62,7 @@ namespace ts.JsTyping {
safeList = result.config; safeList = result.config;
} }
else { else {
safeList = {}; safeList = createMap<string>();
}; };
} }

View file

@ -234,7 +234,7 @@ namespace ts.NavigationBar {
/** Merge declarations of the same kind. */ /** Merge declarations of the same kind. */
function mergeChildren(children: NavigationBarNode[]): void { function mergeChildren(children: NavigationBarNode[]): void {
const nameToItems: Map<NavigationBarNode | NavigationBarNode[]> = {}; const nameToItems = createMap<NavigationBarNode | NavigationBarNode[]>();
filterMutate(children, child => { filterMutate(children, child => {
const decl = <Declaration>child.node; const decl = <Declaration>child.node;
const name = decl.name && nodeText(decl.name); const name = decl.name && nodeText(decl.name);
@ -506,7 +506,7 @@ namespace ts.NavigationBar {
function convertToTopLevelItem(n: NavigationBarNode): NavigationBarItem { function convertToTopLevelItem(n: NavigationBarNode): NavigationBarItem {
return { return {
text: getItemName(n.node), text: getItemName(n.node),
kind: nodeKind(n.node), kind: getNodeKind(n.node),
kindModifiers: getNodeModifiers(n.node), kindModifiers: getNodeModifiers(n.node),
spans: getSpans(n), spans: getSpans(n),
childItems: map(n.children, convertToChildItem) || emptyChildItemArray, childItems: map(n.children, convertToChildItem) || emptyChildItemArray,
@ -518,7 +518,7 @@ namespace ts.NavigationBar {
function convertToChildItem(n: NavigationBarNode): NavigationBarItem { function convertToChildItem(n: NavigationBarNode): NavigationBarItem {
return { return {
text: getItemName(n.node), text: getItemName(n.node),
kind: nodeKind(n.node), kind: getNodeKind(n.node),
kindModifiers: getNodeModifiers(n.node), kindModifiers: getNodeModifiers(n.node),
spans: getSpans(n), spans: getSpans(n),
childItems: emptyChildItemArray, childItems: emptyChildItemArray,
@ -539,57 +539,6 @@ namespace ts.NavigationBar {
} }
} }
// TODO: GH#9145: We should just use getNodeKind. No reason why navigationBar and navigateTo should have different behaviors.
function nodeKind(node: Node): string {
switch (node.kind) {
case SyntaxKind.SourceFile:
return ScriptElementKind.moduleElement;
case SyntaxKind.EnumMember:
return ScriptElementKind.memberVariableElement;
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
let variableDeclarationNode: Node;
let name: Node;
if (node.kind === SyntaxKind.BindingElement) {
name = (<BindingElement>node).name;
variableDeclarationNode = node;
// binding elements are added only for variable declarations
// bubble up to the containing variable declaration
while (variableDeclarationNode && variableDeclarationNode.kind !== SyntaxKind.VariableDeclaration) {
variableDeclarationNode = variableDeclarationNode.parent;
}
Debug.assert(!!variableDeclarationNode);
}
else {
Debug.assert(!isBindingPattern((<VariableDeclaration>node).name));
variableDeclarationNode = node;
name = (<VariableDeclaration>node).name;
}
if (isConst(variableDeclarationNode)) {
return ts.ScriptElementKind.constElement;
}
else if (isLet(variableDeclarationNode)) {
return ts.ScriptElementKind.letElement;
}
else {
return ts.ScriptElementKind.variableElement;
}
case SyntaxKind.ArrowFunction:
return ts.ScriptElementKind.functionElement;
case SyntaxKind.JSDocTypedefTag:
return ScriptElementKind.typeElement;
default:
return getNodeKind(node);
}
}
function getModuleName(moduleDeclaration: ModuleDeclaration): string { function getModuleName(moduleDeclaration: ModuleDeclaration): string {
// We want to maintain quotation marks. // We want to maintain quotation marks.
if (isAmbientModule(moduleDeclaration)) { if (isAmbientModule(moduleDeclaration)) {

View file

@ -113,7 +113,7 @@ namespace ts {
// we see the name of a module that is used everywhere, or the name of an overload). As // 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 // 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. // pattern matcher so we don't have to compute it multiple times.
const stringToWordSpans: Map<TextSpan[]> = {}; const stringToWordSpans = createMap<TextSpan[]>();
pattern = pattern.trim(); pattern = pattern.trim();

View file

@ -975,7 +975,7 @@ namespace ts {
} }
private computeNamedDeclarations(): Map<Declaration[]> { private computeNamedDeclarations(): Map<Declaration[]> {
const result: Map<Declaration[]> = {}; const result = createMap<Declaration[]>();
forEachChild(this, visit); forEachChild(this, visit);
@ -1712,6 +1712,8 @@ namespace ts {
/** enum E */ /** enum E */
export const enumElement = "enum"; export const enumElement = "enum";
// TODO: GH#9983
export const enumMemberElement = "const";
/** /**
* Inside module and script only * Inside module and script only
@ -1915,7 +1917,7 @@ namespace ts {
}; };
} }
// Cache host information about scrip Should be refreshed // Cache host information about script should be refreshed
// at each language service public entry point, since we don't know when // at each language service public entry point, since we don't know when
// set of scripts handled by the host changes. // set of scripts handled by the host changes.
class HostCache { class HostCache {
@ -2054,7 +2056,7 @@ namespace ts {
fileName?: string; fileName?: string;
reportDiagnostics?: boolean; reportDiagnostics?: boolean;
moduleName?: string; moduleName?: string;
renamedDependencies?: Map<string>; renamedDependencies?: MapLike<string>;
} }
export interface TranspileOutput { export interface TranspileOutput {
@ -2278,7 +2280,7 @@ namespace ts {
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
// for those settings. // for those settings.
const buckets: Map<FileMap<DocumentRegistryEntry>> = {}; const buckets = createMap<FileMap<DocumentRegistryEntry>>();
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey { function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
@ -2988,7 +2990,10 @@ namespace ts {
/* @internal */ export function getNodeKind(node: Node): string { /* @internal */ export function getNodeKind(node: Node): string {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement; case SyntaxKind.SourceFile:
return isExternalModule(<SourceFile>node) ? ScriptElementKind.moduleElement : ScriptElementKind.scriptElement;
case SyntaxKind.ModuleDeclaration:
return ScriptElementKind.moduleElement;
case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression: case SyntaxKind.ClassExpression:
return ScriptElementKind.classElement; return ScriptElementKind.classElement;
@ -2996,11 +3001,10 @@ namespace ts {
case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement; case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement;
case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement; case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement;
case SyntaxKind.VariableDeclaration: case SyntaxKind.VariableDeclaration:
return isConst(node) return getKindOfVariableDeclaration(<VariableDeclaration>node);
? ScriptElementKind.constElement case SyntaxKind.BindingElement:
: isLet(node) return getKindOfVariableDeclaration(<VariableDeclaration>getRootDeclaration(node));
? ScriptElementKind.letElement case SyntaxKind.ArrowFunction:
: ScriptElementKind.variableElement;
case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionExpression:
return ScriptElementKind.functionElement; return ScriptElementKind.functionElement;
@ -3017,7 +3021,7 @@ namespace ts {
case SyntaxKind.CallSignature: return ScriptElementKind.callSignatureElement; case SyntaxKind.CallSignature: return ScriptElementKind.callSignatureElement;
case SyntaxKind.Constructor: return ScriptElementKind.constructorImplementationElement; case SyntaxKind.Constructor: return ScriptElementKind.constructorImplementationElement;
case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement; case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement;
case SyntaxKind.EnumMember: return ScriptElementKind.variableElement; case SyntaxKind.EnumMember: return ScriptElementKind.enumMemberElement;
case SyntaxKind.Parameter: return (node.flags & NodeFlags.ParameterPropertyModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement; case SyntaxKind.Parameter: return (node.flags & NodeFlags.ParameterPropertyModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportSpecifier:
@ -3025,8 +3029,19 @@ namespace ts {
case SyntaxKind.ExportSpecifier: case SyntaxKind.ExportSpecifier:
case SyntaxKind.NamespaceImport: case SyntaxKind.NamespaceImport:
return ScriptElementKind.alias; return ScriptElementKind.alias;
case SyntaxKind.JSDocTypedefTag:
return ScriptElementKind.typeElement;
default:
return ScriptElementKind.unknown;
}
function getKindOfVariableDeclaration(v: VariableDeclaration): string {
return isConst(v)
? ScriptElementKind.constElement
: isLet(v)
? ScriptElementKind.letElement
: ScriptElementKind.variableElement;
} }
return ScriptElementKind.unknown;
} }
class CancellationTokenObject implements CancellationToken { class CancellationTokenObject implements CancellationToken {
@ -3116,14 +3131,16 @@ namespace ts {
const oldSettings = program && program.getCompilerOptions(); const oldSettings = program && program.getCompilerOptions();
const newSettings = hostCache.compilationSettings(); const newSettings = hostCache.compilationSettings();
const changesInCompilationSettingsAffectSyntax = oldSettings && const shouldCreateNewSourceFiles = oldSettings &&
(oldSettings.target !== newSettings.target || (oldSettings.target !== newSettings.target ||
oldSettings.module !== newSettings.module || oldSettings.module !== newSettings.module ||
oldSettings.moduleResolution !== newSettings.moduleResolution || oldSettings.moduleResolution !== newSettings.moduleResolution ||
oldSettings.noResolve !== newSettings.noResolve || oldSettings.noResolve !== newSettings.noResolve ||
oldSettings.jsx !== newSettings.jsx || oldSettings.jsx !== newSettings.jsx ||
oldSettings.allowJs !== newSettings.allowJs || oldSettings.allowJs !== newSettings.allowJs ||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit); oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit ||
oldSettings.baseUrl !== newSettings.baseUrl ||
!mapIsEqualTo(oldSettings.paths, newSettings.paths));
// Now create a new compiler // Now create a new compiler
const compilerHost: CompilerHost = { const compilerHost: CompilerHost = {
@ -3175,7 +3192,7 @@ namespace ts {
const oldSourceFiles = program.getSourceFiles(); const oldSourceFiles = program.getSourceFiles();
const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings); const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings);
for (const oldSourceFile of oldSourceFiles) { for (const oldSourceFile of oldSourceFiles) {
if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || shouldCreateNewSourceFiles) {
documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey);
} }
} }
@ -3209,7 +3226,7 @@ namespace ts {
// Check if the language version has changed since we last created a program; if they are the same, // Check if the language version has changed since we last created a program; if they are the same,
// it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile
// can not be reused. we have to dump all syntax trees and create new ones. // can not be reused. we have to dump all syntax trees and create new ones.
if (!changesInCompilationSettingsAffectSyntax) { if (!shouldCreateNewSourceFiles) {
// Check if the old program had this file already // Check if the old program had this file already
const oldSourceFile = program && program.getSourceFileByPath(path); const oldSourceFile = program && program.getSourceFileByPath(path);
if (oldSourceFile) { if (oldSourceFile) {
@ -4126,7 +4143,7 @@ namespace ts {
* do not occur at the current position and have not otherwise been typed. * do not occur at the current position and have not otherwise been typed.
*/ */
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] {
const existingImportsOrExports: Map<boolean> = {}; const existingImportsOrExports = createMap<boolean>();
for (const element of namedImportsOrExports) { for (const element of namedImportsOrExports) {
// If this is the current item we are editing right now, do not filter it out // If this is the current item we are editing right now, do not filter it out
@ -4156,7 +4173,7 @@ namespace ts {
return contextualMemberSymbols; return contextualMemberSymbols;
} }
const existingMemberNames: Map<boolean> = {}; const existingMemberNames = createMap<boolean>();
for (const m of existingMembers) { for (const m of existingMembers) {
// Ignore omitted expressions for missing members // Ignore omitted expressions for missing members
if (m.kind !== SyntaxKind.PropertyAssignment && if (m.kind !== SyntaxKind.PropertyAssignment &&
@ -4199,7 +4216,7 @@ namespace ts {
* do not occur at the current position and have not otherwise been typed. * do not occur at the current position and have not otherwise been typed.
*/ */
function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>): Symbol[] { function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>): Symbol[] {
const seenNames: Map<boolean> = {}; const seenNames = createMap<boolean>();
for (const attr of attributes) { for (const attr of attributes) {
// If this is the current item we are editing right now, do not filter it out // If this is the current item we are editing right now, do not filter it out
if (attr.getStart() <= position && position <= attr.getEnd()) { if (attr.getStart() <= position && position <= attr.getEnd()) {
@ -4341,7 +4358,7 @@ namespace ts {
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> { function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
const start = timestamp(); const start = timestamp();
const uniqueNames: Map<string> = {}; const uniqueNames = createMap<string>();
if (symbols) { if (symbols) {
for (const symbol of symbols) { for (const symbol of symbols) {
const entry = createCompletionEntry(symbol, location, performCharacterChecks); const entry = createCompletionEntry(symbol, location, performCharacterChecks);
@ -5319,7 +5336,14 @@ namespace ts {
} }
if (symbolFlags & SymbolFlags.Alias) { if (symbolFlags & SymbolFlags.Alias) {
addNewLineIfDisplayPartsExist(); addNewLineIfDisplayPartsExist();
displayParts.push(keywordPart(SyntaxKind.ImportKeyword)); if (symbol.declarations[0].kind === SyntaxKind.NamespaceExportDeclaration) {
displayParts.push(keywordPart(SyntaxKind.ExportKeyword));
displayParts.push(spacePart());
displayParts.push(keywordPart(SyntaxKind.NamespaceKeyword));
}
else {
displayParts.push(keywordPart(SyntaxKind.ImportKeyword));
}
displayParts.push(spacePart()); displayParts.push(spacePart());
addFullSymbolName(symbol); addFullSymbolName(symbol);
ts.forEach(symbol.declarations, declaration => { ts.forEach(symbol.declarations, declaration => {
@ -5800,7 +5824,7 @@ namespace ts {
return undefined; return undefined;
} }
const fileNameToDocumentHighlights: Map<DocumentHighlights> = {}; const fileNameToDocumentHighlights = createMap<DocumentHighlights>();
const result: DocumentHighlights[] = []; const result: DocumentHighlights[] = [];
for (const referencedSymbol of referencedSymbols) { for (const referencedSymbol of referencedSymbols) {
for (const referenceEntry of referencedSymbol.references) { for (const referenceEntry of referencedSymbol.references) {
@ -7185,7 +7209,7 @@ namespace ts {
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions // 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)) { 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>());
} }
}); });
@ -7306,7 +7330,7 @@ namespace ts {
// see if any is in the list // see if any is in the list
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
const result: Symbol[] = []; 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); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
} }
@ -8791,7 +8815,7 @@ namespace ts {
} }
function initializeNameTable(sourceFile: SourceFile): void { function initializeNameTable(sourceFile: SourceFile): void {
const nameTable: Map<number> = {}; const nameTable = createMap<number>();
walk(sourceFile); walk(sourceFile);
sourceFile.nameTable = nameTable; sourceFile.nameTable = nameTable;

View file

@ -77,8 +77,13 @@ namespace ts {
directoryExists(directoryName: string): boolean; directoryExists(directoryName: string): boolean;
} }
/** Public interface of the the of a config service shim instance.*/ /** Public interface of the core-services host instance used in managed side */
export interface CoreServicesShimHost extends Logger, ModuleResolutionHost { export interface CoreServicesShimHost extends Logger {
directoryExists(directoryName: string): boolean;
fileExists(fileName: string): boolean;
getCurrentDirectory(): string;
getDirectories(path: string): string;
/** /**
* Returns a JSON-encoded value of the type: string[] * Returns a JSON-encoded value of the type: string[]
* *
@ -86,9 +91,14 @@ namespace ts {
* when enumerating the directory. * when enumerating the directory.
*/ */
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
useCaseSensitiveFileNames?(): boolean;
getCurrentDirectory(): string; /**
* Read arbitary text files on disk, i.e. when resolution procedure needs the content of 'package.json' to determine location of bundled typings for node modules
*/
readFile(fileName: string): string;
realpath?(path: string): string;
trace(s: string): void; trace(s: string): void;
useCaseSensitiveFileNames?(): boolean;
} }
/// ///
@ -246,6 +256,7 @@ namespace ts {
} }
export interface CoreServicesShim extends Shim { export interface CoreServicesShim extends Shim {
getAutomaticTypeDirectiveNames(compilerOptionsJson: string): string;
getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
getDefaultCompilationSettings(): string; getDefaultCompilationSettings(): string;
@ -524,6 +535,10 @@ namespace ts {
private readDirectoryFallback(rootDir: string, extension: string, exclude: string[]) { private readDirectoryFallback(rootDir: string, extension: string, exclude: string[]) {
return JSON.parse(this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude))); return JSON.parse(this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)));
} }
public getDirectories(path: string): string[] {
return JSON.parse(this.shimHost.getDirectories(path));
}
} }
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): any { function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): any {
@ -1042,7 +1057,7 @@ namespace ts {
public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string { public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
return this.forwardJSONCall( return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')", `getPreProcessedFileInfo('${fileName}')`,
() => { () => {
// for now treat files as JavaScript // for now treat files as JavaScript
const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true); const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
@ -1056,6 +1071,16 @@ namespace ts {
}); });
} }
public getAutomaticTypeDirectiveNames(compilerOptionsJson: string): string {
return this.forwardJSONCall(
`getAutomaticTypeDirectiveNames('${compilerOptionsJson}')`,
() => {
const compilerOptions = <CompilerOptions>JSON.parse(compilerOptionsJson);
return getAutomaticTypeDirectiveNames(compilerOptions, this.host);
}
);
}
private convertFileReferences(refs: FileReference[]): IFileReference[] { private convertFileReferences(refs: FileReference[]): IFileReference[] {
if (!refs) { if (!refs) {
return undefined; return undefined;

View file

@ -20,7 +20,7 @@ declare var path: any;
import * as ts from "typescript"; import * as ts from "typescript";
function watch(rootFileNames: string[], options: ts.CompilerOptions) { function watch(rootFileNames: string[], options: ts.CompilerOptions) {
const files: ts.Map<{ version: number }> = {}; const files: ts.MapLike<{ version: number }> = {};
// initialize the list of files // initialize the list of files
rootFileNames.forEach(fileName => { rootFileNames.forEach(fileName => {

View file

@ -0,0 +1,31 @@
//// [abstractClassInLocalScope.ts]
(() => {
abstract class A {}
class B extends A {}
new B();
return A;
})();
//// [abstractClassInLocalScope.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 __());
};
(function () {
var A = (function () {
function A() {
}
return A;
}());
var B = (function (_super) {
__extends(B, _super);
function B() {
_super.apply(this, arguments);
}
return B;
}(A));
new B();
return A;
})();

View file

@ -0,0 +1,17 @@
=== tests/cases/compiler/abstractClassInLocalScope.ts ===
(() => {
abstract class A {}
>A : Symbol(A, Decl(abstractClassInLocalScope.ts, 0, 8))
class B extends A {}
>B : Symbol(B, Decl(abstractClassInLocalScope.ts, 1, 23))
>A : Symbol(A, Decl(abstractClassInLocalScope.ts, 0, 8))
new B();
>B : Symbol(B, Decl(abstractClassInLocalScope.ts, 1, 23))
return A;
>A : Symbol(A, Decl(abstractClassInLocalScope.ts, 0, 8))
})();

View file

@ -0,0 +1,22 @@
=== tests/cases/compiler/abstractClassInLocalScope.ts ===
(() => {
>(() => { abstract class A {} class B extends A {} new B(); return A;})() : typeof A
>(() => { abstract class A {} class B extends A {} new B(); return A;}) : () => typeof A
>() => { abstract class A {} class B extends A {} new B(); return A;} : () => typeof A
abstract class A {}
>A : A
class B extends A {}
>B : B
>A : A
new B();
>new B() : B
>B : typeof B
return A;
>A : typeof A
})();

View file

@ -0,0 +1,13 @@
tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts(4,5): error TS2511: Cannot create an instance of the abstract class 'A'.
==== tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts (1 errors) ====
(() => {
abstract class A {}
class B extends A {}
new A();
~~~~~~~
!!! error TS2511: Cannot create an instance of the abstract class 'A'.
new B();
})()

View file

@ -0,0 +1,31 @@
//// [abstractClassInLocalScopeIsAbstract.ts]
(() => {
abstract class A {}
class B extends A {}
new A();
new B();
})()
//// [abstractClassInLocalScopeIsAbstract.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 __());
};
(function () {
var A = (function () {
function A() {
}
return A;
}());
var B = (function (_super) {
__extends(B, _super);
function B() {
_super.apply(this, arguments);
}
return B;
}(A));
new A();
new B();
})();

View file

@ -0,0 +1,17 @@
tests/cases/compiler/a.ts(2,5): error TS2339: Property 'default' does not exist on type 'typeof "tests/cases/compiler/b"'.
tests/cases/compiler/a.ts(3,5): error TS2339: Property 'default' does not exist on type 'typeof "tests/cases/compiler/b"'.
==== tests/cases/compiler/a.ts (2 errors) ====
import Foo = require("./b");
Foo.default.bar();
~~~~~~~
!!! error TS2339: Property 'default' does not exist on type 'typeof "tests/cases/compiler/b"'.
Foo.default.default.foo();
~~~~~~~
!!! error TS2339: Property 'default' does not exist on type 'typeof "tests/cases/compiler/b"'.
==== tests/cases/compiler/b.d.ts (0 errors) ====
export function foo();
export function bar();

View file

@ -0,0 +1,17 @@
//// [tests/cases/compiler/allowSyntheticDefaultImports10.ts] ////
//// [b.d.ts]
export function foo();
export function bar();
//// [a.ts]
import Foo = require("./b");
Foo.default.bar();
Foo.default.default.foo();
//// [a.js]
"use strict";
var Foo = require("./b");
Foo.default.bar();
Foo.default.default.foo();

View file

@ -0,0 +1,28 @@
//// [tests/cases/compiler/allowSyntheticDefaultImports7.ts] ////
//// [b.d.ts]
export function foo();
export function bar();
//// [a.ts]
import { default as Foo } from "./b";
Foo.bar();
Foo.foo();
//// [a.js]
System.register(["./b"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var b_1;
return {
setters:[
function (b_1_1) {
b_1 = b_1_1;
}],
execute: function() {
b_1["default"].bar();
b_1["default"].foo();
}
}
});

View file

@ -0,0 +1,22 @@
=== tests/cases/compiler/b.d.ts ===
export function foo();
>foo : Symbol(foo, Decl(b.d.ts, 0, 0))
export function bar();
>bar : Symbol(bar, Decl(b.d.ts, 0, 22))
=== tests/cases/compiler/a.ts ===
import { default as Foo } from "./b";
>default : Symbol(Foo, Decl(a.ts, 0, 8))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
Foo.bar();
>Foo.bar : Symbol(Foo.bar, Decl(b.d.ts, 0, 22))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
>bar : Symbol(Foo.bar, Decl(b.d.ts, 0, 22))
Foo.foo();
>Foo.foo : Symbol(Foo.foo, Decl(b.d.ts, 0, 0))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
>foo : Symbol(Foo.foo, Decl(b.d.ts, 0, 0))

View file

@ -0,0 +1,24 @@
=== tests/cases/compiler/b.d.ts ===
export function foo();
>foo : () => any
export function bar();
>bar : () => any
=== tests/cases/compiler/a.ts ===
import { default as Foo } from "./b";
>default : typeof Foo
>Foo : typeof Foo
Foo.bar();
>Foo.bar() : any
>Foo.bar : () => any
>Foo : typeof Foo
>bar : () => any
Foo.foo();
>Foo.foo() : any
>Foo.foo : () => any
>Foo : typeof Foo
>foo : () => any

View file

@ -0,0 +1,14 @@
tests/cases/compiler/a.ts(1,10): error TS2305: Module '"tests/cases/compiler/b"' has no exported member 'default'.
==== tests/cases/compiler/b.d.ts (0 errors) ====
export function foo();
export function bar();
==== tests/cases/compiler/a.ts (1 errors) ====
import { default as Foo } from "./b";
~~~~~~~
!!! error TS2305: Module '"tests/cases/compiler/b"' has no exported member 'default'.
Foo.bar();
Foo.foo();

View file

@ -0,0 +1,28 @@
//// [tests/cases/compiler/allowSyntheticDefaultImports8.ts] ////
//// [b.d.ts]
export function foo();
export function bar();
//// [a.ts]
import { default as Foo } from "./b";
Foo.bar();
Foo.foo();
//// [a.js]
System.register(["./b"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var b_1;
return {
setters:[
function (b_1_1) {
b_1 = b_1_1;
}],
execute: function() {
b_1["default"].bar();
b_1["default"].foo();
}
}
});

View file

@ -0,0 +1,17 @@
//// [tests/cases/compiler/allowSyntheticDefaultImports9.ts] ////
//// [b.d.ts]
export function foo();
export function bar();
//// [a.ts]
import { default as Foo } from "./b";
Foo.bar();
Foo.foo();
//// [a.js]
"use strict";
var b_1 = require("./b");
b_1["default"].bar();
b_1["default"].foo();

View file

@ -0,0 +1,22 @@
=== tests/cases/compiler/b.d.ts ===
export function foo();
>foo : Symbol(foo, Decl(b.d.ts, 0, 0))
export function bar();
>bar : Symbol(bar, Decl(b.d.ts, 0, 22))
=== tests/cases/compiler/a.ts ===
import { default as Foo } from "./b";
>default : Symbol(Foo, Decl(a.ts, 0, 8))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
Foo.bar();
>Foo.bar : Symbol(Foo.bar, Decl(b.d.ts, 0, 22))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
>bar : Symbol(Foo.bar, Decl(b.d.ts, 0, 22))
Foo.foo();
>Foo.foo : Symbol(Foo.foo, Decl(b.d.ts, 0, 0))
>Foo : Symbol(Foo, Decl(a.ts, 0, 8))
>foo : Symbol(Foo.foo, Decl(b.d.ts, 0, 0))

View file

@ -0,0 +1,24 @@
=== tests/cases/compiler/b.d.ts ===
export function foo();
>foo : () => any
export function bar();
>bar : () => any
=== tests/cases/compiler/a.ts ===
import { default as Foo } from "./b";
>default : typeof Foo
>Foo : typeof Foo
Foo.bar();
>Foo.bar() : any
>Foo.bar : () => any
>Foo : typeof Foo
>bar : () => any
Foo.foo();
>Foo.foo() : any
>Foo.foo : () => any
>Foo : typeof Foo
>foo : () => any

View file

@ -0,0 +1,13 @@
=== tests/cases/compiler/a.d.ts ===
declare namespace ns {
>ns : Symbol(ns, Decl(a.d.ts, 0, 0))
class SecondNS extends FirstNS { }
>SecondNS : Symbol(SecondNS, Decl(a.d.ts, 1, 22))
>FirstNS : Symbol(FirstNS, Decl(a.d.ts, 2, 36))
class FirstNS { }
>FirstNS : Symbol(FirstNS, Decl(a.d.ts, 2, 36))
}

View file

@ -0,0 +1,13 @@
=== tests/cases/compiler/a.d.ts ===
declare namespace ns {
>ns : typeof ns
class SecondNS extends FirstNS { }
>SecondNS : SecondNS
>FirstNS : FirstNS
class FirstNS { }
>FirstNS : FirstNS
}

View file

@ -3,21 +3,21 @@ var a: string[] = [];
>a : Symbol(a, Decl(arrayConcat2.ts, 0, 3)) >a : Symbol(a, Decl(arrayConcat2.ts, 0, 3))
a.concat("hello", 'world'); a.concat("hello", 'world');
>a.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >a.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>a : Symbol(a, Decl(arrayConcat2.ts, 0, 3)) >a : Symbol(a, Decl(arrayConcat2.ts, 0, 3))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
a.concat('Hello'); a.concat('Hello');
>a.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >a.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>a : Symbol(a, Decl(arrayConcat2.ts, 0, 3)) >a : Symbol(a, Decl(arrayConcat2.ts, 0, 3))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
var b = new Array<string>(); var b = new Array<string>();
>b : Symbol(b, Decl(arrayConcat2.ts, 5, 3)) >b : Symbol(b, Decl(arrayConcat2.ts, 5, 3))
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
b.concat('hello'); b.concat('hello');
>b.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >b.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>b : Symbol(b, Decl(arrayConcat2.ts, 5, 3)) >b : Symbol(b, Decl(arrayConcat2.ts, 5, 3))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

View file

@ -5,17 +5,17 @@ var a: string[] = [];
a.concat("hello", 'world'); a.concat("hello", 'world');
>a.concat("hello", 'world') : string[] >a.concat("hello", 'world') : string[]
>a.concat : (...items: (string | string[])[]) => string[] >a.concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>a : string[] >a : string[]
>concat : (...items: (string | string[])[]) => string[] >concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>"hello" : string >"hello" : string
>'world' : string >'world' : string
a.concat('Hello'); a.concat('Hello');
>a.concat('Hello') : string[] >a.concat('Hello') : string[]
>a.concat : (...items: (string | string[])[]) => string[] >a.concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>a : string[] >a : string[]
>concat : (...items: (string | string[])[]) => string[] >concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>'Hello' : string >'Hello' : string
var b = new Array<string>(); var b = new Array<string>();
@ -25,8 +25,8 @@ var b = new Array<string>();
b.concat('hello'); b.concat('hello');
>b.concat('hello') : string[] >b.concat('hello') : string[]
>b.concat : (...items: (string | string[])[]) => string[] >b.concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>b : string[] >b : string[]
>concat : (...items: (string | string[])[]) => string[] >concat : { (...items: string[][]): string[]; (...items: (string | string[])[]): string[]; }
>'hello' : string >'hello' : string

View file

@ -2,8 +2,8 @@
var x = [].concat([{ a: 1 }], [{ a: 2 }]) var x = [].concat([{ a: 1 }], [{ a: 2 }])
>x : Symbol(x, Decl(arrayConcatMap.ts, 0, 3)) >x : Symbol(x, Decl(arrayConcatMap.ts, 0, 3))
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>[].concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >[].concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>a : Symbol(a, Decl(arrayConcatMap.ts, 0, 20)) >a : Symbol(a, Decl(arrayConcatMap.ts, 0, 20))
>a : Symbol(a, Decl(arrayConcatMap.ts, 0, 32)) >a : Symbol(a, Decl(arrayConcatMap.ts, 0, 32))

View file

@ -4,9 +4,9 @@ var x = [].concat([{ a: 1 }], [{ a: 2 }])
>[].concat([{ a: 1 }], [{ a: 2 }]) .map(b => b.a) : any[] >[].concat([{ a: 1 }], [{ a: 2 }]) .map(b => b.a) : any[]
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] >[].concat([{ a: 1 }], [{ a: 2 }]) .map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
>[].concat([{ a: 1 }], [{ a: 2 }]) : any[] >[].concat([{ a: 1 }], [{ a: 2 }]) : any[]
>[].concat : (...items: any[]) => any[] >[].concat : { (...items: any[][]): any[]; (...items: any[]): any[]; }
>[] : undefined[] >[] : undefined[]
>concat : (...items: any[]) => any[] >concat : { (...items: any[][]): any[]; (...items: any[]): any[]; }
>[{ a: 1 }] : { a: number; }[] >[{ a: 1 }] : { a: number; }[]
>{ a: 1 } : { a: number; } >{ a: 1 } : { a: number; }
>a : number >a : number

View file

@ -0,0 +1,19 @@
//// [asOpEmitParens.ts]
declare var x;
// Must emit as (x + 1) * 3
(x + 1 as number) * 3;
// Should still emit as x.y
(x as any).y;
// Emit as new (x())
new (x() as any);
//// [asOpEmitParens.js]
// Must emit as (x + 1) * 3
(x + 1) * 3;
// Should still emit as x.y
x.y;
// Emit as new (x())
new (x());

View file

@ -0,0 +1,16 @@
=== tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts ===
declare var x;
>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11))
// Must emit as (x + 1) * 3
(x + 1 as number) * 3;
>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11))
// Should still emit as x.y
(x as any).y;
>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11))
// Emit as new (x())
new (x() as any);
>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11))

View file

@ -0,0 +1,30 @@
=== tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts ===
declare var x;
>x : any
// Must emit as (x + 1) * 3
(x + 1 as number) * 3;
>(x + 1 as number) * 3 : number
>(x + 1 as number) : number
>x + 1 as number : number
>x + 1 : any
>x : any
>1 : number
>3 : number
// Should still emit as x.y
(x as any).y;
>(x as any).y : any
>(x as any) : any
>x as any : any
>x : any
>y : any
// Emit as new (x())
new (x() as any);
>new (x() as any) : any
>(x() as any) : any
>x() as any : any
>x() : any
>x : any

View file

@ -1,4 +1,20 @@
//// [baseTypeWrappingInstantiationChain.ts] //// [baseTypeWrappingInstantiationChain.ts]
class CBaseBase<T3> {
constructor(x: Parameter<T3>) { }
}
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
}
class Parameter<T4> {
method(t: T4) { }
}
class Wrapper<T5> {
property: T5;
}
class C<T1> extends CBase<T1> { class C<T1> extends CBase<T1> {
public works() { public works() {
new CBaseBase<Wrapper<T1>>(this); new CBaseBase<Wrapper<T1>>(this);
@ -9,22 +25,7 @@ class C<T1> extends CBase<T1> {
public method(t: Wrapper<T1>) { } public method(t: Wrapper<T1>) { }
} }
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
}
class CBaseBase<T3> {
constructor(x: Parameter<T3>) { }
}
class Parameter<T4> {
method(t: T4) { }
}
class Wrapper<T5> {
property: T5;
}
//// [baseTypeWrappingInstantiationChain.js] //// [baseTypeWrappingInstantiationChain.js]
var __extends = (this && this.__extends) || function (d, b) { var __extends = (this && this.__extends) || function (d, b) {
@ -32,6 +33,29 @@ var __extends = (this && this.__extends) || function (d, b) {
function __() { this.constructor = d; } function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}; };
var CBaseBase = (function () {
function CBaseBase(x) {
}
return CBaseBase;
}());
var CBase = (function (_super) {
__extends(CBase, _super);
function CBase() {
_super.apply(this, arguments);
}
return CBase;
}(CBaseBase));
var Parameter = (function () {
function Parameter() {
}
Parameter.prototype.method = function (t) { };
return Parameter;
}());
var Wrapper = (function () {
function Wrapper() {
}
return Wrapper;
}());
var C = (function (_super) { var C = (function (_super) {
__extends(C, _super); __extends(C, _super);
function C() { function C() {
@ -46,26 +70,3 @@ var C = (function (_super) {
C.prototype.method = function (t) { }; C.prototype.method = function (t) { };
return C; return C;
}(CBase)); }(CBase));
var CBase = (function (_super) {
__extends(CBase, _super);
function CBase() {
_super.apply(this, arguments);
}
return CBase;
}(CBaseBase));
var CBaseBase = (function () {
function CBaseBase(x) {
}
return CBaseBase;
}());
var Parameter = (function () {
function Parameter() {
}
Parameter.prototype.method = function (t) { };
return Parameter;
}());
var Wrapper = (function () {
function Wrapper() {
}
return Wrapper;
}());

View file

@ -1,69 +1,70 @@
=== tests/cases/compiler/baseTypeWrappingInstantiationChain.ts === === tests/cases/compiler/baseTypeWrappingInstantiationChain.ts ===
class C<T1> extends CBase<T1> { class CBaseBase<T3> {
>C : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0)) >CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8)) >T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 0, 16))
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
public works() { constructor(x: Parameter<T3>) { }
>works : Symbol(C.works, Decl(baseTypeWrappingInstantiationChain.ts, 0, 31)) >x : Symbol(x, Decl(baseTypeWrappingInstantiationChain.ts, 1, 16))
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 6, 1))
new CBaseBase<Wrapper<T1>>(this); >T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 0, 16))
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1))
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
}
public alsoWorks() {
>alsoWorks : Symbol(C.alsoWorks, Decl(baseTypeWrappingInstantiationChain.ts, 3, 5))
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
}
public method(t: Wrapper<T1>) { }
>method : Symbol(C.method, Decl(baseTypeWrappingInstantiationChain.ts, 6, 5))
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 8, 18))
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
} }
class CBase<T2> extends CBaseBase<Wrapper<T2>> { class CBase<T2> extends CBaseBase<Wrapper<T2>> {
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1)) >CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 11, 12)) >T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 4, 12))
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1)) >CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1)) >Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 11, 12)) >T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 4, 12))
} }
class CBaseBase<T3> {
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1))
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 15, 16))
constructor(x: Parameter<T3>) { }
>x : Symbol(x, Decl(baseTypeWrappingInstantiationChain.ts, 16, 16))
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 17, 1))
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 15, 16))
}
class Parameter<T4> { class Parameter<T4> {
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 17, 1)) >Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 6, 1))
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 19, 16)) >T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 8, 16))
method(t: T4) { } method(t: T4) { }
>method : Symbol(Parameter.method, Decl(baseTypeWrappingInstantiationChain.ts, 19, 21)) >method : Symbol(Parameter.method, Decl(baseTypeWrappingInstantiationChain.ts, 8, 21))
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 20, 11)) >t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 9, 11))
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 19, 16)) >T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 8, 16))
} }
class Wrapper<T5> { class Wrapper<T5> {
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1)) >Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 23, 14)) >T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 12, 14))
property: T5; property: T5;
>property : Symbol(Wrapper.property, Decl(baseTypeWrappingInstantiationChain.ts, 23, 19)) >property : Symbol(Wrapper.property, Decl(baseTypeWrappingInstantiationChain.ts, 12, 19))
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 23, 14)) >T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 12, 14))
} }
class C<T1> extends CBase<T1> {
>C : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
public works() {
>works : Symbol(C.works, Decl(baseTypeWrappingInstantiationChain.ts, 16, 31))
new CBaseBase<Wrapper<T1>>(this);
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
}
public alsoWorks() {
>alsoWorks : Symbol(C.alsoWorks, Decl(baseTypeWrappingInstantiationChain.ts, 19, 5))
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
}
public method(t: Wrapper<T1>) { }
>method : Symbol(C.method, Decl(baseTypeWrappingInstantiationChain.ts, 22, 5))
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 24, 18))
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
}

View file

@ -1,4 +1,42 @@
=== tests/cases/compiler/baseTypeWrappingInstantiationChain.ts === === tests/cases/compiler/baseTypeWrappingInstantiationChain.ts ===
class CBaseBase<T3> {
>CBaseBase : CBaseBase<T3>
>T3 : T3
constructor(x: Parameter<T3>) { }
>x : Parameter<T3>
>Parameter : Parameter<T4>
>T3 : T3
}
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
>CBase : CBase<T2>
>T2 : T2
>CBaseBase : CBaseBase<Wrapper<T2>>
>Wrapper : Wrapper<T5>
>T2 : T2
}
class Parameter<T4> {
>Parameter : Parameter<T4>
>T4 : T4
method(t: T4) { }
>method : (t: T4) => void
>t : T4
>T4 : T4
}
class Wrapper<T5> {
>Wrapper : Wrapper<T5>
>T5 : T5
property: T5;
>property : T5
>T5 : T5
}
class C<T1> extends CBase<T1> { class C<T1> extends CBase<T1> {
>C : C<T1> >C : C<T1>
>T1 : T1 >T1 : T1
@ -32,40 +70,3 @@ class C<T1> extends CBase<T1> {
>T1 : T1 >T1 : T1
} }
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
>CBase : CBase<T2>
>T2 : T2
>CBaseBase : CBaseBase<Wrapper<T2>>
>Wrapper : Wrapper<T5>
>T2 : T2
}
class CBaseBase<T3> {
>CBaseBase : CBaseBase<T3>
>T3 : T3
constructor(x: Parameter<T3>) { }
>x : Parameter<T3>
>Parameter : Parameter<T4>
>T3 : T3
}
class Parameter<T4> {
>Parameter : Parameter<T4>
>T4 : T4
method(t: T4) { }
>method : (t: T4) => void
>t : T4
>T4 : T4
}
class Wrapper<T5> {
>Wrapper : Wrapper<T5>
>T5 : T5
property: T5;
>property : T5
>T5 : T5
}

View file

@ -0,0 +1,35 @@
//// [bestChoiceType.ts]
// Repro from #10041
(''.match(/ /) || []).map(s => s.toLowerCase());
// Similar cases
function f1() {
let x = ''.match(/ /);
let y = x || [];
let z = y.map(s => s.toLowerCase());
}
function f2() {
let x = ''.match(/ /);
let y = x ? x : [];
let z = y.map(s => s.toLowerCase());
}
//// [bestChoiceType.js]
// Repro from #10041
(''.match(/ /) || []).map(function (s) { return s.toLowerCase(); });
// Similar cases
function f1() {
var x = ''.match(/ /);
var y = x || [];
var z = y.map(function (s) { return s.toLowerCase(); });
}
function f2() {
var x = ''.match(/ /);
var y = x ? x : [];
var z = y.map(function (s) { return s.toLowerCase(); });
}

View file

@ -0,0 +1,63 @@
=== tests/cases/compiler/bestChoiceType.ts ===
// Repro from #10041
(''.match(/ /) || []).map(s => s.toLowerCase());
>(''.match(/ /) || []).map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>''.match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 3, 26))
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 3, 26))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
// Similar cases
function f1() {
>f1 : Symbol(f1, Decl(bestChoiceType.ts, 3, 48))
let x = ''.match(/ /);
>x : Symbol(x, Decl(bestChoiceType.ts, 8, 7))
>''.match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
let y = x || [];
>y : Symbol(y, Decl(bestChoiceType.ts, 9, 7))
>x : Symbol(x, Decl(bestChoiceType.ts, 8, 7))
let z = y.map(s => s.toLowerCase());
>z : Symbol(z, Decl(bestChoiceType.ts, 10, 7))
>y.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>y : Symbol(y, Decl(bestChoiceType.ts, 9, 7))
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 10, 18))
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 10, 18))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
}
function f2() {
>f2 : Symbol(f2, Decl(bestChoiceType.ts, 11, 1))
let x = ''.match(/ /);
>x : Symbol(x, Decl(bestChoiceType.ts, 14, 7))
>''.match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>match : Symbol(String.match, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
let y = x ? x : [];
>y : Symbol(y, Decl(bestChoiceType.ts, 15, 7))
>x : Symbol(x, Decl(bestChoiceType.ts, 14, 7))
>x : Symbol(x, Decl(bestChoiceType.ts, 14, 7))
let z = y.map(s => s.toLowerCase());
>z : Symbol(z, Decl(bestChoiceType.ts, 16, 7))
>y.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>y : Symbol(y, Decl(bestChoiceType.ts, 15, 7))
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 16, 18))
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
>s : Symbol(s, Decl(bestChoiceType.ts, 16, 18))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
}

View file

@ -0,0 +1,88 @@
=== tests/cases/compiler/bestChoiceType.ts ===
// Repro from #10041
(''.match(/ /) || []).map(s => s.toLowerCase());
>(''.match(/ /) || []).map(s => s.toLowerCase()) : string[]
>(''.match(/ /) || []).map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>(''.match(/ /) || []) : RegExpMatchArray
>''.match(/ /) || [] : RegExpMatchArray
>''.match(/ /) : RegExpMatchArray | null
>''.match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>'' : string
>match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>/ / : RegExp
>[] : never[]
>map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>s => s.toLowerCase() : (s: string) => string
>s : string
>s.toLowerCase() : string
>s.toLowerCase : () => string
>s : string
>toLowerCase : () => string
// Similar cases
function f1() {
>f1 : () => void
let x = ''.match(/ /);
>x : RegExpMatchArray | null
>''.match(/ /) : RegExpMatchArray | null
>''.match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>'' : string
>match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>/ / : RegExp
let y = x || [];
>y : RegExpMatchArray
>x || [] : RegExpMatchArray
>x : RegExpMatchArray | null
>[] : never[]
let z = y.map(s => s.toLowerCase());
>z : string[]
>y.map(s => s.toLowerCase()) : string[]
>y.map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>y : RegExpMatchArray
>map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>s => s.toLowerCase() : (s: string) => string
>s : string
>s.toLowerCase() : string
>s.toLowerCase : () => string
>s : string
>toLowerCase : () => string
}
function f2() {
>f2 : () => void
let x = ''.match(/ /);
>x : RegExpMatchArray | null
>''.match(/ /) : RegExpMatchArray | null
>''.match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>'' : string
>match : { (regexp: string): RegExpMatchArray | null; (regexp: RegExp): RegExpMatchArray | null; }
>/ / : RegExp
let y = x ? x : [];
>y : RegExpMatchArray
>x ? x : [] : RegExpMatchArray
>x : RegExpMatchArray | null
>x : RegExpMatchArray
>[] : never[]
let z = y.map(s => s.toLowerCase());
>z : string[]
>y.map(s => s.toLowerCase()) : string[]
>y.map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>y : RegExpMatchArray
>map : <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]
>s => s.toLowerCase() : (s: string) => string
>s : string
>s.toLowerCase() : string
>s.toLowerCase : () => string
>s : string
>toLowerCase : () => string
}

View file

@ -0,0 +1,25 @@
tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts(5,28): error TS2690: A class must be declared after its base class.
==== tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts (1 errors) ====
// expected no error
module B {
export import a = A;
export class D extends a.C {
~~~
!!! error TS2690: A class must be declared after its base class.
id: number;
}
}
module A {
export class C { name: string }
export import b = B;
}
var c: { name: string };
var c = new B.a.C();

View file

@ -1,47 +0,0 @@
=== tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts ===
// expected no error
module B {
>B : Symbol(a.b, Decl(circularImportAlias.ts, 0, 0))
export import a = A;
>a : Symbol(a, Decl(circularImportAlias.ts, 2, 10))
>A : Symbol(a, Decl(circularImportAlias.ts, 7, 1))
export class D extends a.C {
>D : Symbol(D, Decl(circularImportAlias.ts, 3, 24))
>a.C : Symbol(a.C, Decl(circularImportAlias.ts, 9, 10))
>a : Symbol(a, Decl(circularImportAlias.ts, 2, 10))
>C : Symbol(a.C, Decl(circularImportAlias.ts, 9, 10))
id: number;
>id : Symbol(D.id, Decl(circularImportAlias.ts, 4, 32))
}
}
module A {
>A : Symbol(b.a, Decl(circularImportAlias.ts, 7, 1))
export class C { name: string }
>C : Symbol(C, Decl(circularImportAlias.ts, 9, 10))
>name : Symbol(C.name, Decl(circularImportAlias.ts, 10, 20))
export import b = B;
>b : Symbol(b, Decl(circularImportAlias.ts, 10, 35))
>B : Symbol(b, Decl(circularImportAlias.ts, 0, 0))
}
var c: { name: string };
>c : Symbol(c, Decl(circularImportAlias.ts, 14, 3), Decl(circularImportAlias.ts, 15, 3))
>name : Symbol(name, Decl(circularImportAlias.ts, 14, 8))
var c = new B.a.C();
>c : Symbol(c, Decl(circularImportAlias.ts, 14, 3), Decl(circularImportAlias.ts, 15, 3))
>B.a.C : Symbol(A.C, Decl(circularImportAlias.ts, 9, 10))
>B.a : Symbol(B.a, Decl(circularImportAlias.ts, 2, 10))
>B : Symbol(B, Decl(circularImportAlias.ts, 0, 0))
>a : Symbol(B.a, Decl(circularImportAlias.ts, 2, 10))
>C : Symbol(A.C, Decl(circularImportAlias.ts, 9, 10))

View file

@ -1,48 +0,0 @@
=== tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts ===
// expected no error
module B {
>B : typeof a.b
export import a = A;
>a : typeof a
>A : typeof a
export class D extends a.C {
>D : D
>a.C : a.C
>a : typeof a
>C : typeof a.C
id: number;
>id : number
}
}
module A {
>A : typeof b.a
export class C { name: string }
>C : C
>name : string
export import b = B;
>b : typeof b
>B : typeof b
}
var c: { name: string };
>c : { name: string; }
>name : string
var c = new B.a.C();
>c : { name: string; }
>new B.a.C() : A.C
>B.a.C : typeof A.C
>B.a : typeof A
>B : typeof B
>a : typeof A
>C : typeof A.C

View file

@ -0,0 +1,15 @@
tests/cases/conformance/classes/classExpressions/classExpression3.ts(1,23): error TS2690: A class must be declared after its base class.
tests/cases/conformance/classes/classExpressions/classExpression3.ts(1,37): error TS2690: A class must be declared after its base class.
==== tests/cases/conformance/classes/classExpressions/classExpression3.ts (2 errors) ====
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2690: A class must be declared after its base class.
~~~~~~~~~~~~~~~
!!! error TS2690: A class must be declared after its base class.
let c = new C();
c.a;
c.b;
c.c;

View file

@ -1,26 +0,0 @@
=== tests/cases/conformance/classes/classExpressions/classExpression3.ts ===
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
>C : Symbol(C, Decl(classExpression3.ts, 0, 3))
>a : Symbol((Anonymous class).a, Decl(classExpression3.ts, 0, 43))
>b : Symbol((Anonymous class).b, Decl(classExpression3.ts, 0, 53))
>c : Symbol((Anonymous class).c, Decl(classExpression3.ts, 0, 63))
let c = new C();
>c : Symbol(c, Decl(classExpression3.ts, 1, 3))
>C : Symbol(C, Decl(classExpression3.ts, 0, 3))
c.a;
>c.a : Symbol((Anonymous class).a, Decl(classExpression3.ts, 0, 43))
>c : Symbol(c, Decl(classExpression3.ts, 1, 3))
>a : Symbol((Anonymous class).a, Decl(classExpression3.ts, 0, 43))
c.b;
>c.b : Symbol((Anonymous class).b, Decl(classExpression3.ts, 0, 53))
>c : Symbol(c, Decl(classExpression3.ts, 1, 3))
>b : Symbol((Anonymous class).b, Decl(classExpression3.ts, 0, 53))
c.c;
>c.c : Symbol((Anonymous class).c, Decl(classExpression3.ts, 0, 63))
>c : Symbol(c, Decl(classExpression3.ts, 1, 3))
>c : Symbol((Anonymous class).c, Decl(classExpression3.ts, 0, 63))

View file

@ -1,33 +0,0 @@
=== tests/cases/conformance/classes/classExpressions/classExpression3.ts ===
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
>C : typeof (Anonymous class)
>class extends class extends class { a = 1 } { b = 2 } { c = 3 } : typeof (Anonymous class)
>class extends class { a = 1 } { b = 2 } : (Anonymous class)
>class { a = 1 } : (Anonymous class)
>a : number
>1 : number
>b : number
>2 : number
>c : number
>3 : number
let c = new C();
>c : (Anonymous class)
>new C() : (Anonymous class)
>C : typeof (Anonymous class)
c.a;
>c.a : number
>c : (Anonymous class)
>a : number
c.b;
>c.b : number
>c : (Anonymous class)
>b : number
c.c;
>c.c : number
>c : (Anonymous class)
>c : number

View file

@ -0,0 +1,15 @@
tests/cases/conformance/es6/classExpressions/classExpressionES63.ts(1,23): error TS2690: A class must be declared after its base class.
tests/cases/conformance/es6/classExpressions/classExpressionES63.ts(1,37): error TS2690: A class must be declared after its base class.
==== tests/cases/conformance/es6/classExpressions/classExpressionES63.ts (2 errors) ====
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2690: A class must be declared after its base class.
~~~~~~~~~~~~~~~
!!! error TS2690: A class must be declared after its base class.
let c = new C();
c.a;
c.b;
c.c;

View file

@ -1,26 +0,0 @@
=== tests/cases/conformance/es6/classExpressions/classExpressionES63.ts ===
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
>C : Symbol(C, Decl(classExpressionES63.ts, 0, 3))
>a : Symbol((Anonymous class).a, Decl(classExpressionES63.ts, 0, 43))
>b : Symbol((Anonymous class).b, Decl(classExpressionES63.ts, 0, 53))
>c : Symbol((Anonymous class).c, Decl(classExpressionES63.ts, 0, 63))
let c = new C();
>c : Symbol(c, Decl(classExpressionES63.ts, 1, 3))
>C : Symbol(C, Decl(classExpressionES63.ts, 0, 3))
c.a;
>c.a : Symbol((Anonymous class).a, Decl(classExpressionES63.ts, 0, 43))
>c : Symbol(c, Decl(classExpressionES63.ts, 1, 3))
>a : Symbol((Anonymous class).a, Decl(classExpressionES63.ts, 0, 43))
c.b;
>c.b : Symbol((Anonymous class).b, Decl(classExpressionES63.ts, 0, 53))
>c : Symbol(c, Decl(classExpressionES63.ts, 1, 3))
>b : Symbol((Anonymous class).b, Decl(classExpressionES63.ts, 0, 53))
c.c;
>c.c : Symbol((Anonymous class).c, Decl(classExpressionES63.ts, 0, 63))
>c : Symbol(c, Decl(classExpressionES63.ts, 1, 3))
>c : Symbol((Anonymous class).c, Decl(classExpressionES63.ts, 0, 63))

View file

@ -1,33 +0,0 @@
=== tests/cases/conformance/es6/classExpressions/classExpressionES63.ts ===
let C = class extends class extends class { a = 1 } { b = 2 } { c = 3 };
>C : typeof (Anonymous class)
>class extends class extends class { a = 1 } { b = 2 } { c = 3 } : typeof (Anonymous class)
>class extends class { a = 1 } { b = 2 } : (Anonymous class)
>class { a = 1 } : (Anonymous class)
>a : number
>1 : number
>b : number
>2 : number
>c : number
>3 : number
let c = new C();
>c : (Anonymous class)
>new C() : (Anonymous class)
>C : typeof (Anonymous class)
c.a;
>c.a : number
>c : (Anonymous class)
>a : number
c.b;
>c.b : number
>c : (Anonymous class)
>b : number
c.c;
>c.c : number
>c : (Anonymous class)
>c : number

View file

@ -1,8 +1,11 @@
tests/cases/compiler/classInheritence.ts(1,17): error TS2690: A class must be declared after its base class.
tests/cases/compiler/classInheritence.ts(2,7): error TS2506: 'A' is referenced directly or indirectly in its own base expression. tests/cases/compiler/classInheritence.ts(2,7): error TS2506: 'A' is referenced directly or indirectly in its own base expression.
==== tests/cases/compiler/classInheritence.ts (1 errors) ==== ==== tests/cases/compiler/classInheritence.ts (2 errors) ====
class B extends A { } class B extends A { }
~
!!! error TS2690: A class must be declared after its base class.
class A extends A { } class A extends A { }
~ ~
!!! error TS2506: 'A' is referenced directly or indirectly in its own base expression. !!! error TS2506: 'A' is referenced directly or indirectly in its own base expression.

View file

@ -0,0 +1,25 @@
tests/cases/compiler/classOrder2.ts(2,17): error TS2690: A class must be declared after its base class.
==== tests/cases/compiler/classOrder2.ts (1 errors) ====
class A extends B {
~
!!! error TS2690: A class must be declared after its base class.
foo() { this.bar(); }
}
class B {
bar() { }
}
var a = new A();
a.foo();

View file

@ -1,33 +0,0 @@
=== tests/cases/compiler/classOrder2.ts ===
class A extends B {
>A : Symbol(A, Decl(classOrder2.ts, 0, 0))
>B : Symbol(B, Decl(classOrder2.ts, 5, 1))
foo() { this.bar(); }
>foo : Symbol(A.foo, Decl(classOrder2.ts, 1, 19))
>this.bar : Symbol(B.bar, Decl(classOrder2.ts, 7, 9))
>this : Symbol(A, Decl(classOrder2.ts, 0, 0))
>bar : Symbol(B.bar, Decl(classOrder2.ts, 7, 9))
}
class B {
>B : Symbol(B, Decl(classOrder2.ts, 5, 1))
bar() { }
>bar : Symbol(B.bar, Decl(classOrder2.ts, 7, 9))
}
var a = new A();
>a : Symbol(a, Decl(classOrder2.ts, 14, 3))
>A : Symbol(A, Decl(classOrder2.ts, 0, 0))
a.foo();
>a.foo : Symbol(A.foo, Decl(classOrder2.ts, 1, 19))
>a : Symbol(a, Decl(classOrder2.ts, 14, 3))
>foo : Symbol(A.foo, Decl(classOrder2.ts, 1, 19))

View file

@ -1,36 +0,0 @@
=== tests/cases/compiler/classOrder2.ts ===
class A extends B {
>A : A
>B : B
foo() { this.bar(); }
>foo : () => void
>this.bar() : void
>this.bar : () => void
>this : this
>bar : () => void
}
class B {
>B : B
bar() { }
>bar : () => void
}
var a = new A();
>a : A
>new A() : A
>A : typeof A
a.foo();
>a.foo() : void
>a.foo : () => void
>a : A
>foo : () => void

View file

@ -0,0 +1,26 @@
tests/cases/compiler/classSideInheritance2.ts(7,23): error TS2690: A class must be declared after its base class.
==== tests/cases/compiler/classSideInheritance2.ts (1 errors) ====
interface IText {
foo: number;
}
interface TextSpan {}
class SubText extends TextBase {
~~~~~~~~
!!! error TS2690: A class must be declared after its base class.
constructor(text: IText, span: TextSpan) {
super();
}
}
class TextBase implements IText {
public foo: number;
public subText(span: TextSpan): IText {
return new SubText(this, span);
}
}

View file

@ -1,45 +0,0 @@
=== tests/cases/compiler/classSideInheritance2.ts ===
interface IText {
>IText : Symbol(IText, Decl(classSideInheritance2.ts, 0, 0))
foo: number;
>foo : Symbol(IText.foo, Decl(classSideInheritance2.ts, 0, 17))
}
interface TextSpan {}
>TextSpan : Symbol(TextSpan, Decl(classSideInheritance2.ts, 2, 1))
class SubText extends TextBase {
>SubText : Symbol(SubText, Decl(classSideInheritance2.ts, 4, 21))
>TextBase : Symbol(TextBase, Decl(classSideInheritance2.ts, 11, 1))
constructor(text: IText, span: TextSpan) {
>text : Symbol(text, Decl(classSideInheritance2.ts, 8, 20))
>IText : Symbol(IText, Decl(classSideInheritance2.ts, 0, 0))
>span : Symbol(span, Decl(classSideInheritance2.ts, 8, 32))
>TextSpan : Symbol(TextSpan, Decl(classSideInheritance2.ts, 2, 1))
super();
>super : Symbol(TextBase, Decl(classSideInheritance2.ts, 11, 1))
}
}
class TextBase implements IText {
>TextBase : Symbol(TextBase, Decl(classSideInheritance2.ts, 11, 1))
>IText : Symbol(IText, Decl(classSideInheritance2.ts, 0, 0))
public foo: number;
>foo : Symbol(TextBase.foo, Decl(classSideInheritance2.ts, 13, 33))
public subText(span: TextSpan): IText {
>subText : Symbol(TextBase.subText, Decl(classSideInheritance2.ts, 14, 27))
>span : Symbol(span, Decl(classSideInheritance2.ts, 15, 23))
>TextSpan : Symbol(TextSpan, Decl(classSideInheritance2.ts, 2, 1))
>IText : Symbol(IText, Decl(classSideInheritance2.ts, 0, 0))
return new SubText(this, span);
>SubText : Symbol(SubText, Decl(classSideInheritance2.ts, 4, 21))
>this : Symbol(TextBase, Decl(classSideInheritance2.ts, 11, 1))
>span : Symbol(span, Decl(classSideInheritance2.ts, 15, 23))
}
}

View file

@ -1,47 +0,0 @@
=== tests/cases/compiler/classSideInheritance2.ts ===
interface IText {
>IText : IText
foo: number;
>foo : number
}
interface TextSpan {}
>TextSpan : TextSpan
class SubText extends TextBase {
>SubText : SubText
>TextBase : TextBase
constructor(text: IText, span: TextSpan) {
>text : IText
>IText : IText
>span : TextSpan
>TextSpan : TextSpan
super();
>super() : void
>super : typeof TextBase
}
}
class TextBase implements IText {
>TextBase : TextBase
>IText : IText
public foo: number;
>foo : number
public subText(span: TextSpan): IText {
>subText : (span: TextSpan) => IText
>span : TextSpan
>TextSpan : TextSpan
>IText : IText
return new SubText(this, span);
>new SubText(this, span) : SubText
>SubText : typeof SubText
>this : this
>span : TextSpan
}
}

View file

@ -0,0 +1,53 @@
tests/cases/compiler/complexClassRelationships.ts(2,23): error TS2690: A class must be declared after its base class.
==== tests/cases/compiler/complexClassRelationships.ts (1 errors) ====
// There should be no errors in this file
class Derived extends Base {
~~~~
!!! error TS2690: A class must be declared after its base class.
public static createEmpty(): Derived {
var item = new Derived();
return item;
}
}
class BaseCollection<T extends Base> {
constructor(f: () => T) {
(item: Thing) => { return [item.Components]; };
}
}
class Base {
ownerCollection: BaseCollection<Base>;
}
class Thing {
public get Components(): ComponentCollection<any> { return null }
}
class ComponentCollection<T> {
private static sortComponents(p: Foo) {
return p.prop1;
}
}
class Foo {
public get prop1() {
return new GenericType<string>(this);
}
public populate() {
this.prop2;
}
public get prop2(): BaseCollection<Derived> {
return new BaseCollection<Derived>(Derived.createEmpty);
}
}
class GenericType<T> {
constructor(parent: FooBase) { }
}
class FooBase {
public populate() {
}
}

View file

@ -1,117 +0,0 @@
=== tests/cases/compiler/complexClassRelationships.ts ===
// There should be no errors in this file
class Derived extends Base {
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
>Base : Symbol(Base, Decl(complexClassRelationships.ts, 11, 1))
public static createEmpty(): Derived {
>createEmpty : Symbol(Derived.createEmpty, Decl(complexClassRelationships.ts, 1, 28))
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
var item = new Derived();
>item : Symbol(item, Decl(complexClassRelationships.ts, 3, 11))
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
return item;
>item : Symbol(item, Decl(complexClassRelationships.ts, 3, 11))
}
}
class BaseCollection<T extends Base> {
>BaseCollection : Symbol(BaseCollection, Decl(complexClassRelationships.ts, 6, 1))
>T : Symbol(T, Decl(complexClassRelationships.ts, 7, 21))
>Base : Symbol(Base, Decl(complexClassRelationships.ts, 11, 1))
constructor(f: () => T) {
>f : Symbol(f, Decl(complexClassRelationships.ts, 8, 16))
>T : Symbol(T, Decl(complexClassRelationships.ts, 7, 21))
(item: Thing) => { return [item.Components]; };
>item : Symbol(item, Decl(complexClassRelationships.ts, 9, 9))
>Thing : Symbol(Thing, Decl(complexClassRelationships.ts, 14, 1))
>item.Components : Symbol(Thing.Components, Decl(complexClassRelationships.ts, 16, 13))
>item : Symbol(item, Decl(complexClassRelationships.ts, 9, 9))
>Components : Symbol(Thing.Components, Decl(complexClassRelationships.ts, 16, 13))
}
}
class Base {
>Base : Symbol(Base, Decl(complexClassRelationships.ts, 11, 1))
ownerCollection: BaseCollection<Base>;
>ownerCollection : Symbol(Base.ownerCollection, Decl(complexClassRelationships.ts, 12, 12))
>BaseCollection : Symbol(BaseCollection, Decl(complexClassRelationships.ts, 6, 1))
>Base : Symbol(Base, Decl(complexClassRelationships.ts, 11, 1))
}
class Thing {
>Thing : Symbol(Thing, Decl(complexClassRelationships.ts, 14, 1))
public get Components(): ComponentCollection<any> { return null }
>Components : Symbol(Thing.Components, Decl(complexClassRelationships.ts, 16, 13))
>ComponentCollection : Symbol(ComponentCollection, Decl(complexClassRelationships.ts, 18, 1))
}
class ComponentCollection<T> {
>ComponentCollection : Symbol(ComponentCollection, Decl(complexClassRelationships.ts, 18, 1))
>T : Symbol(T, Decl(complexClassRelationships.ts, 20, 26))
private static sortComponents(p: Foo) {
>sortComponents : Symbol(ComponentCollection.sortComponents, Decl(complexClassRelationships.ts, 20, 30))
>p : Symbol(p, Decl(complexClassRelationships.ts, 21, 34))
>Foo : Symbol(Foo, Decl(complexClassRelationships.ts, 24, 1))
return p.prop1;
>p.prop1 : Symbol(Foo.prop1, Decl(complexClassRelationships.ts, 26, 11))
>p : Symbol(p, Decl(complexClassRelationships.ts, 21, 34))
>prop1 : Symbol(Foo.prop1, Decl(complexClassRelationships.ts, 26, 11))
}
}
class Foo {
>Foo : Symbol(Foo, Decl(complexClassRelationships.ts, 24, 1))
public get prop1() {
>prop1 : Symbol(Foo.prop1, Decl(complexClassRelationships.ts, 26, 11))
return new GenericType<string>(this);
>GenericType : Symbol(GenericType, Decl(complexClassRelationships.ts, 36, 1))
>this : Symbol(Foo, Decl(complexClassRelationships.ts, 24, 1))
}
public populate() {
>populate : Symbol(Foo.populate, Decl(complexClassRelationships.ts, 29, 5))
this.prop2;
>this.prop2 : Symbol(Foo.prop2, Decl(complexClassRelationships.ts, 32, 5))
>this : Symbol(Foo, Decl(complexClassRelationships.ts, 24, 1))
>prop2 : Symbol(Foo.prop2, Decl(complexClassRelationships.ts, 32, 5))
}
public get prop2(): BaseCollection<Derived> {
>prop2 : Symbol(Foo.prop2, Decl(complexClassRelationships.ts, 32, 5))
>BaseCollection : Symbol(BaseCollection, Decl(complexClassRelationships.ts, 6, 1))
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
return new BaseCollection<Derived>(Derived.createEmpty);
>BaseCollection : Symbol(BaseCollection, Decl(complexClassRelationships.ts, 6, 1))
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
>Derived.createEmpty : Symbol(Derived.createEmpty, Decl(complexClassRelationships.ts, 1, 28))
>Derived : Symbol(Derived, Decl(complexClassRelationships.ts, 0, 0))
>createEmpty : Symbol(Derived.createEmpty, Decl(complexClassRelationships.ts, 1, 28))
}
}
class GenericType<T> {
>GenericType : Symbol(GenericType, Decl(complexClassRelationships.ts, 36, 1))
>T : Symbol(T, Decl(complexClassRelationships.ts, 38, 18))
constructor(parent: FooBase) { }
>parent : Symbol(parent, Decl(complexClassRelationships.ts, 39, 16))
>FooBase : Symbol(FooBase, Decl(complexClassRelationships.ts, 40, 1))
}
class FooBase {
>FooBase : Symbol(FooBase, Decl(complexClassRelationships.ts, 40, 1))
public populate() {
>populate : Symbol(FooBase.populate, Decl(complexClassRelationships.ts, 42, 15))
}
}

View file

@ -1,123 +0,0 @@
=== tests/cases/compiler/complexClassRelationships.ts ===
// There should be no errors in this file
class Derived extends Base {
>Derived : Derived
>Base : Base
public static createEmpty(): Derived {
>createEmpty : () => Derived
>Derived : Derived
var item = new Derived();
>item : Derived
>new Derived() : Derived
>Derived : typeof Derived
return item;
>item : Derived
}
}
class BaseCollection<T extends Base> {
>BaseCollection : BaseCollection<T>
>T : T
>Base : Base
constructor(f: () => T) {
>f : () => T
>T : T
(item: Thing) => { return [item.Components]; };
>(item: Thing) => { return [item.Components]; } : (item: Thing) => ComponentCollection<any>[]
>item : Thing
>Thing : Thing
>[item.Components] : ComponentCollection<any>[]
>item.Components : ComponentCollection<any>
>item : Thing
>Components : ComponentCollection<any>
}
}
class Base {
>Base : Base
ownerCollection: BaseCollection<Base>;
>ownerCollection : BaseCollection<Base>
>BaseCollection : BaseCollection<T>
>Base : Base
}
class Thing {
>Thing : Thing
public get Components(): ComponentCollection<any> { return null }
>Components : ComponentCollection<any>
>ComponentCollection : ComponentCollection<T>
>null : null
}
class ComponentCollection<T> {
>ComponentCollection : ComponentCollection<T>
>T : T
private static sortComponents(p: Foo) {
>sortComponents : (p: Foo) => GenericType<string>
>p : Foo
>Foo : Foo
return p.prop1;
>p.prop1 : GenericType<string>
>p : Foo
>prop1 : GenericType<string>
}
}
class Foo {
>Foo : Foo
public get prop1() {
>prop1 : GenericType<string>
return new GenericType<string>(this);
>new GenericType<string>(this) : GenericType<string>
>GenericType : typeof GenericType
>this : this
}
public populate() {
>populate : () => void
this.prop2;
>this.prop2 : BaseCollection<Derived>
>this : this
>prop2 : BaseCollection<Derived>
}
public get prop2(): BaseCollection<Derived> {
>prop2 : BaseCollection<Derived>
>BaseCollection : BaseCollection<T>
>Derived : Derived
return new BaseCollection<Derived>(Derived.createEmpty);
>new BaseCollection<Derived>(Derived.createEmpty) : BaseCollection<Derived>
>BaseCollection : typeof BaseCollection
>Derived : Derived
>Derived.createEmpty : () => Derived
>Derived : typeof Derived
>createEmpty : () => Derived
}
}
class GenericType<T> {
>GenericType : GenericType<T>
>T : T
constructor(parent: FooBase) { }
>parent : FooBase
>FooBase : FooBase
}
class FooBase {
>FooBase : FooBase
public populate() {
>populate : () => void
}
}

View file

@ -14,15 +14,15 @@ var fa: number[];
fa = fa.concat([0]); fa = fa.concat([0]);
>fa : Symbol(fa, Decl(concatError.ts, 8, 3)) >fa : Symbol(fa, Decl(concatError.ts, 8, 3))
>fa.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >fa.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>fa : Symbol(fa, Decl(concatError.ts, 8, 3)) >fa : Symbol(fa, Decl(concatError.ts, 8, 3))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
fa = fa.concat(0); fa = fa.concat(0);
>fa : Symbol(fa, Decl(concatError.ts, 8, 3)) >fa : Symbol(fa, Decl(concatError.ts, 8, 3))
>fa.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >fa.concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>fa : Symbol(fa, Decl(concatError.ts, 8, 3)) >fa : Symbol(fa, Decl(concatError.ts, 8, 3))
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --)) >concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

View file

@ -16,9 +16,9 @@ fa = fa.concat([0]);
>fa = fa.concat([0]) : number[] >fa = fa.concat([0]) : number[]
>fa : number[] >fa : number[]
>fa.concat([0]) : number[] >fa.concat([0]) : number[]
>fa.concat : (...items: (number | number[])[]) => number[] >fa.concat : { (...items: number[][]): number[]; (...items: (number | number[])[]): number[]; }
>fa : number[] >fa : number[]
>concat : (...items: (number | number[])[]) => number[] >concat : { (...items: number[][]): number[]; (...items: (number | number[])[]): number[]; }
>[0] : number[] >[0] : number[]
>0 : number >0 : number
@ -26,9 +26,9 @@ fa = fa.concat(0);
>fa = fa.concat(0) : number[] >fa = fa.concat(0) : number[]
>fa : number[] >fa : number[]
>fa.concat(0) : number[] >fa.concat(0) : number[]
>fa.concat : (...items: (number | number[])[]) => number[] >fa.concat : { (...items: number[][]): number[]; (...items: (number | number[])[]): number[]; }
>fa : number[] >fa : number[]
>concat : (...items: (number | number[])[]) => number[] >concat : { (...items: number[][]): number[]; (...items: (number | number[])[]): number[]; }
>0 : number >0 : number

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