mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
[Transforms] Merge master 08/09 (#10263)
* Improve error message * Remove `SupportedExpressionWithTypeArguments` type; just check that the expression of each `ExpressionWithTypeArguments` is an `EntityNameExpression`. * Fix bug * Fix #10083 - allowSyntheticDefaultImports alters getExternalModuleMember (#10096) * Use recursion, and fix error for undefined node * Rename function * Fix lint error * Narrowing type parameter intersects w/narrowed types This makes sure that a union type that includes a type parameter is still usable as the actual type that the type guard narrows to. * Don't allow ".d.ts" extension in an import either. * Add a helper function `getOrUpdateProperty` to prevent unprotected access to Maps. * Limit type guards as assertions to incomplete types in loops * Accept new baselines * Fix linting error * Allow JS multiple declarations of ctor properties When a property is declared in the constructor and on the prototype of an ES6 class, the property's symbol is discarded in favour of the method's symbol. That because the usual use for this pattern is to bind an instance function: `this.m = this.m.bind(this)`. In this case the type you want really is the method's type. * Use {} type facts for unconstrained type params Previously it was using TypeFacts.All. But the constraint of an unconstrained type parameter is actually {}. * Fix newline lint * Test that declares conflicting method first * [Release-2.0] Fix 9662: Visual Studio 2015 with TS2.0 gives incorrect @types path resolution errors (#9867) * Change the shape of the shim layer to support getAutomaticTypeDirectives * Change the key for looking up automatic type-directives * Update baselines from change look-up name of type-directives * Add @currentDirectory into the test * Update baselines * Fix linting error * Address PR: fix spelling mistake * Instead of return path of the type directive names just return type directive names * Remove unused reference files: these tests produce erros so they will not produce these files (#9233) * Add string-literal completion test for jsdoc * Support other (new) literal types in jsdoc * Don't allow properties inherited from Object to be automatically included in TSX attributes * Add new test baseline and delete else in binder The extra `else` caused a ton of test failures! * Fix lint * Port PR #10016 to Master (#10100) * Treat namespaceExportDeclaration as declaration * Update baselines * wip - add tests * Add tests * Show "export namespace" for quick-info * Fix more lint * Try using runtests-parallel for CI (#9970) * Try using runtests-parallel for CI * Put worker count setting into .travis.yml * Reduce worker count to 4 - 8 wasnt much different from 4-6 but had contention issues causing timeouts * Fix lssl task (#9967) * Surface noErrorTruncation option * Stricter check for discriminant properties in type guards * Add tests * Emit more efficient/concise "empty" ES6 ctor When there are property assignments in a the class body of an inheriting class, tsc current emit the following compilation: ```ts class Foo extends Bar { public foo = 1; } ``` ```js class Foo extends Bar { constructor(…args) { super(…args); this.foo = 1; } } ``` This introduces an unneeded local variable and might force a reification of the `arguments` object (or otherwise reify the arguments into an array). This is particularly bad when that output is fed into another transpiler like Babel. In Babel, you get something like this today: ```js var Foo = (function (_Bar) { _inherits(Foo, _Bar); function Foo() { _classCallCheck(this, Foo); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _Bar.call.apply(_Bar, [this].concat(args)); this.foo = 1; } return Foo; })(Bar); ``` This causes a lot of needless work/allocations and some very strange code (`.call.apply` o_0). Admittedly, this is not strictly tsc’s problem; it could have done a deeper analysis of the code and optimized out the extra dance. However, tsc could also have emitted this simpler, more concise and semantically equivalent code in the first place: ```js class Foo extends Bar { constructor() { super(…arguments); this.foo = 1; } } ``` Which compiles into the following in Babel: ```js var Foo = (function (_Bar) { _inherits(Foo, _Bar); function Foo() { _classCallCheck(this, Foo); _Bar.apply(this, arguments); this.foo = 1; } return Foo; })(Bar); ``` Which is well-optimized (today) in most engines and much less confusing to read. As far as I can tell, the proposed compilation has exactly the same semantics as before. Fixes #10175 * Fix instanceof operator narrowing issues * Accept new baselines * Add regression test * Improve naming and documentation from PR * Update comment * Add more tests * Accept new baselines * Reduce worker count to 3 (#10210) Since we saw a starvation issue on one of @sandersn's PRs. * Speed up fourslash tests * Duh * Make baselines faster by not writing out unneeded files * Fix non-strict-compliant test * Fix 10076: Fix Tuple Destructing with "this" (#10208) * Call checkExpression eventhough there is no appropriate type from destructuring of array * Add tests and baselines * use transpileModule * Remove use strict * Improve instanceof for structurally identical types * Introduce isTypeInstanceOf function * Add test * Accept new baselines * Fix loop over array to use for-of instead of for-in * Use correct this in tuple type parameter constraints Instantiate this in tuple types used as type parameter constraints * Add explanatory comment to resolveTupleTypeMembers * Ignore null, undefined, void when checking for discriminant property * Add regression test * Delay tuple type constraint resolution Create a new tuple that stores the this-type. * Always use thisType when generating tuple id * Optimize format of type list id strings used in maps * wip - fix error * Make ReadonlyArray iterable. * Allow OSX to fail while we investigate (#10255) The random test timeouts are an issue. * Fix error from using merging master * avoid using the global name * Fix single-quote lint * Update baselines * Fix linting * Optimize performance of maps * Update API sample * Fix processDiagnosticMessages script * Have travis take shallow clones of the repo (#10275) Just cloning TS on travis takes 23 seconds on linux (68 seconds on mac), hopefully having it do a shallow clone will help. We don't rely on any tagging/artifacts from the travis servers which clone depth could impact, so this shouldn't impact anything other than build speed. * Add folds to travis log (#10269) * Optimize filterType to only call getUnionType if necessary * Add shorthand types declaration for travis-fold (#10293) * Optimize getTypeWithFacts * Filter out nullable and primitive types in isDiscriminantProperty * Fix typo * Add regression tests * Optimize core filter function to only allocate when necessary * Address CR comments + more optimizations * Faster path for creating union types from filterType * Allow an @types direcotry to have a package.json which specifies `"typings": null` to disclude it from automatically included typings. * Lint * Collect timing information for commands running on travis (#10308) * Simplifies performance API * Use 'MapLike' instead of 'Map' in 'preferConstRule.ts'. * narrow from 'any' in most situations instanceof and user-defined typeguards narrow from 'any' unless the narrowed-to type is exactly 'Object' or 'Function'. This is a breaking change. * Update instanceof conformance tests * accept new baselines * add tests * accept new baselines * Use lowercase names for type reference directives * Use proper response codes in web tests * Treat ambient shorthand declarations as explicit uses of the `any` type * Rename 'find' functions * Parallel linting (#10313) * A perilous thing, a parallel lint * Use work queue rather than scheduling work * Dont read files for lint on main thread * Fix style * Fix the style fix (#10344) * Aligned mark names with values used by ts-perf. * Use an enum in checkClassForDuplicateDeclarations to aid readability * Rename to Accessor * Migrated more MapLikes to Maps * Add ES2015 Date constructor signature that accepts another Date (#10353) * Parameters with no assignments implicitly considered const * Add tests * Migrate additional MapLikes to Maps. * Fix 10625: JSX Not validating when index signature is present (#10352) * Check for type of property declaration before using index signature * Add tests and baselines * fix linting error * Adding more comments * Clean up/move some Map helper functions. * Revert some formatting changes. * Improve ReadonlyArray<T>.concat to match Array<T> The Array-based signature was incorrect and also out-of-date. * Fix link to blog * Remove old assertion about when we're allowed to use fileExists * Set isNewIdentifierLocation to true for JavaScript files * Update error message for conflicting type definitions Fixes #10370 * Explain why we lower-case type reference directives * Correctly merge bindThisPropertyAssignment Also simply it considerably after noticing that it's *only* called for Javascript files, so there was a lot of dead code for TS cases that never happened. * Fix comment * Property handle imcomplete control flow types in nested loops * Update due to CR suggestion * Add regression test * Assign and instantiate contextual this type if not present * Fix 10289: correctly generate tsconfig.json with --lib (#10355) * Separate generate tsconfig into its own function and implement init with --lib # Conflicts: # src/compiler/tsc.ts * Add tests and baselines; Update function name Add unittests and baselines Add unittests and baselines for generating tsconfig Move unittest into harness folder Update harness tsconfig.json USe correct function name * Use new MapLike interstead. Update unittest # Conflicts: # src/compiler/commandLineParser.ts * Update JakeFile * Add tests for incorrect cases * Address PR : remove explicity write node_modules * JSDoc supports null, undefined and never types * Update baselines in jsDocParsing unit tests * Restored comments to explain spreading 'arguments' into calls to 'super'. * Added test. * Use the non-nullable type of the contextual type for object completions. * Return non-JsDocComment children ... to make syntactic classification work * Add more tests for `export = foo.bar`. * Output test baselines to tests/baselines/local instead of root * Move supportedTypescriptExtensionsWithDtsFirst next to supportedTypeScriptExtensions and rename * Fix comment * Fix RWC Runner (#10420) * Use /// <reference types * Don't report an errors if it comes from lib.d.ts * Treat special property access symbol differently ... when retriving documentation * Fix tests * Update shim version to be 2.1 (#10424) * Check return code paths on getters (#10102) * Check return paths on getters * Remove TODO comment * Remove extraneous arguments from harness's runBaseline (#10419) * Remove extraneous arguments from runBaseline * Address comments from @yuit * Remove needless call to basename * Refactor baseliners out of compiler runner (#10440) * CR feedback * fix broken tests * Pass in baselineOpts into types baselines so that RWC baselines can be written to internal folder (#10443) * Add error message Add error message when trying to relate primitives to the boxed/apparent backing types. * fix linting error * follow advise * remove extra code * Add more test for 10426 * fix some errors * routine update of dom libs * Add test for jsdoc syntactic classification for function declaration * Simplify implementation * Tolerate certain errors in tsconfig.json * Add test for configFile error tolerance * Use TS parser to tolerate more errors in tsconfig.json * Implement tuple types as type references to synthesized generic types * Add comments + minor changes * Accept new baselines * Add .types extension * Properly guard for undefined in getTypeReferenceArity * Add jsdoc nullable union test case to fourslash * Fix class/interface merging issue + lint error * Allow "typings" in a package.json to be missing its extension (but also allow it to have an extension) * Contextually type this in getDeclFromSig, not checkThisExpr * Update parser comment with es7 grammar (#10459) * Use ES7 term of ExponentiationExpression * Update timeout for mac OS * Address PR: add space * allowSyntheticDefaultImports resolves to modules instead of variables Fixes #10429 by improving the fix in #10096 * Rename getContextuallyTypedThisParameter to getContextualThisParameter * Fix 10472: Invalid emitted code for await expression (#10483) * Properly emit await expression with yield expression * Add tests and update baselines * Move parsing await expression into parse unary-expression * Update incorrect comment * change error message * Fix broken build from merging with master * Fix linting error
This commit is contained in:
@@ -7,12 +7,18 @@ node_js:
|
||||
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
- workerCount=3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- os: osx
|
||||
node_js: stable
|
||||
osx_image: xcode7.3
|
||||
env: workerCount=2
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
branches:
|
||||
only:
|
||||
@@ -28,3 +34,6 @@ install:
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
+122
-95
@@ -17,7 +17,7 @@ declare module "gulp-typescript" {
|
||||
stripInternal?: boolean;
|
||||
types?: string[];
|
||||
}
|
||||
interface CompileStream extends NodeJS.ReadWriteStream {} // Either gulp or gulp-typescript has some odd typings which don't reflect reality, making this required
|
||||
interface CompileStream extends NodeJS.ReadWriteStream { } // Either gulp or gulp-typescript has some odd typings which don't reflect reality, making this required
|
||||
}
|
||||
import * as insert from "gulp-insert";
|
||||
import * as sourcemaps from "gulp-sourcemaps";
|
||||
@@ -34,7 +34,7 @@ import through2 = require("through2");
|
||||
import merge2 = require("merge2");
|
||||
import intoStream = require("into-stream");
|
||||
import * as os from "os";
|
||||
import Linter = require("tslint");
|
||||
import fold = require("travis-fold");
|
||||
const gulp = helpMaker(originalGulp);
|
||||
const mochaParallel = require("./scripts/mocha-parallel.js");
|
||||
const {runTestsInParallel} = mochaParallel;
|
||||
@@ -65,7 +65,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
|
||||
}
|
||||
});
|
||||
|
||||
function exec(cmd: string, args: string[], complete: () => void = (() => {}), error: (e: any, status: number) => void = (() => {})) {
|
||||
function exec(cmd: string, args: string[], complete: () => void = (() => { }), error: (e: any, status: number) => void = (() => { })) {
|
||||
console.log(`${cmd} ${args.join(" ")}`);
|
||||
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
|
||||
const subshellFlag = isWin ? "/c" : "-c";
|
||||
@@ -116,12 +116,12 @@ const es2015LibrarySources = [
|
||||
];
|
||||
|
||||
const es2015LibrarySourceMap = es2015LibrarySources.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const es2016LibrarySource = [ "es2016.array.include.d.ts" ];
|
||||
const es2016LibrarySource = ["es2016.array.include.d.ts"];
|
||||
|
||||
const es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
|
||||
const es2016LibrarySourceMap = es2016LibrarySource.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
@@ -130,38 +130,38 @@ const es2017LibrarySource = [
|
||||
"es2017.sharedmemory.d.ts"
|
||||
];
|
||||
|
||||
const es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
|
||||
const es2017LibrarySourceMap = es2017LibrarySource.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
const librarySourceMap = [
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
|
||||
const libraryTargets = librarySourceMap.map(function (f) {
|
||||
const libraryTargets = librarySourceMap.map(function(f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
});
|
||||
|
||||
for (const i in libraryTargets) {
|
||||
const entry = librarySourceMap[i];
|
||||
const target = libraryTargets[i];
|
||||
const sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
const sources = [copyright].concat(entry.sources.map(function(s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
gulp.task(target, false, [], function() {
|
||||
@@ -391,7 +391,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(tsc(servicesProject));
|
||||
const completedJs = js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."));
|
||||
.pipe(sourcemaps.write("."));
|
||||
const completedDts = dts.pipe(prependCopyright(/*outputCopyright*/true))
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
file.path = standaloneDefinitionsFile;
|
||||
@@ -434,22 +434,22 @@ const tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverli
|
||||
|
||||
gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
|
||||
const serverLibraryProject = tsc.createProject("src/server/tsconfig.library.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
const {js, dts}: {js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream} = serverLibraryProject.src()
|
||||
const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src()
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(newer(tsserverLibraryFile))
|
||||
.pipe(tsc(serverLibraryProject));
|
||||
|
||||
return merge2([
|
||||
js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(builtLocalDirectory)),
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(builtLocalDirectory)),
|
||||
dts.pipe(prependCopyright())
|
||||
.pipe(gulp.dest(builtLocalDirectory))
|
||||
.pipe(gulp.dest(builtLocalDirectory))
|
||||
]);
|
||||
});
|
||||
|
||||
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]);
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ gulp.task(specMd, false, [word2mdJs], (done) => {
|
||||
const specMDFullPath = path.resolve(specMd);
|
||||
const cmd = "cscript //nologo " + word2mdJs + " \"" + specWordFullPath + "\" " + "\"" + specMDFullPath + "\"";
|
||||
console.log(cmd);
|
||||
cp.exec(cmd, function () {
|
||||
cp.exec(cmd, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -492,18 +492,18 @@ gulp.task("dontUseDebugMode", false, [], (done) => { useDebugMode = false; done(
|
||||
|
||||
gulp.task("VerifyLKG", false, [], () => {
|
||||
const expectedFiles = [builtLocalCompiler, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile].concat(libraryTargets);
|
||||
const missingFiles = expectedFiles.filter(function (f) {
|
||||
const missingFiles = expectedFiles.filter(function(f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
throw new Error("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
return gulp.src(expectedFiles).pipe(gulp.dest(LKGDirectory));
|
||||
});
|
||||
|
||||
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"], () => {
|
||||
return runSequence("LKGInternal", "VerifyLKG");
|
||||
@@ -531,8 +531,6 @@ const localRwcBaseline = path.join(internalTests, "baselines/rwc/local");
|
||||
const refRwcBaseline = path.join(internalTests, "baselines/rwc/reference");
|
||||
|
||||
const localTest262Baseline = path.join(internalTests, "baselines/test262/local");
|
||||
const refTest262Baseline = path.join(internalTests, "baselines/test262/reference");
|
||||
|
||||
|
||||
gulp.task("tests", "Builds the test infrastructure using the built compiler", [run]);
|
||||
gulp.task("tests-debug", "Builds the test sources and automation in debug mode", () => {
|
||||
@@ -553,7 +551,7 @@ function restoreSavedNodeEnv() {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
}
|
||||
|
||||
let testTimeout = 20000;
|
||||
let testTimeout = 40000;
|
||||
function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: (e?: any) => void) {
|
||||
const lintFlag = cmdLineOptions["lint"];
|
||||
cleanTestDirs((err) => {
|
||||
@@ -627,7 +625,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
}
|
||||
args.push(run);
|
||||
setNodeEnvToDevelopment();
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function(err) {
|
||||
// last worker clean everything and runs linter in case if there were no errors
|
||||
del(taskConfigsFolder).then(() => {
|
||||
if (!err) {
|
||||
@@ -679,7 +677,7 @@ gulp.task("runtests",
|
||||
["build-rules", "tests"],
|
||||
(done) => {
|
||||
runConsoleTests("mocha-fivemat-progress-reporter", /*runInParallel*/ false, done);
|
||||
});
|
||||
});
|
||||
|
||||
const nodeServerOutFile = "tests/webTestServer.js";
|
||||
const nodeServerInFile = "tests/webTestServer.ts";
|
||||
@@ -811,32 +809,36 @@ gulp.task("diff-rwc", "Diffs the RWC baselines using the diff tool specified by
|
||||
exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], done, done);
|
||||
});
|
||||
|
||||
gulp.task("baseline-accept", "Makes the most recent test results the new baseline, overwriting the old baseline", () => {
|
||||
return baselineAccept("");
|
||||
});
|
||||
|
||||
function baselineAccept(subfolder = "") {
|
||||
return merge2(baselineCopy(subfolder), baselineDelete(subfolder));
|
||||
}
|
||||
|
||||
function baselineCopy(subfolder = "") {
|
||||
return gulp.src([`tests/baselines/local/${subfolder}/**`, `!tests/baselines/local/${subfolder}/**/*.delete`])
|
||||
.pipe(gulp.dest(refBaseline));
|
||||
}
|
||||
|
||||
function baselineDelete(subfolder = "") {
|
||||
return gulp.src(["tests/baselines/local/**/*.delete"])
|
||||
.pipe(insert.transform((content, fileObj) => {
|
||||
const target = path.join(refBaseline, fileObj.relative.substr(0, fileObj.relative.length - ".delete".length));
|
||||
del.sync(target);
|
||||
del.sync(fileObj.path);
|
||||
return "";
|
||||
}));
|
||||
}
|
||||
|
||||
gulp.task("baseline-accept", "Makes the most recent test results the new baseline, overwriting the old baseline", (done) => {
|
||||
const softAccept = cmdLineOptions["soft"];
|
||||
if (!softAccept) {
|
||||
del(refBaseline).then(() => {
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
done();
|
||||
}, done);
|
||||
}
|
||||
else {
|
||||
gulp.src(localBaseline)
|
||||
.pipe(gulp.dest(refBaseline))
|
||||
.on("end", () => {
|
||||
del(path.join(refBaseline, "local")).then(() => done(), done);
|
||||
});
|
||||
}
|
||||
});
|
||||
gulp.task("baseline-accept-rwc", "Makes the most recent rwc test results the new baseline, overwriting the old baseline", () => {
|
||||
return del(refRwcBaseline).then(() => {
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
});
|
||||
return baselineAccept("rwc");
|
||||
});
|
||||
|
||||
|
||||
gulp.task("baseline-accept-test262", "Makes the most recent test262 test results the new baseline, overwriting the old baseline", () => {
|
||||
return del(refTest262Baseline).then(() => {
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
});
|
||||
return baselineAccept("test262");
|
||||
});
|
||||
|
||||
|
||||
@@ -928,26 +930,6 @@ gulp.task("build-rules", "Compiles tslint rules to js", () => {
|
||||
.pipe(gulp.dest(dest));
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("./tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
const ll = new Linter(path, contents, options);
|
||||
console.log("Linting '" + path + "'.");
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFile(options, path) {
|
||||
const contents = fs.readFileSync(path, "utf8");
|
||||
return lintFileContents(options, path, contents);
|
||||
}
|
||||
|
||||
const lintTargets = [
|
||||
"Gulpfile.ts",
|
||||
"src/compiler/**/*.ts",
|
||||
@@ -959,27 +941,72 @@ const lintTargets = [
|
||||
"tests/*.ts", "tests/webhost/*.ts" // Note: does *not* descend recursively
|
||||
];
|
||||
|
||||
function sendNextFile(files: {path: string}[], child: cp.ChildProcess, callback: (failures: number) => void, failures: number) {
|
||||
const file = files.pop();
|
||||
if (file) {
|
||||
console.log(`Linting '${file.path}'.`);
|
||||
child.send({ kind: "file", name: file.path });
|
||||
}
|
||||
else {
|
||||
child.send({ kind: "close" });
|
||||
callback(failures);
|
||||
}
|
||||
}
|
||||
|
||||
function spawnLintWorker(files: {path: string}[], callback: (failures: number) => void) {
|
||||
const child = cp.fork("./scripts/parallel-lint");
|
||||
let failures = 0;
|
||||
child.on("message", function(data) {
|
||||
switch (data.kind) {
|
||||
case "result":
|
||||
if (data.failures > 0) {
|
||||
failures += data.failures;
|
||||
console.log(data.output);
|
||||
}
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
case "error":
|
||||
console.error(data.error);
|
||||
failures++;
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
}
|
||||
});
|
||||
sendNextFile(files, child, callback, failures);
|
||||
}
|
||||
|
||||
gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
|
||||
const fileMatcher = RegExp(cmdLineOptions["files"]);
|
||||
const lintOptions = getLinterOptions();
|
||||
let failed = 0;
|
||||
return gulp.src(lintTargets)
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
if (!fileMatcher.test(file.path)) return contents;
|
||||
const result = lintFile(lintOptions, file.path);
|
||||
if (result.failureCount > 0) {
|
||||
console.log(result.output);
|
||||
failed += result.failureCount;
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
|
||||
let files: {stat: fs.Stats, path: string}[] = [];
|
||||
return gulp.src(lintTargets, { read: false })
|
||||
.pipe(through2.obj((chunk, enc, cb) => {
|
||||
files.push(chunk);
|
||||
cb();
|
||||
}, (cb) => {
|
||||
files = files.filter(file => fileMatcher.test(file.path)).sort((filea, fileb) => filea.stat.size - fileb.stat.size);
|
||||
const workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(files, finished);
|
||||
}
|
||||
return contents; // TODO (weswig): Automatically apply fixes? :3
|
||||
}))
|
||||
.on("end", () => {
|
||||
if (failed > 0) {
|
||||
console.error("Linter errors.");
|
||||
process.exit(1);
|
||||
|
||||
let completed = 0;
|
||||
let failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
throw new Error(`Linter errors: ${failures}`);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
|
||||
+267
-229
@@ -4,7 +4,7 @@ var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
var Linter = require("tslint");
|
||||
var fold = require("travis-fold");
|
||||
var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
|
||||
|
||||
// Variables
|
||||
@@ -27,9 +27,31 @@ var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
|
||||
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
|
||||
if (process.env.path !== undefined) {
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
} else if (process.env.PATH !== undefined) {
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
}
|
||||
|
||||
function toNs(diff) {
|
||||
return diff[0] * 1e9 + diff[1];
|
||||
}
|
||||
|
||||
function mark() {
|
||||
if (!fold.isTravis()) return;
|
||||
var stamp = process.hrtime();
|
||||
var id = Math.floor(Math.random() * 0xFFFFFFFF).toString(16);
|
||||
console.log("travis_time:start:" + id + "\r");
|
||||
return {
|
||||
stamp: stamp,
|
||||
id: id
|
||||
};
|
||||
}
|
||||
|
||||
function measure(marker) {
|
||||
if (!fold.isTravis()) return;
|
||||
var diff = process.hrtime(marker.stamp);
|
||||
var total = [marker.stamp[0] + diff[0], marker.stamp[1] + diff[1]];
|
||||
console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r");
|
||||
}
|
||||
|
||||
var compilerSources = [
|
||||
@@ -184,7 +206,8 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"convertCompilerOptionsFromJson.ts",
|
||||
"convertTypingOptionsFromJson.ts",
|
||||
"tsserverProjectSystem.ts",
|
||||
"matchFiles.ts"
|
||||
"matchFiles.ts",
|
||||
"initializeTSConfig.ts",
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
@@ -208,11 +231,11 @@ var es2015LibrarySources = [
|
||||
"es2015.symbol.wellknown.d.ts"
|
||||
];
|
||||
|
||||
var es2015LibrarySourceMap = es2015LibrarySources.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
var es2015LibrarySourceMap = es2015LibrarySources.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
var es2016LibrarySource = [ "es2016.array.include.d.ts" ];
|
||||
var es2016LibrarySource = ["es2016.array.include.d.ts"];
|
||||
|
||||
var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
@@ -230,21 +253,21 @@ var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
|
||||
var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
var librarySourceMap = [
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
// Host library
|
||||
{ target: "lib.dom.d.ts", sources: ["header.d.ts", "dom.generated.d.ts"] },
|
||||
{ target: "lib.dom.iterable.d.ts", sources: ["header.d.ts", "dom.iterable.d.ts"] },
|
||||
{ target: "lib.webworker.d.ts", sources: ["header.d.ts", "webworker.generated.d.ts"] },
|
||||
{ target: "lib.scripthost.d.ts", sources: ["header.d.ts", "scripthost.d.ts"] },
|
||||
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
// JavaScript library
|
||||
{ target: "lib.es5.d.ts", sources: ["header.d.ts", "es5.d.ts"] },
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
|
||||
var libraryTargets = librarySourceMap.map(function (f) {
|
||||
@@ -260,7 +283,7 @@ function prependFile(prefixFile, destinationFile) {
|
||||
fail(destinationFile + " failed to be created!");
|
||||
}
|
||||
var temp = "temptemp";
|
||||
jake.cpR(prefixFile, temp, {silent: true});
|
||||
jake.cpR(prefixFile, temp, { silent: true });
|
||||
fs.appendFileSync(temp, fs.readFileSync(destinationFile));
|
||||
fs.renameSync(temp, destinationFile);
|
||||
}
|
||||
@@ -272,11 +295,11 @@ function concatenateFiles(destinationFile, sourceFiles) {
|
||||
if (!fs.existsSync(sourceFiles[0])) {
|
||||
fail(sourceFiles[0] + " does not exist!");
|
||||
}
|
||||
jake.cpR(sourceFiles[0], temp, {silent: true});
|
||||
jake.cpR(sourceFiles[0], temp, { silent: true });
|
||||
// append all files in sequence
|
||||
for (var i = 1; i < sourceFiles.length; i++) {
|
||||
if (!fs.existsSync(sourceFiles[i])) {
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
fail(sourceFiles[i] + " does not exist!");
|
||||
}
|
||||
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
|
||||
}
|
||||
@@ -314,9 +337,10 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
if (process.env.USE_TRANSFORMS === "false") {
|
||||
useBuiltCompiler = false;
|
||||
}
|
||||
var startCompileTime = mark();
|
||||
opts = opts || {};
|
||||
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler;
|
||||
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
|
||||
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
|
||||
if (opts.types) {
|
||||
options += opts.types.join(",");
|
||||
}
|
||||
@@ -346,7 +370,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
options += " --module commonjs";
|
||||
}
|
||||
|
||||
if(opts.noResolve) {
|
||||
if (opts.noResolve) {
|
||||
options += " --noResolve";
|
||||
}
|
||||
|
||||
@@ -373,13 +397,13 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
if (!useDebugMode && prefixes && fs.existsSync(outFile)) {
|
||||
for (var i in prefixes) {
|
||||
prependFile(prefixes[i], outFile);
|
||||
@@ -390,14 +414,16 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
callback();
|
||||
}
|
||||
|
||||
measure(startCompileTime);
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function() {
|
||||
ex.addListener("error", function () {
|
||||
fs.unlinkSync(outFile);
|
||||
fail("Compilation of " + outFile + " unsuccessful");
|
||||
measure(startCompileTime);
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
}
|
||||
|
||||
// Prerequisite task for built directory and library typings
|
||||
@@ -410,7 +436,7 @@ for (var i in libraryTargets) {
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
file(target, [builtLocalDirectory].concat(sources), function () {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
})(i);
|
||||
@@ -433,30 +459,30 @@ file(processDiagnosticMessagesTs);
|
||||
|
||||
// processDiagnosticMessages script
|
||||
compileFile(processDiagnosticMessagesJs,
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
|
||||
file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () {
|
||||
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
var cmd = host + " " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
file(builtGeneratedDiagnosticMessagesJSON,[generatedDiagnosticMessagesJSON], function() {
|
||||
file(builtGeneratedDiagnosticMessagesJSON, [generatedDiagnosticMessagesJSON], function () {
|
||||
if (fs.existsSync(builtLocalDirectory)) {
|
||||
jake.cpR(generatedDiagnosticMessagesJSON, builtGeneratedDiagnosticMessagesJSON);
|
||||
}
|
||||
@@ -474,17 +500,17 @@ var programTs = path.join(compilerDirectory, "program.ts");
|
||||
file(configureNightlyTs);
|
||||
|
||||
compileFile(/*outfile*/configureNightlyJs,
|
||||
/*sources*/ [configureNightlyTs],
|
||||
/*prereqs*/ [configureNightlyTs],
|
||||
/*prefixes*/ [],
|
||||
/*sources*/[configureNightlyTs],
|
||||
/*prereqs*/[configureNightlyTs],
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler*/ false,
|
||||
{ noOutFile: false, generateDeclarations: false, keepComments: false, noResolve: false, stripInternal: false });
|
||||
{ noOutFile: false, generateDeclarations: false, keepComments: false, noResolve: false, stripInternal: false });
|
||||
|
||||
task("setDebugMode", function() {
|
||||
task("setDebugMode", function () {
|
||||
useDebugMode = true;
|
||||
});
|
||||
|
||||
task("configure-nightly", [configureNightlyJs], function() {
|
||||
task("configure-nightly", [configureNightlyJs], function () {
|
||||
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
@@ -525,63 +551,65 @@ var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
var nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_standalone.d.ts");
|
||||
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*opts*/ { noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true
|
||||
},
|
||||
/*opts*/ {
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true
|
||||
},
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
jake.cpR(servicesFile, nodePackageFile, { silent: true });
|
||||
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, { silent: true });
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
|
||||
compileFile(
|
||||
servicesFileInBrowserTest,
|
||||
servicesSources,
|
||||
[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{ noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
noMapRoot: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
{
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
noMapRoot: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"] });
|
||||
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/[copyright], /*useBuiltCompiler*/ true, { types: ["node"] });
|
||||
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
compileFile(
|
||||
tsserverLibraryFile,
|
||||
languageServiceLibrarySources,
|
||||
[builtLocalDirectory, copyright].concat(languageServiceLibrarySources),
|
||||
/*prefixes*/ [copyright],
|
||||
[builtLocalDirectory, copyright, builtLocalCompiler].concat(languageServiceLibrarySources).concat(libraryTargets),
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{ noOutFile: false, generateDeclarations: true });
|
||||
|
||||
@@ -589,9 +617,19 @@ compileFile(
|
||||
desc("Builds language service server library");
|
||||
task("lssl", [tsserverLibraryFile, tsserverLibraryDefinitionFile]);
|
||||
|
||||
desc("Emit the start of the build fold");
|
||||
task("build-fold-start", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("build"));
|
||||
});
|
||||
|
||||
desc("Emit the end of the build fold");
|
||||
task("build-fold-end", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.end("build"));
|
||||
});
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON]);
|
||||
task("local", ["build-fold-start", "generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON, "lssl", "build-fold-end"]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
@@ -599,7 +637,7 @@ task("tsc", ["generate-diagnostics", "lib", tscFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Sets release mode flag");
|
||||
task("release", function() {
|
||||
task("release", function () {
|
||||
useDebugMode = false;
|
||||
});
|
||||
|
||||
@@ -609,7 +647,7 @@ task("default", ["local"]);
|
||||
|
||||
// Cleans the built directory
|
||||
desc("Cleans the compiler output, declare files, and tests");
|
||||
task("clean", function() {
|
||||
task("clean", function () {
|
||||
jake.rmRf(builtDirectory);
|
||||
});
|
||||
|
||||
@@ -623,9 +661,9 @@ file(word2mdTs);
|
||||
|
||||
// word2md script
|
||||
compileFile(word2mdJs,
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
|
||||
// The generated spec.md; built for the 'generate-spec' task
|
||||
@@ -637,7 +675,7 @@ file(specMd, [word2mdJs, specWord], function () {
|
||||
child_process.exec(cmd, function () {
|
||||
complete();
|
||||
});
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
|
||||
desc("Generates a Markdown version of the Language Specification");
|
||||
@@ -646,14 +684,14 @@ task("generate-spec", [specMd]);
|
||||
|
||||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local", "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 missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
if (missingFiles.length > 0) {
|
||||
fail("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory +
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
". The following files are missing:\n" + missingFiles.join("\n"));
|
||||
}
|
||||
// Copy all the targets into the LKG directory
|
||||
jake.mkdirP(LKGDirectory);
|
||||
@@ -674,8 +712,8 @@ var run = path.join(builtLocalDirectory, "run.js");
|
||||
compileFile(
|
||||
/*outFile*/ run,
|
||||
/*source*/ harnessSources,
|
||||
/*prereqs*/ [builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/ [],
|
||||
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler:*/ true,
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"] });
|
||||
|
||||
@@ -694,22 +732,22 @@ desc("Builds the test infrastructure using the built compiler");
|
||||
task("tests", ["local", run].concat(libraryTargets));
|
||||
|
||||
function exec(cmd, completeHandler, errorHandler) {
|
||||
var ex = jake.createExec([cmd], {windowsVerbatimArguments: true});
|
||||
var ex = jake.createExec([cmd], { windowsVerbatimArguments: true });
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
ex.addListener("stdout", function (output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
ex.addListener("stderr", function (error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
if (completeHandler) {
|
||||
completeHandler();
|
||||
}
|
||||
complete();
|
||||
});
|
||||
ex.addListener("error", function(e, status) {
|
||||
if(errorHandler) {
|
||||
ex.addListener("error", function (e, status) {
|
||||
if (errorHandler) {
|
||||
errorHandler(e, status);
|
||||
} else {
|
||||
fail("Process exited with code " + status);
|
||||
@@ -797,7 +835,8 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
if(!runInParallel) {
|
||||
if (!runInParallel) {
|
||||
var startTime = mark();
|
||||
tests = tests ? ' -g "' + tests + '"' : '';
|
||||
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
@@ -806,10 +845,12 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
process.env.NODE_ENV = "development";
|
||||
exec(cmd, function () {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
measure(startTime);
|
||||
runLinter();
|
||||
finish();
|
||||
}, function(e, status) {
|
||||
}, function (e, status) {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
measure(startTime);
|
||||
finish(status);
|
||||
});
|
||||
|
||||
@@ -817,9 +858,10 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
else {
|
||||
var savedNodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = "development";
|
||||
var startTime = mark();
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
|
||||
measure(startTime);
|
||||
// last worker clean everything and runs linter in case if there were no errors
|
||||
deleteTemporaryProjectOutput();
|
||||
jake.rmRf(taskConfigsFolder);
|
||||
@@ -860,14 +902,14 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () {
|
||||
runConsoleTests('min', /*runInParallel*/ true);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Runs the tests using the built run.js file. Optional arguments are: t[ests]=regex r[eporter]=[list|spec|json|<more>] d[ebug]=true color[s]=false lint=true bail=false dirty=false.");
|
||||
task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
runConsoleTests('mocha-fivemat-progress-reporter', /*runInParallel*/ false);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Generates code coverage data via instanbul");
|
||||
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
@@ -885,20 +927,20 @@ desc("Runs browserify on run.js to produce a file suitable for running tests in
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
var cmd = 'browserify built/local/run.js -t ./scripts/browserify-optional -d -o built/local/bundle.js';
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function() {
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function () {
|
||||
cleanTestDirs();
|
||||
host = "node";
|
||||
browser = process.env.browser || process.env.b || "IE";
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
if (fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests || light) {
|
||||
if (tests || light) {
|
||||
writeTestConfigFile(tests, light);
|
||||
}
|
||||
|
||||
@@ -906,7 +948,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi
|
||||
var cmd = host + " tests/webTestServer.js " + browser + " " + JSON.stringify(tests);
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
function getDiffTool() {
|
||||
var program = process.env['DIFF'];
|
||||
@@ -919,17 +961,17 @@ function getDiffTool() {
|
||||
// Baseline Diff
|
||||
desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable");
|
||||
task('diff-rwc', function () {
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
desc("Builds the test sources and automation in debug mode");
|
||||
task("tests-debug", ["setDebugMode", "tests"]);
|
||||
@@ -937,30 +979,39 @@ task("tests-debug", ["setDebugMode", "tests"]);
|
||||
|
||||
// Makes the test results the new baseline
|
||||
desc("Makes the most recent test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept", function(hardOrSoft) {
|
||||
if (!hardOrSoft || hardOrSoft === "hard") {
|
||||
jake.rmRf(refBaseline);
|
||||
fs.renameSync(localBaseline, refBaseline);
|
||||
}
|
||||
else if (hardOrSoft === "soft") {
|
||||
var files = jake.readdirR(localBaseline);
|
||||
for (var i in files) {
|
||||
jake.cpR(files[i], refBaseline);
|
||||
}
|
||||
jake.rmRf(path.join(refBaseline, "local"));
|
||||
}
|
||||
task("baseline-accept", function () {
|
||||
acceptBaseline("");
|
||||
});
|
||||
|
||||
function acceptBaseline(containerFolder) {
|
||||
var sourceFolder = path.join(localBaseline, containerFolder);
|
||||
var targetFolder = path.join(refBaseline, containerFolder);
|
||||
console.log('Accept baselines from ' + sourceFolder + ' to ' + targetFolder);
|
||||
var files = fs.readdirSync(sourceFolder);
|
||||
var deleteEnding = '.delete';
|
||||
for (var i in files) {
|
||||
var filename = files[i];
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
} else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desc("Makes the most recent rwc test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-rwc", function() {
|
||||
jake.rmRf(refRwcBaseline);
|
||||
fs.renameSync(localRwcBaseline, refRwcBaseline);
|
||||
task("baseline-accept-rwc", function () {
|
||||
acceptBaseline("rwc");
|
||||
});
|
||||
|
||||
desc("Makes the most recent test262 test results the new baseline, overwriting the old baseline");
|
||||
task("baseline-accept-test262", function() {
|
||||
jake.rmRf(refTest262Baseline);
|
||||
fs.renameSync(localTest262Baseline, refTest262Baseline);
|
||||
task("baseline-accept-test262", function () {
|
||||
acceptBaseline("test262");
|
||||
});
|
||||
|
||||
|
||||
@@ -970,8 +1021,8 @@ var webhostJsPath = "tests/webhost/webtsc.js";
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true);
|
||||
|
||||
desc("Builds the tsc web host");
|
||||
task("webhost", [webhostJsPath], function() {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true});
|
||||
task("webhost", [webhostJsPath], function () {
|
||||
jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", { silent: true });
|
||||
});
|
||||
|
||||
// Perf compiler
|
||||
@@ -984,38 +1035,38 @@ task("perftsc", [perftscJsPath]);
|
||||
// Instrumented compiler
|
||||
var loggedIOpath = harnessDirectory + 'loggedIO.ts';
|
||||
var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js';
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
|
||||
file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () {
|
||||
var temp = builtLocalDirectory + 'temp';
|
||||
jake.mkdirP(temp);
|
||||
var options = "--outdir " + temp + ' ' + loggedIOpath;
|
||||
var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " ";
|
||||
console.log(cmd + "\n");
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath);
|
||||
jake.rmRf(temp);
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, {async: true});
|
||||
}, { async: true });
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () {
|
||||
var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
ex.addListener("cmdEnd", function() {
|
||||
ex.addListener("cmdEnd", function () {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, { async: true });
|
||||
|
||||
desc("Updates the sublime plugin's tsserver");
|
||||
task("update-sublime", ["local", serverFile], function() {
|
||||
task("update-sublime", ["local", serverFile], function () {
|
||||
jake.cpR(serverFile, "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
jake.cpR(serverFile + ".map", "../TypeScript-Sublime-Plugin/tsserver/");
|
||||
});
|
||||
@@ -1031,124 +1082,111 @@ var tslintRules = [
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"noTypeAssertionWhitespaceRule"
|
||||
];
|
||||
var tslintRulesFiles = tslintRules.map(function(p) {
|
||||
var tslintRulesFiles = tslintRules.map(function (p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
});
|
||||
var tslintRulesOutFiles = tslintRules.map(function(p) {
|
||||
var tslintRulesOutFiles = tslintRules.map(function (p) {
|
||||
return path.join(builtLocalDirectory, "tslint", p + ".js");
|
||||
});
|
||||
desc("Compiles tslint rules to js");
|
||||
task("build-rules", tslintRulesOutFiles);
|
||||
tslintRulesFiles.forEach(function(ruleFile, i) {
|
||||
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
|
||||
tslintRulesFiles.forEach(function (ruleFile, i) {
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint")});
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint") });
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("./tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
desc("Emit the start of the build-rules fold");
|
||||
task("build-rules-start", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("build-rules"));
|
||||
});
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
var ll = new Linter(path, contents, options);
|
||||
console.log("Linting '" + path + "'.");
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFile(options, path) {
|
||||
var contents = fs.readFileSync(path, "utf8");
|
||||
return lintFileContents(options, path, contents);
|
||||
}
|
||||
|
||||
function lintFileAsync(options, path, cb) {
|
||||
fs.readFile(path, "utf8", function(err, contents) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
var result = lintFileContents(options, path, contents);
|
||||
cb(undefined, result);
|
||||
});
|
||||
}
|
||||
desc("Emit the end of the build-rules fold");
|
||||
task("build-rules-end", [], function () {
|
||||
if (fold.isTravis()) console.log(fold.end("build-rules"));
|
||||
});
|
||||
|
||||
var lintTargets = compilerSources
|
||||
.concat(harnessSources)
|
||||
// Other harness sources
|
||||
.concat(["instrumenter.ts"].map(function(f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(["instrumenter.ts"].map(function (f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(serverCoreSources)
|
||||
.concat(tslintRulesFiles)
|
||||
.concat(servicesSources)
|
||||
.concat(["Gulpfile.ts"])
|
||||
.concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath]);
|
||||
|
||||
function sendNextFile(files, child, callback, failures) {
|
||||
var file = files.pop();
|
||||
if (file) {
|
||||
console.log("Linting '" + file + "'.");
|
||||
child.send({ kind: "file", name: file });
|
||||
}
|
||||
else {
|
||||
child.send({ kind: "close" });
|
||||
callback(failures);
|
||||
}
|
||||
}
|
||||
|
||||
function spawnLintWorker(files, callback) {
|
||||
var child = child_process.fork("./scripts/parallel-lint");
|
||||
var failures = 0;
|
||||
child.on("message", function (data) {
|
||||
switch (data.kind) {
|
||||
case "result":
|
||||
if (data.failures > 0) {
|
||||
failures += data.failures;
|
||||
console.log(data.output);
|
||||
}
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
case "error":
|
||||
console.error(data.error);
|
||||
failures++;
|
||||
sendNextFile(files, child, callback, failures);
|
||||
break;
|
||||
}
|
||||
});
|
||||
sendNextFile(files, child, callback, failures);
|
||||
}
|
||||
|
||||
desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
|
||||
task("lint", ["build-rules"], function() {
|
||||
var lintOptions = getLinterOptions();
|
||||
task("lint", ["build-rules"], function () {
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
var startTime = mark();
|
||||
var failed = 0;
|
||||
var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || "");
|
||||
var done = {};
|
||||
for (var i in lintTargets) {
|
||||
var target = lintTargets[i];
|
||||
if (!done[target] && fileMatcher.test(target)) {
|
||||
var result = lintFile(lintOptions, target);
|
||||
if (result.failureCount > 0) {
|
||||
console.log(result.output);
|
||||
failed += result.failureCount;
|
||||
}
|
||||
done[target] = true;
|
||||
done[target] = fs.statSync(target).size;
|
||||
}
|
||||
}
|
||||
if (failed > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This is required because file watches on Windows get fires _twice_
|
||||
* when a file changes on some node/windows version configuations
|
||||
* (node v4 and win 10, for example). By not running a lint for a file
|
||||
* which already has a pending lint, we avoid duplicating our work.
|
||||
* (And avoid printing duplicate results!)
|
||||
*/
|
||||
var lintSemaphores = {};
|
||||
var workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
|
||||
function lintWatchFile(filename) {
|
||||
fs.watch(filename, {persistent: true}, function(event) {
|
||||
if (event !== "change") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lintSemaphores[filename]) {
|
||||
lintSemaphores[filename] = true;
|
||||
lintFileAsync(getLinterOptions(), filename, function(err, result) {
|
||||
delete lintSemaphores[filename];
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
if (result.failureCount > 0) {
|
||||
console.log("***Lint failure***");
|
||||
for (var i = 0; i < result.failures.length; i++) {
|
||||
var failure = result.failures[i];
|
||||
var start = failure.startPosition.lineAndCharacter;
|
||||
var end = failure.endPosition.lineAndCharacter;
|
||||
console.log("warning " + filename + " (" + (start.line + 1) + "," + (start.character + 1) + "," + (end.line + 1) + "," + (end.character + 1) + "): " + failure.failure);
|
||||
}
|
||||
console.log("*** Total " + result.failureCount + " failures.");
|
||||
}
|
||||
});
|
||||
}
|
||||
var names = Object.keys(done).sort(function (namea, nameb) {
|
||||
return done[namea] - done[nameb];
|
||||
});
|
||||
}
|
||||
|
||||
desc("Watches files for changes to rerun a lint pass");
|
||||
task("lint-server", ["build-rules"], function() {
|
||||
console.log("Watching ./src for changes to linted files");
|
||||
for (var i = 0; i < lintTargets.length; i++) {
|
||||
lintWatchFile(lintTargets[i]);
|
||||
for (var i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(names, finished);
|
||||
}
|
||||
});
|
||||
|
||||
var completed = 0;
|
||||
var failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
measure(startTime);
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { async: true });
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
[](https://gitter.im/Microsoft/TypeScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](http://blogs.msdn.com/typescript) and [Twitter account](https://twitter.com/typescriptlang).
|
||||
[TypeScript](http://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types, classes, and modules to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](http://www.typescriptlang.org/Playground), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescriptlang).
|
||||
|
||||
## Installing
|
||||
|
||||
|
||||
+4
-2
@@ -30,8 +30,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/browserify": "latest",
|
||||
"@types/convert-source-map": "latest",
|
||||
"@types/chai": "latest",
|
||||
"@types/convert-source-map": "latest",
|
||||
"@types/del": "latest",
|
||||
"@types/glob": "latest",
|
||||
"@types/gulp": "latest",
|
||||
@@ -69,9 +69,11 @@
|
||||
"mkdirp": "latest",
|
||||
"mocha": "latest",
|
||||
"mocha-fivemat-progress-reporter": "latest",
|
||||
"q": "latest",
|
||||
"run-sequence": "latest",
|
||||
"sorcery": "latest",
|
||||
"through2": "latest",
|
||||
"travis-fold": "latest",
|
||||
"ts-node": "latest",
|
||||
"tsd": "latest",
|
||||
"tslint": "next",
|
||||
@@ -79,7 +81,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"pretest": "jake tests",
|
||||
"test": "jake runtests",
|
||||
"test": "jake runtests-parallel",
|
||||
"build": "npm run build:compiler && npm run build:tests",
|
||||
"build:compiler": "jake local",
|
||||
"build:tests": "jake tests",
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../src/harness/external/node.d.ts" />
|
||||
/// <reference types="node"/>
|
||||
|
||||
import fs = require('fs');
|
||||
import path = require('path');
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
var Linter = require("tslint");
|
||||
var fs = require("fs");
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
configuration: require("../tslint.json"),
|
||||
formatter: "prose",
|
||||
formattersDirectory: undefined,
|
||||
rulesDirectory: "built/local/tslint"
|
||||
};
|
||||
}
|
||||
|
||||
function lintFileContents(options, path, contents) {
|
||||
var ll = new Linter(path, contents, options);
|
||||
return ll.lint();
|
||||
}
|
||||
|
||||
function lintFileAsync(options, path, cb) {
|
||||
fs.readFile(path, "utf8", function (err, contents) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
var result = lintFileContents(options, path, contents);
|
||||
cb(undefined, result);
|
||||
});
|
||||
}
|
||||
|
||||
process.on("message", function (data) {
|
||||
switch (data.kind) {
|
||||
case "file":
|
||||
var target = data.name;
|
||||
var lintOptions = getLinterOptions();
|
||||
lintFileAsync(lintOptions, target, function (err, result) {
|
||||
if (err) {
|
||||
process.send({ kind: "error", error: err.toString() });
|
||||
return;
|
||||
}
|
||||
process.send({ kind: "result", failures: result.failureCount, output: result.output });
|
||||
});
|
||||
break;
|
||||
case "close":
|
||||
process.exit(0);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -69,7 +69,7 @@ function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosti
|
||||
}
|
||||
|
||||
function buildUniqueNameMap(names: string[]): ts.Map<string> {
|
||||
var nameMap: ts.Map<string> = {};
|
||||
var nameMap = ts.createMap<string>();
|
||||
|
||||
var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as Lint from "tslint/lib/lint";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (identifier: string) => `Identifier '${identifier}' never appears on the LHS of an assignment - use const instead of let for its declaration.`;
|
||||
|
||||
@@ -64,7 +63,7 @@ interface DeclarationUsages {
|
||||
}
|
||||
|
||||
class PreferConstWalker extends Lint.RuleWalker {
|
||||
private inScopeLetDeclarations: ts.Map<DeclarationUsages>[] = [];
|
||||
private inScopeLetDeclarations: ts.MapLike<DeclarationUsages>[] = [];
|
||||
private errors: Lint.RuleFailure[] = [];
|
||||
private markAssignment(identifier: ts.Identifier) {
|
||||
const name = identifier.text;
|
||||
@@ -172,7 +171,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
|
||||
private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
const names: ts.MapLike<DeclarationUsages> = {};
|
||||
if (isLet(node.initializer)) {
|
||||
if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) {
|
||||
this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names);
|
||||
@@ -194,7 +193,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
|
||||
visitBlock(node: ts.Block) {
|
||||
const names: ts.Map<DeclarationUsages> = {};
|
||||
const names: ts.MapLike<DeclarationUsages> = {};
|
||||
for (const statement of node.statements) {
|
||||
if (statement.kind === ts.SyntaxKind.VariableStatement) {
|
||||
this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names);
|
||||
@@ -205,7 +204,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
this.popDeclarations();
|
||||
}
|
||||
|
||||
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.Map<DeclarationUsages>) {
|
||||
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.MapLike<DeclarationUsages>) {
|
||||
for (const node of list.declarations) {
|
||||
if (isLet(node) && !isExported(node)) {
|
||||
this.collectNameIdentifiers(node, node.name, ret);
|
||||
@@ -213,7 +212,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
}
|
||||
|
||||
private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.MapLike<DeclarationUsages>) {
|
||||
if (node.kind === ts.SyntaxKind.Identifier) {
|
||||
table[(node as ts.Identifier).text] = { declaration, usages: 0 };
|
||||
}
|
||||
@@ -222,7 +221,7 @@ class PreferConstWalker extends Lint.RuleWalker {
|
||||
}
|
||||
}
|
||||
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.MapLike<DeclarationUsages>) {
|
||||
for (const element of pattern.elements) {
|
||||
this.collectNameIdentifiers(value, element.name, table);
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -10,7 +10,7 @@ declare module "gulp-insert" {
|
||||
export function append(text: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function prepend(text: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function wrap(text: string | Buffer, tail: string | Buffer): NodeJS.ReadWriteStream;
|
||||
export function transform(cb: (contents: string, file: {path: string}) => string): NodeJS.ReadWriteStream; // file is a vinyl file
|
||||
export function transform(cb: (contents: string, file: {path: string, relative: string}) => string): NodeJS.ReadWriteStream; // file is a vinyl file
|
||||
}
|
||||
|
||||
declare module "into-stream" {
|
||||
@@ -22,3 +22,4 @@ declare module "into-stream" {
|
||||
}
|
||||
|
||||
declare module "sorcery";
|
||||
declare module "travis-fold";
|
||||
|
||||
+70
-55
@@ -89,9 +89,10 @@ namespace ts {
|
||||
const binder = createBinder();
|
||||
|
||||
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeBind");
|
||||
binder(file, options);
|
||||
performance.measure("Bind", start);
|
||||
performance.mark("afterBind");
|
||||
performance.measure("Bind", "beforeBind", "afterBind");
|
||||
}
|
||||
|
||||
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
@@ -139,7 +140,7 @@ namespace ts {
|
||||
options = opts;
|
||||
languageVersion = getEmitScriptTarget(options);
|
||||
inStrictMode = !!file.externalModuleIndicator;
|
||||
classifiableNames = {};
|
||||
classifiableNames = createMap<string>();
|
||||
symbolCount = 0;
|
||||
skipTransformFlagAggregation = isDeclarationFile(file);
|
||||
|
||||
@@ -189,11 +190,11 @@ namespace ts {
|
||||
symbol.declarations.push(node);
|
||||
|
||||
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
|
||||
symbol.exports = {};
|
||||
symbol.exports = createMap<Symbol>();
|
||||
}
|
||||
|
||||
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
|
||||
symbol.members = {};
|
||||
symbol.members = createMap<Symbol>();
|
||||
}
|
||||
|
||||
if (symbolFlags & SymbolFlags.Value) {
|
||||
@@ -304,8 +305,10 @@ namespace ts {
|
||||
const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
|
||||
|
||||
let symbol: Symbol;
|
||||
if (name !== undefined) {
|
||||
|
||||
if (name === undefined) {
|
||||
symbol = createSymbol(SymbolFlags.None, "__missing");
|
||||
}
|
||||
else {
|
||||
// Check and see if the symbol table already has a symbol with this name. If not,
|
||||
// create a new symbol with this name and add it to the table. Note that we don't
|
||||
// give the new symbol any flags *yet*. This ensures that it will not conflict
|
||||
@@ -317,6 +320,11 @@ namespace ts {
|
||||
// declaration we have for this symbol, and then create a new symbol for this
|
||||
// declaration.
|
||||
//
|
||||
// Note that when properties declared in Javascript constructors
|
||||
// (marked by isReplaceableByMethod) conflict with another symbol, the property loses.
|
||||
// Always. This allows the common Javascript pattern of overwriting a prototype method
|
||||
// with an bound instance method of the same type: `this.method = this.method.bind(this)`
|
||||
//
|
||||
// If we created a new symbol, either because we didn't have a symbol with this name
|
||||
// in the symbol table, or we conflicted with an existing symbol, then just add this
|
||||
// node as the sole declaration of the new symbol.
|
||||
@@ -324,42 +332,44 @@ namespace ts {
|
||||
// Otherwise, we'll be merging into a compatible existing symbol (for example when
|
||||
// you have multiple 'vars' with the same name in the same container). In this case
|
||||
// just add this node into the declarations list of the symbol.
|
||||
symbol = hasProperty(symbolTable, name)
|
||||
? symbolTable[name]
|
||||
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
|
||||
symbol = symbolTable[name] || (symbolTable[name] = createSymbol(SymbolFlags.None, name));
|
||||
|
||||
if (name && (includes & SymbolFlags.Classifiable)) {
|
||||
classifiableNames[name] = name;
|
||||
}
|
||||
|
||||
if (symbol.flags & excludes) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
if (symbol.isReplaceableByMethod) {
|
||||
// Javascript constructor-declared symbols can be discarded in favor of
|
||||
// prototype symbols like methods.
|
||||
symbol = symbolTable[name] = createSymbol(SymbolFlags.None, name);
|
||||
}
|
||||
|
||||
// Report errors every position with duplicate declaration
|
||||
// Report errors on previous encountered declarations
|
||||
let message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
if (hasModifier(declaration, ModifierFlags.Default)) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
else {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
});
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
// Report errors every position with duplicate declaration
|
||||
// Report errors on previous encountered declarations
|
||||
let message = symbol.flags & SymbolFlags.BlockScopedVariable
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
|
||||
symbol = createSymbol(SymbolFlags.None, name);
|
||||
forEach(symbol.declarations, declaration => {
|
||||
if (hasModifier(declaration, ModifierFlags.Default)) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
}
|
||||
});
|
||||
|
||||
forEach(symbol.declarations, declaration => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
|
||||
});
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
|
||||
|
||||
symbol = createSymbol(SymbolFlags.None, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
symbol = createSymbol(SymbolFlags.None, "__missing");
|
||||
}
|
||||
|
||||
addDeclarationToSymbol(symbol, node, includes);
|
||||
symbol.parent = parent;
|
||||
@@ -440,7 +450,7 @@ namespace ts {
|
||||
if (containerFlags & ContainerFlags.IsContainer) {
|
||||
container = blockScopeContainer = node;
|
||||
if (containerFlags & ContainerFlags.HasLocals) {
|
||||
container.locals = {};
|
||||
container.locals = createMap<Symbol>();
|
||||
}
|
||||
addToContainerChain(container);
|
||||
}
|
||||
@@ -1422,7 +1432,8 @@ namespace ts {
|
||||
|
||||
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
|
||||
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
|
||||
typeLiteralSymbol.members = { [symbol.name]: symbol };
|
||||
typeLiteralSymbol.members = createMap<Symbol>();
|
||||
typeLiteralSymbol.members[symbol.name] = symbol;
|
||||
}
|
||||
|
||||
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
|
||||
@@ -1432,7 +1443,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (inStrictMode) {
|
||||
const seen: Map<ElementKind> = {};
|
||||
const seen = createMap<ElementKind>();
|
||||
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name.kind !== SyntaxKind.Identifier) {
|
||||
@@ -1488,7 +1499,7 @@ namespace ts {
|
||||
// fall through.
|
||||
default:
|
||||
if (!blockScopeContainer.locals) {
|
||||
blockScopeContainer.locals = {};
|
||||
blockScopeContainer.locals = createMap<Symbol>();
|
||||
addToContainerChain(blockScopeContainer);
|
||||
}
|
||||
declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
@@ -1913,18 +1924,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
|
||||
const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (<ExportAssignment>node).expression : (<BinaryExpression>node).right;
|
||||
if (!container.symbol || !container.symbol.exports) {
|
||||
// Export assignment in some sort of block construct
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
|
||||
}
|
||||
else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) {
|
||||
// An export default clause with an identifier exports all meanings of that identifier
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
}
|
||||
else {
|
||||
// An export default clause with an expression exports a value
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node)
|
||||
// An export default clause with an EntityNameExpression exports all meanings of that identifier
|
||||
? SymbolFlags.Alias
|
||||
// An export default clause with any other expression exports a value
|
||||
: SymbolFlags.Property;
|
||||
declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1951,7 +1961,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);
|
||||
}
|
||||
|
||||
@@ -1993,20 +2003,25 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
// Declare a 'member' in case it turns out the container was an ES5 class or ES6 constructor
|
||||
let assignee: Node;
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
|
||||
assignee = container;
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
else if (container.kind === SyntaxKind.Constructor) {
|
||||
assignee = container.parent;
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const saveContainer = container;
|
||||
container = container.parent;
|
||||
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// constructor-declared symbols can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
container = saveContainer;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
assignee.symbol.members = assignee.symbol.members || {};
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(assignee.symbol.members, assignee.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
|
||||
function bindPrototypePropertyAssignment(node: BinaryExpression) {
|
||||
@@ -2030,7 +2045,7 @@ namespace ts {
|
||||
|
||||
// Set up the members collection if it doesn't exist already
|
||||
if (!funcSymbol.members) {
|
||||
funcSymbol.members = {};
|
||||
funcSymbol.members = createMap<Symbol>();
|
||||
}
|
||||
|
||||
// Declare the method/property
|
||||
@@ -2079,7 +2094,7 @@ namespace ts {
|
||||
// module might have an exported variable called 'prototype'. We can't allow that as
|
||||
// that would clash with the built-in 'prototype' for the class.
|
||||
const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
|
||||
if (hasProperty(symbol.exports, prototypeSymbol.name)) {
|
||||
if (symbol.exports[prototypeSymbol.name]) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
|
||||
+698
-492
File diff suppressed because it is too large
Load Diff
@@ -62,10 +62,10 @@ namespace ts {
|
||||
},
|
||||
{
|
||||
name: "jsx",
|
||||
type: {
|
||||
type: createMap({
|
||||
"preserve": JsxEmit.Preserve,
|
||||
"react": JsxEmit.React
|
||||
},
|
||||
}),
|
||||
paramType: Diagnostics.KIND,
|
||||
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
|
||||
},
|
||||
@@ -92,7 +92,7 @@ namespace ts {
|
||||
{
|
||||
name: "module",
|
||||
shortName: "m",
|
||||
type: {
|
||||
type: createMap({
|
||||
"none": ModuleKind.None,
|
||||
"commonjs": ModuleKind.CommonJS,
|
||||
"amd": ModuleKind.AMD,
|
||||
@@ -100,16 +100,16 @@ namespace ts {
|
||||
"umd": ModuleKind.UMD,
|
||||
"es6": ModuleKind.ES6,
|
||||
"es2015": ModuleKind.ES2015,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
|
||||
paramType: Diagnostics.KIND,
|
||||
},
|
||||
{
|
||||
name: "newLine",
|
||||
type: {
|
||||
type: createMap({
|
||||
"crlf": NewLineKind.CarriageReturnLineFeed,
|
||||
"lf": NewLineKind.LineFeed
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix,
|
||||
paramType: Diagnostics.NEWLINE,
|
||||
},
|
||||
@@ -127,6 +127,10 @@ namespace ts {
|
||||
type: "boolean",
|
||||
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
|
||||
},
|
||||
{
|
||||
name: "noErrorTruncation",
|
||||
type: "boolean"
|
||||
},
|
||||
{
|
||||
name: "noImplicitAny",
|
||||
type: "boolean",
|
||||
@@ -251,12 +255,12 @@ namespace ts {
|
||||
{
|
||||
name: "target",
|
||||
shortName: "t",
|
||||
type: {
|
||||
type: createMap({
|
||||
"es3": ScriptTarget.ES3,
|
||||
"es5": ScriptTarget.ES5,
|
||||
"es6": ScriptTarget.ES6,
|
||||
"es2015": ScriptTarget.ES2015,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015,
|
||||
paramType: Diagnostics.VERSION,
|
||||
},
|
||||
@@ -285,10 +289,10 @@ namespace ts {
|
||||
},
|
||||
{
|
||||
name: "moduleResolution",
|
||||
type: {
|
||||
type: createMap({
|
||||
"node": ModuleResolutionKind.NodeJs,
|
||||
"classic": ModuleResolutionKind.Classic,
|
||||
},
|
||||
}),
|
||||
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
|
||||
},
|
||||
{
|
||||
@@ -393,7 +397,7 @@ namespace ts {
|
||||
type: "list",
|
||||
element: {
|
||||
name: "lib",
|
||||
type: {
|
||||
type: createMap({
|
||||
// JavaScript only
|
||||
"es5": "lib.es5.d.ts",
|
||||
"es6": "lib.es2015.d.ts",
|
||||
@@ -418,7 +422,7 @@ namespace ts {
|
||||
"es2016.array.include": "lib.es2016.array.include.d.ts",
|
||||
"es2017.object": "lib.es2017.object.d.ts",
|
||||
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts"
|
||||
},
|
||||
}),
|
||||
},
|
||||
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
|
||||
},
|
||||
@@ -468,6 +472,14 @@ namespace ts {
|
||||
shortOptionNames: Map<string>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
};
|
||||
|
||||
let optionNameMapCache: OptionNameMap;
|
||||
|
||||
/* @internal */
|
||||
@@ -476,8 +488,8 @@ namespace ts {
|
||||
return optionNameMapCache;
|
||||
}
|
||||
|
||||
const optionNameMap: Map<CommandLineOption> = {};
|
||||
const shortOptionNames: Map<string> = {};
|
||||
const optionNameMap = createMap<CommandLineOption>();
|
||||
const shortOptionNames = createMap<string>();
|
||||
forEach(optionDeclarations, option => {
|
||||
optionNameMap[option.name.toLowerCase()] = option;
|
||||
if (option.shortName) {
|
||||
@@ -492,10 +504,9 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
|
||||
const namesOfType: string[] = [];
|
||||
forEachKey(opt.type, key => {
|
||||
for (const key in opt.type) {
|
||||
namesOfType.push(` '${key}'`);
|
||||
});
|
||||
|
||||
}
|
||||
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
|
||||
}
|
||||
|
||||
@@ -503,7 +514,7 @@ namespace ts {
|
||||
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
const key = trimString((value || "")).toLowerCase();
|
||||
const map = opt.type;
|
||||
if (hasProperty(map, key)) {
|
||||
if (key in map) {
|
||||
return map[key];
|
||||
}
|
||||
else {
|
||||
@@ -557,11 +568,11 @@ namespace ts {
|
||||
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
|
||||
// Try to translate short option names to their full equivalents.
|
||||
if (hasProperty(shortOptionNames, s)) {
|
||||
if (s in shortOptionNames) {
|
||||
s = shortOptionNames[s];
|
||||
}
|
||||
|
||||
if (hasProperty(optionNameMap, s)) {
|
||||
if (s in optionNameMap) {
|
||||
const opt = optionNameMap[s];
|
||||
|
||||
if (opt.isTSConfigOnly) {
|
||||
@@ -674,6 +685,94 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate tsconfig configuration when running command line "--init"
|
||||
* @param options commandlineOptions to be generated into tsconfig.json
|
||||
* @param fileNames array of filenames to be generated into tsconfig.json
|
||||
*/
|
||||
/* @internal */
|
||||
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map<CompilerOptionsValue> } {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: any = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions)
|
||||
};
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
|
||||
return configurations;
|
||||
|
||||
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
|
||||
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
|
||||
// this is of a type CommandLineOptionOfPrimitiveType
|
||||
return undefined;
|
||||
}
|
||||
else if (optionDefinition.type === "list") {
|
||||
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
|
||||
}
|
||||
else {
|
||||
return (<CommandLineOptionOfCustomType>optionDefinition).type;
|
||||
}
|
||||
}
|
||||
|
||||
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike<string | number>): string | undefined {
|
||||
// There is a typeMap associated with this command-line option so use it to map value back to its name
|
||||
for (const key in customTypeMap) {
|
||||
if (customTypeMap[key] === value) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
|
||||
const result = createMap<CompilerOptionsValue>();
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
if (hasProperty(options, name)) {
|
||||
// tsconfig only options cannot be specified via command line,
|
||||
// so we can assume that only types that can appear here string | number | boolean
|
||||
switch (name) {
|
||||
case "init":
|
||||
case "watch":
|
||||
case "version":
|
||||
case "help":
|
||||
case "project":
|
||||
break;
|
||||
default:
|
||||
const value = options[name];
|
||||
let optionDefinition = optionsNameMap[name.toLowerCase()];
|
||||
if (optionDefinition) {
|
||||
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
|
||||
if (!customTypeMap) {
|
||||
// There is no map associated with this compiler option then use the value as-is
|
||||
// This is the case if the value is expect to be string, number, boolean or list of string
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
if (optionDefinition.type === "list") {
|
||||
const convertedValue: string[] = [];
|
||||
for (const element of value as (string | number)[]) {
|
||||
convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap));
|
||||
}
|
||||
result[name] = convertedValue;
|
||||
}
|
||||
else {
|
||||
// There is a typeMap associated with this command-line option so use it to map value back to its name
|
||||
result[name] = getNameOfCompilerOptionValue(value, customTypeMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the comments from a json like text.
|
||||
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
|
||||
@@ -817,7 +916,7 @@ namespace ts {
|
||||
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
|
||||
|
||||
for (const id in jsonOptions) {
|
||||
if (hasProperty(optionNameMap, id)) {
|
||||
if (id in optionNameMap) {
|
||||
const opt = optionNameMap[id];
|
||||
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
|
||||
}
|
||||
@@ -854,7 +953,7 @@ namespace ts {
|
||||
|
||||
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
const key = value.toLowerCase();
|
||||
if (hasProperty(opt.type, key)) {
|
||||
if (key in opt.type) {
|
||||
return opt.type[key];
|
||||
}
|
||||
else {
|
||||
@@ -964,12 +1063,12 @@ namespace ts {
|
||||
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
|
||||
// file map with a possibly case insensitive key. We use this map later when when including
|
||||
// wildcard paths.
|
||||
const literalFileMap: Map<string> = {};
|
||||
const literalFileMap = createMap<string>();
|
||||
|
||||
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
|
||||
// file map with a possibly case insensitive key. We use this map to store paths matched
|
||||
// via wildcard, and to handle extension priority.
|
||||
const wildcardFileMap: Map<string> = {};
|
||||
const wildcardFileMap = createMap<string>();
|
||||
|
||||
if (include) {
|
||||
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
|
||||
@@ -1017,7 +1116,7 @@ namespace ts {
|
||||
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
|
||||
|
||||
const key = keyMapper(file);
|
||||
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
|
||||
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
|
||||
wildcardFileMap[key] = file;
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1168,7 @@ namespace ts {
|
||||
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
|
||||
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
|
||||
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
|
||||
const wildcardDirectories: Map<WatchDirectoryFlags> = {};
|
||||
const wildcardDirectories = createMap<WatchDirectoryFlags>();
|
||||
if (include !== undefined) {
|
||||
const recursiveKeys: string[] = [];
|
||||
for (const file of include) {
|
||||
@@ -1082,7 +1181,7 @@ namespace ts {
|
||||
if (match) {
|
||||
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
|
||||
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
|
||||
const existingFlags = getProperty(wildcardDirectories, key);
|
||||
const existingFlags = wildcardDirectories[key];
|
||||
if (existingFlags === undefined || existingFlags < flags) {
|
||||
wildcardDirectories[key] = flags;
|
||||
if (flags === WatchDirectoryFlags.Recursive) {
|
||||
@@ -1094,11 +1193,9 @@ namespace ts {
|
||||
|
||||
// Remove any subpaths under an existing recursively watched directory.
|
||||
for (const key in wildcardDirectories) {
|
||||
if (hasProperty(wildcardDirectories, key)) {
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
}
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1121,7 +1218,7 @@ namespace ts {
|
||||
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
|
||||
const higherPriorityExtension = extensions[i];
|
||||
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
|
||||
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
|
||||
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-13
@@ -53,9 +53,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
let commentStart: number;
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
performance.mark("preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement;
|
||||
@@ -88,7 +87,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
performance.measure("commentTime", "preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
@@ -99,7 +98,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
performance.mark("beginEmitNodeWithComment");
|
||||
}
|
||||
|
||||
// Restore previous container state.
|
||||
@@ -114,16 +113,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
performance.measure("commentTime", "beginEmitNodeWithComment");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
|
||||
let commentStart: number;
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
performance.mark("preEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
const { pos, end } = detachedRange;
|
||||
@@ -136,7 +134,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
performance.measure("commentTime", "preEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
if (emitFlags & NodeEmitFlags.NoNestedComments) {
|
||||
@@ -147,7 +145,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
performance.mark("beginEmitBodyWithDetachedCommetns");
|
||||
}
|
||||
|
||||
if (!skipTrailingComments) {
|
||||
@@ -155,7 +153,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
performance.measure("commentTime", "beginEmitBodyWithDetachedCommetns");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,15 +225,14 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
let commentStart: number;
|
||||
if (extendedDiagnostics) {
|
||||
commentStart = performance.mark();
|
||||
performance.mark("beforeEmitTrailingCommentsOfPosition");
|
||||
}
|
||||
|
||||
forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", commentStart);
|
||||
performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+246
-99
@@ -19,8 +19,28 @@ namespace ts {
|
||||
True = -1
|
||||
}
|
||||
|
||||
const createObject = Object.create;
|
||||
|
||||
export function createMap<T>(template?: MapLike<T>): Map<T> {
|
||||
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
|
||||
|
||||
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
|
||||
// This disables creation of hidden classes, which are expensive when an object is
|
||||
// constantly changing shape.
|
||||
map["__"] = undefined;
|
||||
delete map["__"];
|
||||
|
||||
// Copies keys/values from template. Note that for..in will not throw if
|
||||
// template is undefined, and instead will just exit the loop.
|
||||
for (const key in template) if (hasOwnProperty.call(template, key)) {
|
||||
map[key] = template[key];
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
|
||||
let files: Map<T> = {};
|
||||
let files = createMap<T>();
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
@@ -46,7 +66,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function contains(path: Path) {
|
||||
return hasProperty(files, toKey(path));
|
||||
return toKey(path) in files;
|
||||
}
|
||||
|
||||
function remove(path: Path) {
|
||||
@@ -55,7 +75,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function clear() {
|
||||
files = {};
|
||||
files = createMap<T>();
|
||||
}
|
||||
|
||||
function toKey(path: Path): string {
|
||||
@@ -81,7 +101,7 @@ namespace ts {
|
||||
* returns a truthy value, then returns that value.
|
||||
* If no such value is found, the callback is applied to each element of array and undefined is returned.
|
||||
*/
|
||||
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
|
||||
export function forEach<T, U>(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
|
||||
if (array) {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const result = callback(array[i], i);
|
||||
@@ -110,6 +130,31 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */
|
||||
export function find<T>(array: T[], predicate: (element: T, index: number) => boolean): T | undefined {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const value = array[i];
|
||||
if (predicate(value, i)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first truthy result of `callback`, or else fails.
|
||||
* This is like `forEach`, but never returns undefined.
|
||||
*/
|
||||
export function findMap<T, U>(array: T[], callback: (element: T, index: number) => U | undefined): U {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Debug.fail();
|
||||
}
|
||||
|
||||
export function contains<T>(array: T[], value: T): boolean {
|
||||
if (array) {
|
||||
for (const v of array) {
|
||||
@@ -154,20 +199,42 @@ namespace ts {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function filter<T, U extends T>(array: T[], f: (x: T, i: number) => x is U): U[];
|
||||
export function filter<T>(array: T[], f: (x: T, i: number) => boolean): T[];
|
||||
export function filter<T>(array: T[], f: (x: T, i: number) => boolean): T[] {
|
||||
let result: T[];
|
||||
export function filter<T, U extends T>(array: T[], f: (x: T) => x is U): U[];
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[]
|
||||
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
if (f(v, i)) {
|
||||
result.push(v);
|
||||
const len = array.length;
|
||||
let i = 0;
|
||||
while (i < len && f(array[i])) i++;
|
||||
if (i < len) {
|
||||
const result = array.slice(0, i);
|
||||
i++;
|
||||
while (i < len) {
|
||||
const item = array[i];
|
||||
if (f(item)) {
|
||||
result.push(item);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return array;
|
||||
}
|
||||
|
||||
export function removeWhere<T>(array: T[], f: (x: T) => boolean): boolean {
|
||||
let outIndex = 0;
|
||||
for (const item of array) {
|
||||
if (!f(item)) {
|
||||
array[outIndex] = item;
|
||||
outIndex++;
|
||||
}
|
||||
}
|
||||
if (outIndex !== array.length) {
|
||||
array.length = outIndex;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function filterMutate<T>(array: T[], f: (x: T) => boolean): void {
|
||||
@@ -487,82 +554,142 @@ namespace ts {
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||||
/**
|
||||
* Indicates whether a map-like contains an own property with the specified key.
|
||||
*
|
||||
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
|
||||
* the 'in' operator.
|
||||
*
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
}
|
||||
|
||||
export function getKeys<T>(map: Map<T>): string[] {
|
||||
/**
|
||||
* Gets the value of an owned property in a map-like.
|
||||
*
|
||||
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
|
||||
* an indexer.
|
||||
*
|
||||
* @param map A map-like.
|
||||
* @param key A property key.
|
||||
*/
|
||||
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
|
||||
return hasOwnProperty.call(map, key) ? map[key] : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owned, enumerable property keys of a map-like.
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* Object.keys instead as it offers better performance.
|
||||
*
|
||||
* @param map A map-like.
|
||||
*/
|
||||
export function getOwnKeys<T>(map: MapLike<T>): string[] {
|
||||
const keys: string[] = [];
|
||||
for (const key in map) {
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
export function getProperty<T>(map: Map<T>, key: string): T | undefined {
|
||||
return hasProperty(map, key) ? map[key] : undefined;
|
||||
/**
|
||||
* Enumerates the properties of a Map<T>, invoking a callback and returning the first truthy result.
|
||||
*
|
||||
* @param map A map for which properties should be enumerated.
|
||||
* @param callback A callback to invoke for each property.
|
||||
*/
|
||||
export function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U {
|
||||
let result: U;
|
||||
for (const key in map) {
|
||||
if (result = callback(map[key], key)) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getOrUpdateProperty<T>(map: Map<T>, key: string, makeValue: () => T): T {
|
||||
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
|
||||
/**
|
||||
* Returns true if a Map<T> has some matching property.
|
||||
*
|
||||
* @param map A map whose properties should be tested.
|
||||
* @param predicate An optional callback used to test each property.
|
||||
*/
|
||||
export function someProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
|
||||
for (const key in map) {
|
||||
if (!predicate || predicate(map[key], key)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isEmpty<T>(map: Map<T>) {
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Performs a shallow copy of the properties from a source Map<T> to a target MapLike<T>
|
||||
*
|
||||
* @param source A map from which properties should be copied.
|
||||
* @param target A map to which properties should be copied.
|
||||
*/
|
||||
export function copyProperties<T>(source: Map<T>, target: MapLike<T>): void {
|
||||
for (const key in source) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
|
||||
* reduceOwnProperties instead as it offers better runtime safety.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
for (const key in map) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties defined on a map-like (but not from its prototype chain).
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* reduceProperties instead as it offers better performance.
|
||||
*
|
||||
* @param map The map-like to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a shallow equality comparison of the contents of two map-likes.
|
||||
*
|
||||
* @param left A map-like whose properties should be compared.
|
||||
* @param right A map-like whose properties should be compared.
|
||||
*/
|
||||
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>, equalityComparer?: (left: T, right: T) => boolean) {
|
||||
if (left === right) return true;
|
||||
if (!left || !right) return false;
|
||||
for (const key in left) if (hasOwnProperty.call(left, key)) {
|
||||
if (!hasOwnProperty.call(right, key) === undefined) return false;
|
||||
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
|
||||
}
|
||||
for (const key in right) if (hasOwnProperty.call(right, key)) {
|
||||
if (!hasOwnProperty.call(left, key)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
const result: any = {};
|
||||
for (const id in object) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
return <T>result;
|
||||
}
|
||||
|
||||
export function extend<T1 extends Map<{}>, T2 extends Map<{}>>(first: T1 , second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in first) {
|
||||
(result as any)[id] = first[id];
|
||||
}
|
||||
for (const id in second) {
|
||||
if (!hasProperty(result, id)) {
|
||||
(result as any)[id] = second[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
|
||||
let result: U;
|
||||
for (const id in map) {
|
||||
if (result = callback(map[id])) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
|
||||
let result: U;
|
||||
for (const id in map) {
|
||||
if (result = callback(id)) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function lookUp<T>(map: Map<T>, key: string): T {
|
||||
return hasProperty(map, key) ? map[key] : undefined;
|
||||
}
|
||||
|
||||
export function copyMap<T>(source: Map<T>, target: Map<T>): void {
|
||||
for (const p in source) {
|
||||
target[p] = source[p];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a map from the elements of an array.
|
||||
*
|
||||
@@ -573,33 +700,49 @@ namespace ts {
|
||||
* the same key with the given 'makeKey' function, then the element with the higher
|
||||
* index in the array will be the one associated with the produced key.
|
||||
*/
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
|
||||
const result: Map<T> = {};
|
||||
|
||||
forEach(array, value => {
|
||||
result[makeKey(value)] = value;
|
||||
});
|
||||
|
||||
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
|
||||
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
|
||||
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map<T | U> {
|
||||
const result = createMap<T | U>();
|
||||
for (const value of array) {
|
||||
result[makeKey(value)] = makeValue ? makeValue(value) : value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
if (map) {
|
||||
for (const key in map) {
|
||||
if (hasProperty(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
export function isEmpty<T>(map: Map<T>) {
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function cloneMap<T>(map: Map<T>) {
|
||||
const clone = createMap<T>();
|
||||
copyProperties(map, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
export function clone<T>(object: T): T {
|
||||
const result: any = {};
|
||||
for (const id in object) {
|
||||
if (hasOwnProperty.call(object, id)) {
|
||||
result[id] = (<any>object)[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in second) if (hasOwnProperty.call(second, id)) {
|
||||
(result as any)[id] = (second as any)[id];
|
||||
}
|
||||
for (const id in first) if (hasOwnProperty.call(first, id)) {
|
||||
(result as any)[id] = (first as any)[id];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -630,9 +773,7 @@ namespace ts {
|
||||
export let localizedDiagnosticMessages: Map<string> = undefined;
|
||||
|
||||
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key]
|
||||
? localizedDiagnosticMessages[message.key]
|
||||
: message.message;
|
||||
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
|
||||
}
|
||||
|
||||
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
|
||||
@@ -1368,6 +1509,8 @@ namespace ts {
|
||||
* List of supported extensions in order of file resolution precedence.
|
||||
*/
|
||||
export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"];
|
||||
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
|
||||
export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"];
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
@@ -1450,8 +1593,12 @@ namespace ts {
|
||||
return path;
|
||||
}
|
||||
|
||||
export function tryRemoveExtension(path: string, extension: string): string {
|
||||
return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined;
|
||||
export function tryRemoveExtension(path: string, extension: string): string | undefined {
|
||||
return fileExtensionIs(path, extension) ? removeExtension(path, extension) : undefined;
|
||||
}
|
||||
|
||||
export function removeExtension(path: string, extension: string): string {
|
||||
return path.substring(0, path.length - extension.length);
|
||||
}
|
||||
|
||||
export function isJsxOrTsxExtension(ext: string): boolean {
|
||||
|
||||
@@ -157,9 +157,7 @@ namespace ts {
|
||||
|
||||
if (usedTypeDirectiveReferences) {
|
||||
for (const directive in usedTypeDirectiveReferences) {
|
||||
if (hasProperty(usedTypeDirectiveReferences, directive)) {
|
||||
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
|
||||
}
|
||||
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +267,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!usedTypeDirectiveReferences) {
|
||||
usedTypeDirectiveReferences = {};
|
||||
usedTypeDirectiveReferences = createMap<string>();
|
||||
}
|
||||
for (const directive of typeReferenceDirectives) {
|
||||
if (!hasProperty(usedTypeDirectiveReferences, directive)) {
|
||||
if (!(directive in usedTypeDirectiveReferences)) {
|
||||
usedTypeDirectiveReferences[directive] = directive;
|
||||
}
|
||||
}
|
||||
@@ -441,7 +439,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
|
||||
function emitEntityName(entityName: EntityNameOrEntityNameExpression) {
|
||||
const visibilityResult = resolver.isEntityNameVisible(entityName,
|
||||
// Aliases can be written asynchronously so use correct enclosing declaration
|
||||
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
|
||||
@@ -452,9 +450,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
|
||||
if (isSupportedExpressionWithTypeArguments(node)) {
|
||||
if (isEntityNameExpression(node.expression)) {
|
||||
Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
|
||||
emitEntityName(<Identifier | PropertyAccessExpression>node.expression);
|
||||
emitEntityName(node.expression);
|
||||
if (node.typeArguments) {
|
||||
write("<");
|
||||
emitCommaList(node.typeArguments, emitType);
|
||||
@@ -537,14 +535,14 @@ namespace ts {
|
||||
// do not need to keep track of created temp names.
|
||||
function getExportDefaultTempVariableName(): string {
|
||||
const baseName = "_default";
|
||||
if (!hasProperty(currentIdentifiers, baseName)) {
|
||||
if (!(baseName in currentIdentifiers)) {
|
||||
return baseName;
|
||||
}
|
||||
let count = 0;
|
||||
while (true) {
|
||||
count++;
|
||||
const name = baseName + "_" + count;
|
||||
if (!hasProperty(currentIdentifiers, name)) {
|
||||
if (!(name in currentIdentifiers)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1020,7 +1018,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) {
|
||||
if (isSupportedExpressionWithTypeArguments(node)) {
|
||||
if (isEntityNameExpression(node.expression)) {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
|
||||
}
|
||||
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
|
||||
|
||||
@@ -1947,6 +1947,14 @@
|
||||
"category": "Error",
|
||||
"code": 2690
|
||||
},
|
||||
"An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
|
||||
"category": "Error",
|
||||
"code": 2691
|
||||
},
|
||||
"'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible.": {
|
||||
"category": "Error",
|
||||
"code": 2692
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
@@ -2227,7 +2235,7 @@
|
||||
"category": "Error",
|
||||
"code": 4082
|
||||
},
|
||||
"Conflicting library definitions for '{0}' found at '{1}' and '{2}'. Copy the correct file to the 'typings' folder to resolve this conflict.": {
|
||||
"Conflicting definitions for '{0}' found at '{1}' and '{2}'. Consider installing a specific version of this library to resolve the conflict.": {
|
||||
"category": "Message",
|
||||
"code": 4090
|
||||
},
|
||||
@@ -2824,9 +2832,13 @@
|
||||
"category": "Message",
|
||||
"code": 6137
|
||||
},
|
||||
"Property '{0}' is declared but never used.": {
|
||||
"category": "Error",
|
||||
"code": 6138
|
||||
},
|
||||
"Import emit helpers from 'tslib'.": {
|
||||
"category": "Message",
|
||||
"code": 6138
|
||||
"code": 6139
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
+6
-10
@@ -182,8 +182,7 @@ const _super = (function (geti, seti) {
|
||||
let isOwnFileEmit: boolean;
|
||||
let emitSkipped = false;
|
||||
|
||||
performance.emit("beforeTransform");
|
||||
const transformStart = performance.mark();
|
||||
performance.mark("beforeTransform");
|
||||
|
||||
// Transform the source files
|
||||
const transformed = transformFiles(
|
||||
@@ -192,8 +191,7 @@ const _super = (function (geti, seti) {
|
||||
getSourceFilesToEmit(host, targetSourceFile),
|
||||
transformers);
|
||||
|
||||
performance.measure("transformTime", transformStart);
|
||||
performance.emit("afterTransform");
|
||||
performance.measure("transformTime", "beforeTransform");
|
||||
|
||||
// Extract helpers from the result
|
||||
const {
|
||||
@@ -204,8 +202,7 @@ const _super = (function (geti, seti) {
|
||||
onEmitNode
|
||||
} = transformed;
|
||||
|
||||
performance.emit("beforePrint");
|
||||
const printStart = performance.mark();
|
||||
performance.mark("beforePrint");
|
||||
|
||||
// Emit each output file
|
||||
forEachTransformedEmitFile(host, transformed.getSourceFiles(), emitFile);
|
||||
@@ -213,8 +210,7 @@ const _super = (function (geti, seti) {
|
||||
// Clean up after transformation
|
||||
transformed.dispose();
|
||||
|
||||
performance.measure("printTime", printStart);
|
||||
performance.emit("afterPrint");
|
||||
performance.measure("printTime", "beforePrint");
|
||||
|
||||
return {
|
||||
emitSkipped,
|
||||
@@ -251,7 +247,7 @@ const _super = (function (geti, seti) {
|
||||
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
|
||||
nodeIdToGeneratedName = [];
|
||||
autoGeneratedIdToGeneratedName = [];
|
||||
generatedNameSet = {};
|
||||
generatedNameSet = createMap<string>();
|
||||
isOwnFileEmit = !isBundledEmit;
|
||||
|
||||
// Emit helpers from all the files
|
||||
@@ -2609,7 +2605,7 @@ const _super = (function (geti, seti) {
|
||||
|
||||
function getTextOfNode(node: Node, includeTrivia?: boolean): string {
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return getGeneratedIdentifier(node);
|
||||
return getGeneratedIdentifier(<Identifier>node);
|
||||
}
|
||||
else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) {
|
||||
return unescapeIdentifier(node.text);
|
||||
|
||||
+58
-21
@@ -420,14 +420,16 @@ namespace ts {
|
||||
visitNode(cbNode, (<JSDocPropertyTag>node).name);
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
|
||||
case SyntaxKind.JSDocLiteralType:
|
||||
return visitNode(cbNode, (<JSDocLiteralType>node).literal);
|
||||
}
|
||||
}
|
||||
|
||||
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeParse");
|
||||
const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
|
||||
|
||||
performance.measure("Parse", start);
|
||||
performance.mark("afterParse");
|
||||
performance.measure("Parse", "beforeParse", "afterParse");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -598,7 +600,7 @@ namespace ts {
|
||||
|
||||
parseDiagnostics = [];
|
||||
parsingContext = 0;
|
||||
identifiers = {};
|
||||
identifiers = createMap<string>();
|
||||
identifierCount = 0;
|
||||
nodeCount = 0;
|
||||
|
||||
@@ -913,7 +915,7 @@ namespace ts {
|
||||
// Note: it is not actually necessary to save/restore the context flags here. That's
|
||||
// because the saving/restoring of these flags happens naturally through the recursive
|
||||
// descent nature of our parser. However, we still store this here just so we can
|
||||
// assert that that invariant holds.
|
||||
// assert that invariant holds.
|
||||
const saveContextFlags = contextFlags;
|
||||
|
||||
// If we're only looking ahead, then tell the scanner to only lookahead as well.
|
||||
@@ -1097,7 +1099,7 @@ namespace ts {
|
||||
|
||||
function internIdentifier(text: string): string {
|
||||
text = escapeIdentifier(text);
|
||||
return hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
|
||||
return identifiers[text] || (identifiers[text] = text);
|
||||
}
|
||||
|
||||
// An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
|
||||
@@ -2761,7 +2763,7 @@ namespace ts {
|
||||
// Note: for ease of implementation we treat productions '2' and '3' as the same thing.
|
||||
// (i.e. they're both BinaryExpressions with an assignment operator in it).
|
||||
|
||||
// First, do the simple check if we have a YieldExpression (production '5').
|
||||
// First, do the simple check if we have a YieldExpression (production '6').
|
||||
if (isYieldExpression()) {
|
||||
return parseYieldExpression();
|
||||
}
|
||||
@@ -3368,24 +3370,40 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ES7 unary expression and await expression
|
||||
* Parse ES7 exponential expression and await expression
|
||||
*
|
||||
* ES7 ExponentiationExpression:
|
||||
* 1) UnaryExpression[?Yield]
|
||||
* 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
|
||||
*
|
||||
* ES7 UnaryExpression:
|
||||
* 1) SimpleUnaryExpression[?yield]
|
||||
* 2) IncrementExpression[?yield] ** UnaryExpression[?yield]
|
||||
*/
|
||||
function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
|
||||
if (isAwaitExpression()) {
|
||||
return parseAwaitExpression();
|
||||
}
|
||||
|
||||
if (isIncrementExpression()) {
|
||||
/**
|
||||
* ES7 UpdateExpression:
|
||||
* 1) LeftHandSideExpression[?Yield]
|
||||
* 2) LeftHandSideExpression[?Yield][no LineTerminator here]++
|
||||
* 3) LeftHandSideExpression[?Yield][no LineTerminator here]--
|
||||
* 4) ++UnaryExpression[?Yield]
|
||||
* 5) --UnaryExpression[?Yield]
|
||||
*/
|
||||
if (isUpdateExpression()) {
|
||||
const incrementExpression = parseIncrementExpression();
|
||||
return token() === SyntaxKind.AsteriskAsteriskToken ?
|
||||
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
|
||||
incrementExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* ES7 UnaryExpression:
|
||||
* 1) UpdateExpression[?yield]
|
||||
* 2) delete UpdateExpression[?yield]
|
||||
* 3) void UpdateExpression[?yield]
|
||||
* 4) typeof UpdateExpression[?yield]
|
||||
* 5) + UpdateExpression[?yield]
|
||||
* 6) - UpdateExpression[?yield]
|
||||
* 7) ~ UpdateExpression[?yield]
|
||||
* 8) ! UpdateExpression[?yield]
|
||||
*/
|
||||
const unaryOperator = token();
|
||||
const simpleUnaryExpression = parseSimpleUnaryExpression();
|
||||
if (token() === SyntaxKind.AsteriskAsteriskToken) {
|
||||
@@ -3403,8 +3421,8 @@ namespace ts {
|
||||
/**
|
||||
* Parse ES7 simple-unary expression or higher:
|
||||
*
|
||||
* ES7 SimpleUnaryExpression:
|
||||
* 1) IncrementExpression[?yield]
|
||||
* ES7 UnaryExpression:
|
||||
* 1) UpdateExpression[?yield]
|
||||
* 2) delete UnaryExpression[?yield]
|
||||
* 3) void UnaryExpression[?yield]
|
||||
* 4) typeof UnaryExpression[?yield]
|
||||
@@ -3412,6 +3430,7 @@ namespace ts {
|
||||
* 6) - UnaryExpression[?yield]
|
||||
* 7) ~ UnaryExpression[?yield]
|
||||
* 8) ! UnaryExpression[?yield]
|
||||
* 9) [+Await] await UnaryExpression[?yield]
|
||||
*/
|
||||
function parseSimpleUnaryExpression(): UnaryExpression {
|
||||
switch (token()) {
|
||||
@@ -3431,6 +3450,10 @@ namespace ts {
|
||||
// UnaryExpression (modified):
|
||||
// < type > UnaryExpression
|
||||
return parseTypeAssertion();
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
if (isAwaitExpression()) {
|
||||
return parseAwaitExpression();
|
||||
}
|
||||
default:
|
||||
return parseIncrementExpression();
|
||||
}
|
||||
@@ -3439,14 +3462,14 @@ namespace ts {
|
||||
/**
|
||||
* Check if the current token can possibly be an ES7 increment expression.
|
||||
*
|
||||
* ES7 IncrementExpression:
|
||||
* ES7 UpdateExpression:
|
||||
* LeftHandSideExpression[?Yield]
|
||||
* LeftHandSideExpression[?Yield][no LineTerminator here]++
|
||||
* LeftHandSideExpression[?Yield][no LineTerminator here]--
|
||||
* ++LeftHandSideExpression[?Yield]
|
||||
* --LeftHandSideExpression[?Yield]
|
||||
*/
|
||||
function isIncrementExpression(): boolean {
|
||||
function isUpdateExpression(): boolean {
|
||||
// This function is called inside parseUnaryExpression to decide
|
||||
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
|
||||
switch (token()) {
|
||||
@@ -3457,6 +3480,7 @@ namespace ts {
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
return false;
|
||||
case SyntaxKind.LessThanToken:
|
||||
// If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
|
||||
@@ -5883,10 +5907,17 @@ namespace ts {
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.NullKeyword:
|
||||
case SyntaxKind.UndefinedKeyword:
|
||||
case SyntaxKind.NeverKeyword:
|
||||
return parseTokenNode<JSDocType>();
|
||||
case SyntaxKind.StringLiteral:
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
return parseJSDocLiteralType();
|
||||
}
|
||||
|
||||
// TODO (drosen): Parse string literal types in JSDoc as well.
|
||||
return parseJSDocTypeReference();
|
||||
}
|
||||
|
||||
@@ -6063,6 +6094,12 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseJSDocLiteralType(): JSDocLiteralType {
|
||||
const result = <JSDocLiteralType>createNode(SyntaxKind.JSDocLiteralType);
|
||||
result.literal = parseLiteralTypeNode();
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
|
||||
const pos = scanner.getStartPos();
|
||||
// skip the ?
|
||||
|
||||
+50
-64
@@ -6,71 +6,57 @@ namespace ts {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
/** Performance measurements for the compiler. */
|
||||
namespace ts.performance {
|
||||
/** Performance measurements for the compiler. */
|
||||
declare const onProfilerEvent: { (markName: string): void; profiler: boolean; };
|
||||
let profilerEvent: (markName: string) => void;
|
||||
let counters: Map<number>;
|
||||
|
||||
const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
|
||||
? onProfilerEvent
|
||||
: (markName: string) => { };
|
||||
|
||||
let enabled = false;
|
||||
let profilerStart = 0;
|
||||
let counts: Map<number>;
|
||||
let marks: Map<number>;
|
||||
let measures: Map<number>;
|
||||
|
||||
/**
|
||||
* Emit a performance event if ts-profiler is connected. This is primarily used
|
||||
* to generate heap snapshots.
|
||||
* Marks a performance event.
|
||||
*
|
||||
* @param eventName A name for the event.
|
||||
* @param markName The name of the mark.
|
||||
*/
|
||||
export function emit(eventName: string) {
|
||||
if (profilerEvent) {
|
||||
profilerEvent(eventName);
|
||||
export function mark(markName: string) {
|
||||
if (enabled) {
|
||||
marks[markName] = timestamp();
|
||||
counts[markName] = (counts[markName] || 0) + 1;
|
||||
profilerEvent(markName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a counter with the specified name.
|
||||
*
|
||||
* @param counterName The name of the counter.
|
||||
*/
|
||||
export function increment(counterName: string) {
|
||||
if (counters) {
|
||||
counters[counterName] = (getProperty(counters, counterName) || 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the counter with the specified name.
|
||||
*
|
||||
* @param counterName The name of the counter.
|
||||
*/
|
||||
export function getCount(counterName: string) {
|
||||
return counters && getProperty(counters, counterName) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the start of a performance measurement.
|
||||
*/
|
||||
export function mark() {
|
||||
return measures ? timestamp() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a performance measurement with the specified name.
|
||||
*
|
||||
* @param measureName The name of the performance measurement.
|
||||
* @param marker The timestamp of the starting mark.
|
||||
* @param startMarkName The name of the starting mark. If not supplied, the point at which the
|
||||
* profiler was enabled is used.
|
||||
* @param endMarkName The name of the ending mark. If not supplied, the current timestamp is
|
||||
* used.
|
||||
*/
|
||||
export function measure(measureName: string, marker: number) {
|
||||
if (measures) {
|
||||
measures[measureName] = (getProperty(measures, measureName) || 0) + (timestamp() - marker);
|
||||
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
|
||||
if (enabled) {
|
||||
const end = endMarkName && marks[endMarkName] || timestamp();
|
||||
const start = startMarkName && marks[startMarkName] || profilerStart;
|
||||
measures[measureName] = (measures[measureName] || 0) + (end - start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each measure, performing some action
|
||||
*
|
||||
* @param cb The action to perform for each measure
|
||||
* Gets the number of times a marker was encountered.
|
||||
*
|
||||
* @param markName The name of the mark.
|
||||
*/
|
||||
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
|
||||
return forEachKey(measures, key => cb(key, measures[key]));
|
||||
export function getCount(markName: string) {
|
||||
return counts && counts[markName] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,31 +65,31 @@ namespace ts.performance {
|
||||
* @param measureName The name of the measure whose durations should be accumulated.
|
||||
*/
|
||||
export function getDuration(measureName: string) {
|
||||
return measures && getProperty(measures, measureName) || 0;
|
||||
return measures && measures[measureName] || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each measure, performing some action
|
||||
*
|
||||
* @param cb The action to perform for each measure
|
||||
*/
|
||||
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
|
||||
for (const key in measures) {
|
||||
cb(key, measures[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Enables (and resets) performance measurements for the compiler. */
|
||||
export function enable() {
|
||||
counters = { };
|
||||
measures = {
|
||||
"I/O Read": 0,
|
||||
"I/O Write": 0,
|
||||
"Program": 0,
|
||||
"Parse": 0,
|
||||
"Bind": 0,
|
||||
"Check": 0,
|
||||
"Emit": 0,
|
||||
};
|
||||
|
||||
profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
|
||||
? onProfilerEvent
|
||||
: undefined;
|
||||
counts = createMap<number>();
|
||||
marks = createMap<number>();
|
||||
measures = createMap<number>();
|
||||
enabled = true;
|
||||
profilerStart = timestamp();
|
||||
}
|
||||
|
||||
/** Disables (and clears) performance measurements for the compiler. */
|
||||
/** Disables performance measurements for the compiler. */
|
||||
export function disable() {
|
||||
counters = undefined;
|
||||
measures = undefined;
|
||||
profilerEvent = undefined;
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
+113
-117
@@ -119,49 +119,31 @@ namespace ts {
|
||||
}
|
||||
|
||||
function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
|
||||
let jsonContent: { typings?: string, types?: string, main?: string };
|
||||
try {
|
||||
const jsonText = state.host.readFile(packageJsonPath);
|
||||
jsonContent = jsonText ? <{ typings?: string, types?: string, main?: string }>JSON.parse(jsonText) : {};
|
||||
}
|
||||
catch (e) {
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
jsonContent = {};
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
|
||||
function tryReadFromField(fieldName: string) {
|
||||
if (hasProperty(jsonContent, fieldName)) {
|
||||
const typesFile = (<any>jsonContent)[fieldName];
|
||||
if (typeof typesFile === "string") {
|
||||
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
|
||||
}
|
||||
return typesFilePath;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let typesFile: string;
|
||||
let fieldName: string;
|
||||
// first try to read content of 'typings' section (backward compatibility)
|
||||
if (jsonContent.typings) {
|
||||
if (typeof jsonContent.typings === "string") {
|
||||
fieldName = "typings";
|
||||
typesFile = jsonContent.typings;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings);
|
||||
}
|
||||
}
|
||||
}
|
||||
// then read 'types'
|
||||
if (!typesFile && jsonContent.types) {
|
||||
if (typeof jsonContent.types === "string") {
|
||||
fieldName = "types";
|
||||
typesFile = jsonContent.types;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typesFile) {
|
||||
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
|
||||
}
|
||||
const typesFilePath = tryReadFromField("typings") || tryReadFromField("types");
|
||||
if (typesFilePath) {
|
||||
return typesFilePath;
|
||||
}
|
||||
|
||||
// Use the main module for inferring types if no types package specified and the allowJs is set
|
||||
if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") {
|
||||
if (state.traceEnabled) {
|
||||
@@ -173,6 +155,17 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } {
|
||||
try {
|
||||
const jsonText = host.readFile(path);
|
||||
return jsonText ? JSON.parse(jsonText) : {};
|
||||
}
|
||||
catch (e) {
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const typeReferenceExtensions = [".d.ts"];
|
||||
|
||||
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
|
||||
@@ -508,7 +501,7 @@ namespace ts {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
|
||||
}
|
||||
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
|
||||
matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName);
|
||||
}
|
||||
|
||||
if (matchedPattern) {
|
||||
@@ -668,24 +661,27 @@ namespace ts {
|
||||
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
// First try to keep/add an extension: importing "./foo.ts" can be matched by a file "./foo.ts", and "./foo" by "./foo.d.ts"
|
||||
const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (resolvedByAddingOrKeepingExtension) {
|
||||
return resolvedByAddingOrKeepingExtension;
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
|
||||
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (resolvedByAddingExtension) {
|
||||
return resolvedByAddingExtension;
|
||||
}
|
||||
// Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
|
||||
// If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
|
||||
// e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
if (hasJavaScriptFileExtension(candidate)) {
|
||||
const extensionless = removeFileExtension(candidate);
|
||||
if (state.traceEnabled) {
|
||||
const extension = candidate.substring(extensionless.length);
|
||||
trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension);
|
||||
}
|
||||
return loadModuleFromFileWorker(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
}
|
||||
}
|
||||
|
||||
function loadModuleFromFileWorker(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
/** Try to return an existing file that adds one of the `extensions` to `candidate`. */
|
||||
function tryAddingExtensions(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
const directory = getDirectoryPath(candidate);
|
||||
@@ -693,31 +689,29 @@ namespace ts {
|
||||
onlyRecordFailures = !directoryProbablyExists(directory, state.host);
|
||||
}
|
||||
}
|
||||
return forEach(extensions, tryLoad);
|
||||
return forEach(extensions, ext =>
|
||||
!(state.skipTsx && isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state));
|
||||
}
|
||||
|
||||
function tryLoad(ext: string): string {
|
||||
if (state.skipTsx && isJsxOrTsxExtension(ext)) {
|
||||
return undefined;
|
||||
/** Return the file if it exists. */
|
||||
function tryFile(fileName: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures && state.host.fileExists(fileName)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName);
|
||||
}
|
||||
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
|
||||
if (!onlyRecordFailures && state.host.fileExists(fileName)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, fileName);
|
||||
}
|
||||
failedLookupLocation.push(fileName);
|
||||
return undefined;
|
||||
return fileName;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, fileName);
|
||||
}
|
||||
failedLookupLocation.push(fileName);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
const packageJsonPath = combinePaths(candidate, "package.json");
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
if (state.traceEnabled) {
|
||||
@@ -725,7 +719,10 @@ namespace ts {
|
||||
}
|
||||
const typesFile = tryReadTypesSection(packageJsonPath, candidate, state);
|
||||
if (typesFile) {
|
||||
const result = loadModuleFromFile(typesFile, extensions, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(typesFile), state.host), state);
|
||||
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
|
||||
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
|
||||
const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state) ||
|
||||
tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -747,6 +744,10 @@ namespace ts {
|
||||
return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state);
|
||||
}
|
||||
|
||||
function pathToPackageJson(directory: string): string {
|
||||
return combinePaths(directory, "package.json");
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
|
||||
const nodeModulesFolder = combinePaths(directory, "node_modules");
|
||||
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
|
||||
@@ -831,14 +832,6 @@ namespace ts {
|
||||
: { resolvedModule: undefined, failedLookupLocations };
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
};
|
||||
|
||||
interface OutputFingerprint {
|
||||
hash: string;
|
||||
byteOrderMark: boolean;
|
||||
@@ -846,7 +839,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
|
||||
const existingDirectories: Map<boolean> = {};
|
||||
const existingDirectories = createMap<boolean>();
|
||||
|
||||
function getCanonicalFileName(fileName: string): string {
|
||||
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
|
||||
@@ -860,9 +853,10 @@ namespace ts {
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeIORead");
|
||||
text = sys.readFile(fileName, options.charset);
|
||||
performance.measure("I/O Read", start);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@@ -877,7 +871,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function directoryExists(directoryPath: string): boolean {
|
||||
if (hasProperty(existingDirectories, directoryPath)) {
|
||||
if (directoryPath in existingDirectories) {
|
||||
return true;
|
||||
}
|
||||
if (sys.directoryExists(directoryPath)) {
|
||||
@@ -899,13 +893,13 @@ namespace ts {
|
||||
|
||||
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
|
||||
if (!outputFingerprints) {
|
||||
outputFingerprints = {};
|
||||
outputFingerprints = createMap<OutputFingerprint>();
|
||||
}
|
||||
|
||||
const hash = sys.createHash(data);
|
||||
const mtimeBefore = sys.getModifiedTime(fileName);
|
||||
|
||||
if (mtimeBefore && hasProperty(outputFingerprints, fileName)) {
|
||||
if (mtimeBefore && fileName in outputFingerprints) {
|
||||
const fingerprint = outputFingerprints[fileName];
|
||||
|
||||
// If output has not been changed, and the file has no external modification
|
||||
@@ -929,7 +923,7 @@ namespace ts {
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||
try {
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
|
||||
@@ -939,7 +933,8 @@ namespace ts {
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
performance.measure("I/O Write", start);
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@@ -1041,16 +1036,11 @@ namespace ts {
|
||||
return [];
|
||||
}
|
||||
const resolutions: T[] = [];
|
||||
const cache: Map<T> = {};
|
||||
const cache = createMap<T>();
|
||||
for (const name of names) {
|
||||
let result: T;
|
||||
if (hasProperty(cache, name)) {
|
||||
result = cache[name];
|
||||
}
|
||||
else {
|
||||
result = loader(name, containingFile);
|
||||
cache[name] = result;
|
||||
}
|
||||
const result = name in cache
|
||||
? cache[name]
|
||||
: cache[name] = loader(name, containingFile);
|
||||
resolutions.push(result);
|
||||
}
|
||||
return resolutions;
|
||||
@@ -1071,15 +1061,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Walk the primary type lookup locations
|
||||
let result: string[] = [];
|
||||
const result: string[] = [];
|
||||
if (host.directoryExists && host.getDirectories) {
|
||||
const typeRoots = getEffectiveTypeRoots(options, host);
|
||||
if (typeRoots) {
|
||||
for (const root of typeRoots) {
|
||||
if (host.directoryExists(root)) {
|
||||
for (const typeDirectivePath of host.getDirectories(root)) {
|
||||
// Return just the type directive names
|
||||
result = result.concat(getBaseFileName(normalizePath(typeDirectivePath)));
|
||||
const normalized = normalizePath(typeDirectivePath);
|
||||
const packageJsonPath = pathToPackageJson(combinePaths(root, normalized));
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null;
|
||||
if (!isNotNeededPackage) {
|
||||
// Return just the type directive names
|
||||
result.push(getBaseFileName(normalized));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1096,7 +1092,7 @@ namespace ts {
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {};
|
||||
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
|
||||
@@ -1111,12 +1107,12 @@ namespace ts {
|
||||
|
||||
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
|
||||
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
|
||||
const modulesWithElidedImports: Map<boolean> = {};
|
||||
const modulesWithElidedImports = createMap<boolean>();
|
||||
|
||||
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
|
||||
const sourceFilesFoundSearchingNodeModules: Map<boolean> = {};
|
||||
const sourceFilesFoundSearchingNodeModules = createMap<boolean>();
|
||||
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
host = host || createCompilerHost(options);
|
||||
|
||||
@@ -1214,8 +1210,8 @@ namespace ts {
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
|
||||
performance.measure("Program", start);
|
||||
performance.mark("afterProgram");
|
||||
performance.measure("Program", "beforeProgram", "afterProgram");
|
||||
|
||||
return program;
|
||||
|
||||
@@ -1242,10 +1238,10 @@ namespace ts {
|
||||
if (!classifiableNames) {
|
||||
// Initialize a checker so that all our files are bound.
|
||||
getTypeChecker();
|
||||
classifiableNames = {};
|
||||
classifiableNames = createMap<string>();
|
||||
|
||||
for (const sourceFile of files) {
|
||||
copyMap(sourceFile.classifiableNames, classifiableNames);
|
||||
copyProperties(sourceFile.classifiableNames, classifiableNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1273,7 +1269,7 @@ namespace ts {
|
||||
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
|
||||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
|
||||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
|
||||
!mapIsEqualTo(oldOptions.paths, options.paths)) {
|
||||
!equalOwnProperties(oldOptions.paths, options.paths)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1395,7 +1391,7 @@ namespace ts {
|
||||
getSourceFile: program.getSourceFile,
|
||||
getSourceFileByPath: program.getSourceFileByPath,
|
||||
getSourceFiles: program.getSourceFiles,
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path),
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
|
||||
writeFile: writeFileCallback || (
|
||||
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
|
||||
isEmitBlocked,
|
||||
@@ -1458,17 +1454,15 @@ namespace ts {
|
||||
// checked is to not pass the file to getEmitResolver.
|
||||
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
|
||||
|
||||
performance.emit("beforeEmit");
|
||||
const start = performance.mark();
|
||||
performance.mark("beforeEmit");
|
||||
|
||||
const emitResult = emitFiles(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
|
||||
performance.measure("Emit", start);
|
||||
performance.emit("afterEmit");
|
||||
|
||||
performance.mark("afterEmit");
|
||||
performance.measure("Emit", "beforeEmit", "afterEmit");
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
@@ -1946,7 +1940,7 @@ namespace ts {
|
||||
|
||||
// If the file was previously found via a node_modules search, but is now being processed as a root file,
|
||||
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
|
||||
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
|
||||
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
|
||||
sourceFilesFoundSearchingNodeModules[file.path] = false;
|
||||
if (!options.noResolve) {
|
||||
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
|
||||
@@ -1957,7 +1951,7 @@ namespace ts {
|
||||
processImportedModules(file, getDirectoryPath(fileName));
|
||||
}
|
||||
// See if we need to reprocess the imports due to prior skipped imports
|
||||
else if (file && lookUp(modulesWithElidedImports, file.path)) {
|
||||
else if (file && modulesWithElidedImports[file.path]) {
|
||||
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
|
||||
modulesWithElidedImports[file.path] = false;
|
||||
processImportedModules(file, getDirectoryPath(fileName));
|
||||
@@ -2024,15 +2018,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function processTypeReferenceDirectives(file: SourceFile) {
|
||||
const typeDirectives = map(file.typeReferenceDirectives, l => l.fileName);
|
||||
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
|
||||
const typeDirectives = map(file.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase());
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
|
||||
|
||||
for (let i = 0; i < typeDirectives.length; i++) {
|
||||
const ref = file.typeReferenceDirectives[i];
|
||||
const resolvedTypeReferenceDirective = resolutions[i];
|
||||
// store resolved type directive on the file
|
||||
setResolvedTypeReferenceDirective(file, ref.fileName, resolvedTypeReferenceDirective);
|
||||
processTypeReferenceDirective(ref.fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
|
||||
const fileName = ref.fileName.toLocaleLowerCase();
|
||||
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective);
|
||||
processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2057,7 +2053,7 @@ namespace ts {
|
||||
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
|
||||
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
|
||||
Diagnostics.Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_the_typings_folder_to_resolve_this_conflict,
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
@@ -2097,7 +2093,7 @@ namespace ts {
|
||||
function processImportedModules(file: SourceFile, basePath: string) {
|
||||
collectExternalModuleReferences(file);
|
||||
if (file.imports.length || file.moduleAugmentations.length) {
|
||||
file.resolvedModules = {};
|
||||
file.resolvedModules = createMap<ResolvedModule>();
|
||||
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
|
||||
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
|
||||
for (let i = 0; i < moduleNames.length; i++) {
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace ts {
|
||||
tryScan<T>(callback: () => T): T;
|
||||
}
|
||||
|
||||
const textToToken: Map<SyntaxKind> = {
|
||||
const textToToken = createMap({
|
||||
"abstract": SyntaxKind.AbstractKeyword,
|
||||
"any": SyntaxKind.AnyKeyword,
|
||||
"as": SyntaxKind.AsKeyword,
|
||||
@@ -179,7 +179,7 @@ namespace ts {
|
||||
"|=": SyntaxKind.BarEqualsToken,
|
||||
"^=": SyntaxKind.CaretEqualsToken,
|
||||
"@": SyntaxKind.AtToken,
|
||||
};
|
||||
});
|
||||
|
||||
/*
|
||||
As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
|
||||
@@ -274,9 +274,7 @@ namespace ts {
|
||||
function makeReverseMap(source: Map<number>): string[] {
|
||||
const result: string[] = [];
|
||||
for (const name in source) {
|
||||
if (source.hasOwnProperty(name)) {
|
||||
result[source[name]] = name;
|
||||
}
|
||||
result[source[name]] = name;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+18
-12
@@ -219,6 +219,7 @@ namespace ts {
|
||||
|
||||
function createSourceMapWriterWorker(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentSourceText: string;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
@@ -462,7 +463,9 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
const start = performance.mark();
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("beforeSourcemap");
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
@@ -504,7 +507,10 @@ namespace ts {
|
||||
|
||||
updateLastEncodedAndRecordedSpans();
|
||||
|
||||
performance.measure("Source Map", start);
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("afterSourcemap");
|
||||
performance.measure("Source Map", "beforeSourcemap", "afterSourcemap");
|
||||
}
|
||||
}
|
||||
|
||||
function getStartPosPastDecorators(range: TextRange) {
|
||||
@@ -782,30 +788,30 @@ namespace ts {
|
||||
getSourceMapData,
|
||||
setSourceFile,
|
||||
emitPos(pos: number): void {
|
||||
const sourcemapStart = performance.mark();
|
||||
performance.mark("sourcemapStart");
|
||||
emitPos(pos);
|
||||
performance.measure("sourceMapTime", sourcemapStart);
|
||||
performance.measure("sourceMapTime", "sourcemapStart");
|
||||
},
|
||||
emitStart(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void {
|
||||
const sourcemapStart = performance.mark();
|
||||
performance.mark("emitSourcemap:emitStart");
|
||||
emitStart(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback);
|
||||
performance.measure("sourceMapTime", sourcemapStart);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitStart");
|
||||
},
|
||||
emitEnd(range: TextRange, contextNode?: Node, ignoreNodeCallback?: (node: Node) => boolean, ignoreChildrenCallback?: (node: Node) => boolean, getTextRangeCallback?: (node: Node) => TextRange): void {
|
||||
const sourcemapStart = performance.mark();
|
||||
performance.mark("emitSourcemap:emitEnd");
|
||||
emitEnd(range, contextNode, ignoreNodeCallback, ignoreChildrenCallback, getTextRangeCallback);
|
||||
performance.measure("sourceMapTime", sourcemapStart);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitEnd");
|
||||
},
|
||||
emitTokenStart(token: SyntaxKind, tokenStartPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
const sourcemapStart = performance.mark();
|
||||
performance.mark("emitSourcemap:emitTokenStart");
|
||||
tokenStartPos = emitTokenStart(token, tokenStartPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback);
|
||||
performance.measure("sourceMapTime", sourcemapStart);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitTokenStart");
|
||||
return tokenStartPos;
|
||||
},
|
||||
emitTokenEnd(token: SyntaxKind, tokenEndPos: number, contextNode?: Node, ignoreTokenCallback?: (node: Node) => boolean, getTokenTextRangeCallback?: (node: Node, token: SyntaxKind) => TextRange): number {
|
||||
const sourcemapStart = performance.mark();
|
||||
performance.mark("emitSourcemap:emitTokenEnd");
|
||||
tokenEndPos = emitTokenEnd(token, tokenEndPos, contextNode, ignoreTokenCallback, getTokenTextRangeCallback);
|
||||
performance.measure("sourceMapTime", sourcemapStart);
|
||||
performance.measure("sourceMapTime", "emitSourcemap:emitTokenEnd");
|
||||
return tokenEndPos;
|
||||
},
|
||||
changeEmitSourcePos,
|
||||
|
||||
+13
-18
@@ -239,15 +239,15 @@ namespace ts {
|
||||
const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"];
|
||||
|
||||
function createWatchedFileSet() {
|
||||
const dirWatchers: Map<DirectoryWatcher> = {};
|
||||
const dirWatchers = createMap<DirectoryWatcher>();
|
||||
// One file can have multiple watchers
|
||||
const fileWatcherCallbacks: Map<FileWatcherCallback[]> = {};
|
||||
const fileWatcherCallbacks = createMap<FileWatcherCallback[]>();
|
||||
return { addFile, removeFile };
|
||||
|
||||
function reduceDirWatcherRefCountForFile(fileName: string) {
|
||||
const dirName = getDirectoryPath(fileName);
|
||||
if (hasProperty(dirWatchers, dirName)) {
|
||||
const watcher = dirWatchers[dirName];
|
||||
const watcher = dirWatchers[dirName];
|
||||
if (watcher) {
|
||||
watcher.referenceCount -= 1;
|
||||
if (watcher.referenceCount <= 0) {
|
||||
watcher.close();
|
||||
@@ -257,13 +257,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addDirWatcher(dirPath: string): void {
|
||||
if (hasProperty(dirWatchers, dirPath)) {
|
||||
const watcher = dirWatchers[dirPath];
|
||||
let watcher = dirWatchers[dirPath];
|
||||
if (watcher) {
|
||||
watcher.referenceCount += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const watcher: DirectoryWatcher = _fs.watch(
|
||||
watcher = _fs.watch(
|
||||
dirPath,
|
||||
{ persistent: true },
|
||||
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
|
||||
@@ -274,12 +273,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
|
||||
if (hasProperty(fileWatcherCallbacks, filePath)) {
|
||||
fileWatcherCallbacks[filePath].push(callback);
|
||||
}
|
||||
else {
|
||||
fileWatcherCallbacks[filePath] = [callback];
|
||||
}
|
||||
(fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback);
|
||||
}
|
||||
|
||||
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
|
||||
@@ -295,8 +289,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
|
||||
if (hasProperty(fileWatcherCallbacks, filePath)) {
|
||||
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks[filePath]);
|
||||
const callbacks = fileWatcherCallbacks[filePath];
|
||||
if (callbacks) {
|
||||
const newCallbacks = copyListRemovingItem(callback, callbacks);
|
||||
if (newCallbacks.length === 0) {
|
||||
delete fileWatcherCallbacks[filePath];
|
||||
}
|
||||
@@ -312,7 +307,7 @@ namespace ts {
|
||||
? undefined
|
||||
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
|
||||
// Some applications save a working file via rename operations
|
||||
if ((eventName === "change" || eventName === "rename") && hasProperty(fileWatcherCallbacks, fileName)) {
|
||||
if ((eventName === "change" || eventName === "rename") && fileWatcherCallbacks[fileName]) {
|
||||
for (const fileCallback of fileWatcherCallbacks[fileName]) {
|
||||
fileCallback(fileName);
|
||||
}
|
||||
@@ -443,7 +438,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDirectories(path: string): string[] {
|
||||
return filter<string>(_fs.readdirSync(path), p => fileSystemEntryExists(combinePaths(path, p), FileSystemEntryKind.Directory));
|
||||
return filter<string>(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory));
|
||||
}
|
||||
|
||||
const nodeSystem: System = {
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
const moduleTransformerMap: Map<Transformer> = {
|
||||
const moduleTransformerMap = createMap<Transformer>({
|
||||
[ModuleKind.ES6]: transformES6Module,
|
||||
[ModuleKind.System]: transformSystemModule,
|
||||
[ModuleKind.AMD]: transformModule,
|
||||
[ModuleKind.CommonJS]: transformModule,
|
||||
[ModuleKind.UMD]: transformModule,
|
||||
[ModuleKind.None]: transformModule,
|
||||
};
|
||||
});
|
||||
|
||||
const enum SyntaxKindFeatureFlags {
|
||||
Substitution = 1 << 0,
|
||||
@@ -206,7 +206,7 @@ namespace ts {
|
||||
const transformId = nextTransformId;
|
||||
nextTransformId++;
|
||||
|
||||
const tokenSourceMapRanges: Map<TextRange> = { };
|
||||
const tokenSourceMapRanges = createMap<TextRange>();
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
|
||||
@@ -1663,7 +1663,7 @@ namespace ts {
|
||||
function visitLabeledStatement(node: LabeledStatement): VisitResult<Statement> {
|
||||
if (convertedLoopState) {
|
||||
if (!convertedLoopState.labels) {
|
||||
convertedLoopState.labels = {};
|
||||
convertedLoopState.labels = createMap<string>();
|
||||
}
|
||||
convertedLoopState.labels[node.label.text] = node.label.text;
|
||||
}
|
||||
@@ -1815,7 +1815,9 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
else {
|
||||
assignment.end = initializer.end;
|
||||
// Currently there is not way to check that assignment is binary expression of destructing assignment
|
||||
// so we have to cast never type to binaryExpression
|
||||
(<BinaryExpression>assignment).end = initializer.end;
|
||||
statements.push(createStatement(assignment, /*location*/ moveRangeEnd(initializer, -1)));
|
||||
}
|
||||
}
|
||||
@@ -2249,13 +2251,13 @@ namespace ts {
|
||||
function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void {
|
||||
if (isBreak) {
|
||||
if (!state.labeledNonLocalBreaks) {
|
||||
state.labeledNonLocalBreaks = {};
|
||||
state.labeledNonLocalBreaks = createMap<string>();
|
||||
}
|
||||
state.labeledNonLocalBreaks[labelText] = labelMarker;
|
||||
}
|
||||
else {
|
||||
if (!state.labeledNonLocalContinues) {
|
||||
state.labeledNonLocalContinues = {};
|
||||
state.labeledNonLocalContinues = createMap<string>();
|
||||
}
|
||||
state.labeledNonLocalContinues[labelText] = labelMarker;
|
||||
}
|
||||
|
||||
@@ -216,13 +216,13 @@ namespace ts {
|
||||
Endfinally = 7,
|
||||
}
|
||||
|
||||
const instructionNames: Map<string> = {
|
||||
const instructionNames = createMap<string>({
|
||||
[Instruction.Return]: "return",
|
||||
[Instruction.Break]: "break",
|
||||
[Instruction.Yield]: "yield",
|
||||
[Instruction.YieldStar]: "yield*",
|
||||
[Instruction.Endfinally]: "endfinally",
|
||||
};
|
||||
});
|
||||
|
||||
export function transformGenerators(context: TransformationContext) {
|
||||
const {
|
||||
@@ -1912,7 +1912,7 @@ namespace ts {
|
||||
function cacheExpression(node: Expression): Identifier {
|
||||
let temp: Identifier;
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return node;
|
||||
return <Identifier>node;
|
||||
}
|
||||
|
||||
temp = createTempVariable(hoistVariableDeclaration);
|
||||
@@ -2060,8 +2060,8 @@ namespace ts {
|
||||
const name = declareLocal(text);
|
||||
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = {};
|
||||
renamedCatchVariableDeclarations = {};
|
||||
renamedCatchVariables = createMap<boolean>();
|
||||
renamedCatchVariableDeclarations = createMap<Identifier>();
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createEntitiesMap(): Map<number> {
|
||||
return {
|
||||
return createMap<number>({
|
||||
"quot": 0x0022,
|
||||
"amp": 0x0026,
|
||||
"apos": 0x0027,
|
||||
@@ -513,6 +513,6 @@ namespace ts {
|
||||
"clubs": 0x2663,
|
||||
"hearts": 0x2665,
|
||||
"diams": 0x2666
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,12 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function transformModule(context: TransformationContext) {
|
||||
const transformModuleDelegates: Map<(node: SourceFile) => SourceFile> = {
|
||||
const transformModuleDelegates = createMap<(node: SourceFile) => SourceFile>({
|
||||
[ModuleKind.None]: transformCommonJSModule,
|
||||
[ModuleKind.CommonJS]: transformCommonJSModule,
|
||||
[ModuleKind.AMD]: transformAMDModule,
|
||||
[ModuleKind.UMD]: transformUMDModule,
|
||||
};
|
||||
});
|
||||
|
||||
const {
|
||||
startLexicalEnvironment,
|
||||
@@ -43,7 +43,7 @@ namespace ts {
|
||||
let bindingNameExportSpecifiersMap: Map<ExportSpecifier[]>;
|
||||
// Subset of exportSpecifiers that is a binding-name.
|
||||
// This is to reduce amount of memory we have to keep around even after we done with module-transformer
|
||||
const bindingNameExportSpecifiersForFileMap: Map<Map<ExportSpecifier[]>> = {};
|
||||
const bindingNameExportSpecifiersForFileMap = createMap<Map<ExportSpecifier[]>>();
|
||||
let hasExportStarsToExportValues: boolean;
|
||||
|
||||
return transformSourceFile;
|
||||
@@ -667,7 +667,7 @@ namespace ts {
|
||||
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
|
||||
const sourceFileId = getOriginalNodeId(currentSourceFile);
|
||||
if (!bindingNameExportSpecifiersForFileMap[sourceFileId]) {
|
||||
bindingNameExportSpecifiersForFileMap[sourceFileId] = {};
|
||||
bindingNameExportSpecifiersForFileMap[sourceFileId] = createMap<ExportSpecifier[]>();
|
||||
}
|
||||
bindingNameExportSpecifiersForFileMap[sourceFileId][name.text] = exportSpecifiers[name.text];
|
||||
addExportMemberAssignments(resultStatements, name);
|
||||
|
||||
@@ -1324,7 +1324,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function collectDependencyGroups(externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]) {
|
||||
const groupIndices: Map<number> = {};
|
||||
const groupIndices = createMap<number>();
|
||||
const dependencyGroups: DependencyGroup[] = [];
|
||||
for (let i = 0; i < externalImports.length; i++) {
|
||||
const externalImport = externalImports[i];
|
||||
|
||||
@@ -3152,7 +3152,7 @@ namespace ts {
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
|
||||
// Keep track of class aliases.
|
||||
classAliases = {};
|
||||
classAliases = createMap<Identifier>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-68
@@ -127,11 +127,11 @@ namespace ts {
|
||||
const gutterSeparator = " ";
|
||||
const resetEscapeSequence = "\u001b[0m";
|
||||
const ellipsis = "...";
|
||||
const categoryFormatMap: Map<string> = {
|
||||
const categoryFormatMap = createMap<string>({
|
||||
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
|
||||
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
|
||||
};
|
||||
});
|
||||
|
||||
function formatAndReset(text: string, formatStyle: string) {
|
||||
return formatStyle + text + resetEscapeSequence;
|
||||
@@ -425,7 +425,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// reset the cache of existing files
|
||||
cachedExistingFiles = {};
|
||||
cachedExistingFiles = createMap<boolean>();
|
||||
|
||||
const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
|
||||
|
||||
@@ -438,10 +438,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function cachedFileExists(fileName: string): boolean {
|
||||
if (hasProperty(cachedExistingFiles, fileName)) {
|
||||
return cachedExistingFiles[fileName];
|
||||
}
|
||||
return cachedExistingFiles[fileName] = hostFileExists(fileName);
|
||||
return fileName in cachedExistingFiles
|
||||
? cachedExistingFiles[fileName]
|
||||
: cachedExistingFiles[fileName] = hostFileExists(fileName);
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
|
||||
@@ -704,7 +703,7 @@ namespace ts {
|
||||
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
|
||||
const descriptionColumn: string[] = [];
|
||||
|
||||
const optionsDescriptionMap: Map<string[]> = {}; // Map between option.description and list of option.type if it is a kind
|
||||
const optionsDescriptionMap = createMap<string[]>(); // Map between option.description and list of option.type if it is a kind
|
||||
|
||||
for (let i = 0; i < optsList.length; i++) {
|
||||
const option = optsList[i];
|
||||
@@ -732,9 +731,10 @@ namespace ts {
|
||||
description = getDiagnosticText(option.description);
|
||||
const options: string[] = [];
|
||||
const element = (<CommandLineOptionOfListType>option).element;
|
||||
forEachKey(<Map<number | string>>element.type, key => {
|
||||
const typeMap = <Map<number | string>>element.type;
|
||||
for (const key in typeMap) {
|
||||
options.push(`'${key}'`);
|
||||
});
|
||||
}
|
||||
optionsDescriptionMap[description] = options;
|
||||
}
|
||||
else {
|
||||
@@ -791,68 +791,11 @@ namespace ts {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
|
||||
}
|
||||
else {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: any = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions)
|
||||
};
|
||||
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
else {
|
||||
configurations.exclude = ["node_modules"];
|
||||
if (compilerOptions.outDir) {
|
||||
configurations.exclude.push(compilerOptions.outDir);
|
||||
}
|
||||
}
|
||||
|
||||
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
|
||||
sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
|
||||
const result: Map<string | number | boolean> = {};
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
if (hasProperty(options, name)) {
|
||||
// tsconfig only options cannot be specified via command line,
|
||||
// so we can assume that only types that can appear here string | number | boolean
|
||||
const value = <string | number | boolean>options[name];
|
||||
switch (name) {
|
||||
case "init":
|
||||
case "watch":
|
||||
case "version":
|
||||
case "help":
|
||||
case "project":
|
||||
break;
|
||||
default:
|
||||
let optionDefinition = optionsNameMap[name.toLowerCase()];
|
||||
if (optionDefinition) {
|
||||
if (typeof optionDefinition.type === "string") {
|
||||
// string, number or boolean
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
// Enum
|
||||
const typeMap = <Map<number>>optionDefinition.type;
|
||||
for (const key in typeMap) {
|
||||
if (hasProperty(typeMap, key)) {
|
||||
if (typeMap[key] === value)
|
||||
result[name] = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+49
-30
@@ -1,9 +1,13 @@
|
||||
|
||||
namespace ts {
|
||||
export interface Map<T> {
|
||||
|
||||
export interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
export interface Map<T> extends MapLike<T> {
|
||||
__mapBrand: any;
|
||||
}
|
||||
|
||||
// branded string type used to store absolute, normalized and canonicalized paths
|
||||
// arbitrary file name can be converted to Path via toPath function
|
||||
export type Path = string & { __pathBrand: any };
|
||||
@@ -346,6 +350,10 @@ namespace ts {
|
||||
JSDocTypedefTag,
|
||||
JSDocPropertyTag,
|
||||
JSDocTypeLiteral,
|
||||
JSDocLiteralType,
|
||||
JSDocNullKeyword,
|
||||
JSDocUndefinedKeyword,
|
||||
JSDocNeverKeyword,
|
||||
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
@@ -383,9 +391,9 @@ namespace ts {
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocTypeLiteral,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
FirstJSDocTagNode = JSDocComment,
|
||||
LastJSDocTagNode = JSDocTypeLiteral
|
||||
LastJSDocTagNode = JSDocNeverKeyword
|
||||
}
|
||||
|
||||
export const enum NodeFlags {
|
||||
@@ -585,7 +593,7 @@ namespace ts {
|
||||
// @kind(SyntaxKind.ConstructSignature)
|
||||
export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { }
|
||||
|
||||
export type BindingName = Identifier | ObjectBindingPattern | ArrayBindingPattern;
|
||||
export type BindingName = Identifier | BindingPattern;
|
||||
|
||||
// @kind(SyntaxKind.VariableDeclaration)
|
||||
export interface VariableDeclaration extends Declaration {
|
||||
@@ -1038,13 +1046,19 @@ namespace ts {
|
||||
multiLine?: boolean;
|
||||
}
|
||||
|
||||
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
|
||||
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
|
||||
|
||||
// @kind(SyntaxKind.PropertyAccessExpression)
|
||||
export interface PropertyAccessExpression extends MemberExpression, Declaration {
|
||||
expression: LeftHandSideExpression;
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression;
|
||||
/** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */
|
||||
export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression {
|
||||
_propertyAccessExpressionLikeQualifiedNameBrand?: any;
|
||||
expression: EntityNameExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.ElementAccessExpression)
|
||||
export interface ElementAccessExpression extends MemberExpression {
|
||||
@@ -1566,6 +1580,10 @@ namespace ts {
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocLiteralType extends JSDocType {
|
||||
literal: LiteralTypeNode;
|
||||
}
|
||||
|
||||
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
|
||||
|
||||
// @kind(SyntaxKind.JSDocRecordMember)
|
||||
@@ -2108,7 +2126,7 @@ namespace ts {
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult;
|
||||
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
getReferencedValueDeclaration(reference: Identifier): Declaration;
|
||||
@@ -2117,7 +2135,7 @@ namespace ts {
|
||||
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
|
||||
isArgumentsLocalBinding(node: Identifier): boolean;
|
||||
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile;
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityName | PropertyAccessExpression): string[];
|
||||
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
|
||||
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
|
||||
}
|
||||
|
||||
@@ -2224,6 +2242,8 @@ namespace ts {
|
||||
/* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
|
||||
/* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
|
||||
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
|
||||
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
|
||||
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2237,6 +2257,8 @@ namespace ts {
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
|
||||
hasCommonType?: boolean; // True if constituents of synthetic property all have same type
|
||||
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
|
||||
@@ -2247,9 +2269,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
|
||||
export interface SymbolTable {
|
||||
[index: string]: Symbol;
|
||||
}
|
||||
export type SymbolTable = Map<Symbol>;
|
||||
|
||||
/** Represents a "prefix*suffix" pattern. */
|
||||
/* @internal */
|
||||
@@ -2276,23 +2296,26 @@ namespace ts {
|
||||
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
|
||||
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
|
||||
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
|
||||
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
|
||||
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
|
||||
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
|
||||
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
|
||||
ClassWithConstructorReference = 0x00080000, // Class that contains a binding to its constructor inside of the class body.
|
||||
ConstructorReferenceInClass = 0x00100000, // Binding to a class constructor inside of the class's body.
|
||||
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
|
||||
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
|
||||
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
|
||||
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
|
||||
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
|
||||
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
|
||||
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
|
||||
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
|
||||
AssignmentsMarked = 0x00400000, // Parameter assignments have been marked
|
||||
ClassWithConstructorReference = 0x00800000, // Class that contains a binding to its constructor inside of the class body.
|
||||
ConstructorReferenceInClass = 0x01000000, // Binding to a class constructor inside of the class's body.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NodeLinks {
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
resolvedType?: Type; // Cached type of type node
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
enumMemberValue?: number; // Constant value of enum member
|
||||
isVisible?: boolean; // Is this node visible
|
||||
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
|
||||
@@ -2322,7 +2345,7 @@ namespace ts {
|
||||
Class = 1 << 15, // Class
|
||||
Interface = 1 << 16, // Interface
|
||||
Reference = 1 << 17, // Generic type reference
|
||||
Tuple = 1 << 18, // Tuple
|
||||
Tuple = 1 << 18, // Synthesized generic tuple type
|
||||
Union = 1 << 19, // Union (T | U)
|
||||
Intersection = 1 << 20, // Intersection (T & U)
|
||||
Anonymous = 1 << 21, // Anonymous
|
||||
@@ -2444,10 +2467,6 @@ namespace ts {
|
||||
instantiations: Map<TypeReference>; // Generic instantiation cache
|
||||
}
|
||||
|
||||
export interface TupleType extends ObjectType {
|
||||
elementTypes: Type[]; // Element types
|
||||
}
|
||||
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
@@ -2632,7 +2651,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export type RootPaths = string[];
|
||||
export type PathSubstitutions = Map<string[]>;
|
||||
export type PathSubstitutions = MapLike<string[]>;
|
||||
export type TsConfigOnlyOptions = RootPaths | PathSubstitutions;
|
||||
|
||||
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions;
|
||||
@@ -2793,7 +2812,7 @@ namespace ts {
|
||||
fileNames: string[];
|
||||
raw?: any;
|
||||
errors: Diagnostic[];
|
||||
wildcardDirectories?: Map<WatchDirectoryFlags>;
|
||||
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
|
||||
}
|
||||
|
||||
export const enum WatchDirectoryFlags {
|
||||
@@ -2803,7 +2822,7 @@ namespace ts {
|
||||
|
||||
export interface ExpandResult {
|
||||
fileNames: string[];
|
||||
wildcardDirectories: Map<WatchDirectoryFlags>;
|
||||
wildcardDirectories: MapLike<WatchDirectoryFlags>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2825,7 +2844,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
|
||||
type: Map<number | string>; // an object literal mapping named values to actual values
|
||||
type: Map<number | string>; // an object literal mapping named values to actual values
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
+38
-53
@@ -83,25 +83,6 @@ namespace ts {
|
||||
return node.end - node.pos;
|
||||
}
|
||||
|
||||
export function mapIsEqualTo<T>(map1: Map<T>, map2: Map<T>): boolean {
|
||||
if (!map1 || !map2) {
|
||||
return map1 === map2;
|
||||
}
|
||||
return containsAll(map1, map2) && containsAll(map2, map1);
|
||||
}
|
||||
|
||||
function containsAll<T>(map: Map<T>, other: Map<T>): boolean {
|
||||
for (const key in map) {
|
||||
if (!hasProperty(map, key)) {
|
||||
continue;
|
||||
}
|
||||
if (!hasProperty(other, key) || map[key] !== other[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
|
||||
if (!array1 || !array2) {
|
||||
return array1 === array2;
|
||||
@@ -122,7 +103,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
|
||||
return sourceFile && sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleNameText);
|
||||
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]);
|
||||
}
|
||||
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
|
||||
@@ -131,7 +112,7 @@ namespace ts {
|
||||
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
|
||||
if (!sourceFile.resolvedModules) {
|
||||
sourceFile.resolvedModules = {};
|
||||
sourceFile.resolvedModules = createMap<ResolvedModule>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedModules[moduleNameText] = resolvedModule;
|
||||
@@ -139,7 +120,7 @@ namespace ts {
|
||||
|
||||
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
|
||||
if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames = {};
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective;
|
||||
@@ -162,7 +143,7 @@ namespace ts {
|
||||
}
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const newResolution = newResolutions[i];
|
||||
const oldResolution = oldResolutions && hasProperty(oldResolutions, names[i]) ? oldResolutions[names[i]] : undefined;
|
||||
const oldResolution = oldResolutions && oldResolutions[names[i]];
|
||||
const changed =
|
||||
oldResolution
|
||||
? !newResolution || !comparer(oldResolution, newResolution)
|
||||
@@ -320,6 +301,10 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
|
||||
}
|
||||
|
||||
export function isJSDocTag(node: Node) {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
@@ -1118,23 +1103,14 @@ namespace ts {
|
||||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function isSuperPropertyCall(node: Node): node is CallExpression {
|
||||
return node.kind === SyntaxKind.CallExpression
|
||||
&& <boolean>isSuperProperty((<CallExpression>node).expression);
|
||||
}
|
||||
|
||||
export function isSuperCall(node: Node): node is CallExpression {
|
||||
return node.kind === SyntaxKind.CallExpression
|
||||
&& (<CallExpression>node).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return (<ExpressionWithTypeArguments>node).expression;
|
||||
Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
|
||||
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.QualifiedName:
|
||||
return (<EntityName><Node>node);
|
||||
@@ -1716,8 +1692,8 @@ namespace ts {
|
||||
// import * as <symbol> from ...
|
||||
// import { x as <symbol> } from ...
|
||||
// export { x as <symbol> } from ...
|
||||
// export = ...
|
||||
// export default ...
|
||||
// export = <EntityNameExpression>
|
||||
// export default <EntityNameExpression>
|
||||
export function isAliasSymbolDeclaration(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
|
||||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
|
||||
@@ -1725,7 +1701,11 @@ namespace ts {
|
||||
node.kind === SyntaxKind.NamespaceImport ||
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier;
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node);
|
||||
}
|
||||
|
||||
export function exportAssignmentIsAlias(node: ExportAssignment): boolean {
|
||||
return isEntityNameExpression(node.expression);
|
||||
}
|
||||
|
||||
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
@@ -2043,7 +2023,6 @@ namespace ts {
|
||||
return Associativity.Right;
|
||||
}
|
||||
}
|
||||
|
||||
return Associativity.Left;
|
||||
}
|
||||
|
||||
@@ -2198,7 +2177,7 @@ namespace ts {
|
||||
|
||||
export function createDiagnosticCollection(): DiagnosticCollection {
|
||||
let nonFileDiagnostics: Diagnostic[] = [];
|
||||
const fileDiagnostics: Map<Diagnostic[]> = {};
|
||||
const fileDiagnostics = createMap<Diagnostic[]>();
|
||||
|
||||
let diagnosticsModified = false;
|
||||
let modificationCount = 0;
|
||||
@@ -2262,9 +2241,7 @@ namespace ts {
|
||||
forEach(nonFileDiagnostics, pushDiagnostic);
|
||||
|
||||
for (const key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
forEach(fileDiagnostics[key], pushDiagnostic);
|
||||
}
|
||||
forEach(fileDiagnostics[key], pushDiagnostic);
|
||||
}
|
||||
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
@@ -2279,9 +2256,7 @@ namespace ts {
|
||||
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
|
||||
|
||||
for (const key in fileDiagnostics) {
|
||||
if (hasProperty(fileDiagnostics, key)) {
|
||||
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
|
||||
}
|
||||
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2292,7 +2267,7 @@ namespace ts {
|
||||
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
|
||||
// There is no reason for this other than that JSON.stringify does not handle it either.
|
||||
const escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const escapedCharsMap: Map<string> = {
|
||||
const escapedCharsMap = createMap({
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
@@ -2305,7 +2280,7 @@ namespace ts {
|
||||
"\u2028": "\\u2028", // lineSeparator
|
||||
"\u2029": "\\u2029", // paragraphSeparator
|
||||
"\u0085": "\\u0085" // nextLine
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
@@ -3083,6 +3058,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
|
||||
return node.kind === SyntaxKind.Identifier ||
|
||||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
|
||||
}
|
||||
|
||||
export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
return (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) ||
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
@@ -3111,6 +3091,11 @@ namespace ts {
|
||||
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */
|
||||
export function tryExtractTypeScriptExtension(fileName: string): string | undefined {
|
||||
return find(supportedTypescriptExtensionsForExtractExtension, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace each instance of non-ascii characters by one, two, three, or four escape sequences
|
||||
* representing the UTF-8 encoding of the character, and return the expanded char code list.
|
||||
@@ -3190,7 +3175,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function stringifyObject(value: any) {
|
||||
return `{${reduceProperties(value, stringifyProperty, "")}}`;
|
||||
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
|
||||
}
|
||||
|
||||
function stringifyProperty(memo: string, value: any, key: string) {
|
||||
@@ -3332,7 +3317,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
const syntaxKindCache: Map<string> = {};
|
||||
const syntaxKindCache = createMap<string>();
|
||||
|
||||
export function formatSyntaxKind(kind: SyntaxKind): string {
|
||||
const syntaxKindEnum = (<any>ts).SyntaxKind;
|
||||
@@ -3480,7 +3465,7 @@ namespace ts {
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver) {
|
||||
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
const exportSpecifiers: Map<ExportSpecifier[]> = {};
|
||||
const exportSpecifiers = createMap<ExportSpecifier[]>();
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
for (const node of sourceFile.statements) {
|
||||
@@ -3521,7 +3506,7 @@ namespace ts {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
const name = (specifier.propertyName || specifier.name).text;
|
||||
getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
|
||||
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3623,7 +3608,7 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
export function isGeneratedIdentifier(node: Node): node is Identifier {
|
||||
export function isGeneratedIdentifier(node: Node): boolean {
|
||||
// Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`.
|
||||
return isIdentifier(node) && node.autoGenerateKind > GeneratedIdentifierKind.None;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace ts {
|
||||
* supplant the existing `forEachChild` implementation if performance is not
|
||||
* significantly impacted.
|
||||
*/
|
||||
const nodeEdgeTraversalMap: Map<NodeTraversalPath> = {
|
||||
const nodeEdgeTraversalMap = createMap<NodeTraversalPath>({
|
||||
[SyntaxKind.QualifiedName]: [
|
||||
{ name: "left", test: isEntityName },
|
||||
{ name: "right", test: isIdentifier }
|
||||
@@ -93,7 +93,7 @@ namespace ts {
|
||||
{ name: "name", test: isPropertyName },
|
||||
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
function reduceNode<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
|
||||
return node ? f(initial, node) : initial;
|
||||
@@ -523,7 +523,7 @@ namespace ts {
|
||||
const edgeTraversalPath = nodeEdgeTraversalMap[kind];
|
||||
if (edgeTraversalPath) {
|
||||
for (const edge of edgeTraversalPath) {
|
||||
const value = (<Map<any>>node)[edge.name];
|
||||
const value = (<MapLike<any>>node)[edge.name];
|
||||
if (value !== undefined) {
|
||||
result = isArray(value)
|
||||
? reduceLeft(<NodeArray<Node>>value, f, result)
|
||||
@@ -1140,7 +1140,7 @@ namespace ts {
|
||||
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
default:
|
||||
let updated: Node & Map<any>;
|
||||
let updated: Node & MapLike<any>;
|
||||
const edgeTraversalPath = nodeEdgeTraversalMap[kind];
|
||||
if (edgeTraversalPath) {
|
||||
for (const edge of edgeTraversalPath) {
|
||||
|
||||
+10
-218
@@ -1,8 +1,6 @@
|
||||
/// <reference path="harness.ts" />
|
||||
/// <reference path="runnerbase.ts" />
|
||||
/// <reference path="typeWriter.ts" />
|
||||
// In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
|
||||
const enum CompilerTestType {
|
||||
Conformance,
|
||||
@@ -52,7 +50,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
private makeUnitName(name: string, root: string) {
|
||||
const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
return path.replace(pathStart, "/");
|
||||
return pathStart ? path.replace(pathStart, "/") : path;
|
||||
};
|
||||
|
||||
public checkTestCodeOutput(fileName: string) {
|
||||
@@ -136,27 +134,16 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
otherFiles = undefined;
|
||||
});
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
|
||||
}
|
||||
|
||||
function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) {
|
||||
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
|
||||
}
|
||||
|
||||
// check errors
|
||||
it("Correct errors for " + fileName, () => {
|
||||
if (this.errors) {
|
||||
Harness.Baseline.runBaseline("Correct errors for " + fileName, justName.replace(/\.tsx?$/, ".errors.txt"), (): string => {
|
||||
if (result.errors.length === 0) return null;
|
||||
return getErrorBaseline(toBeCompiled, otherFiles, result);
|
||||
});
|
||||
Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors);
|
||||
}
|
||||
});
|
||||
|
||||
it (`Correct module resolution tracing for ${fileName}`, () => {
|
||||
if (options.traceResolution) {
|
||||
Harness.Baseline.runBaseline("Correct module resolution tracing for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
return JSON.stringify(result.traceResults || [], undefined, 4);
|
||||
});
|
||||
}
|
||||
@@ -165,11 +152,13 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
// Source maps?
|
||||
it("Correct sourcemap content for " + fileName, () => {
|
||||
if (options.sourceMap || options.inlineSourceMap) {
|
||||
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
|
||||
const record = result.getSourceMapRecord();
|
||||
if ((options.noEmitOnError && result.errors.length !== 0) || record === undefined) {
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required.
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
return record;
|
||||
});
|
||||
@@ -178,87 +167,12 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
it("Correct JS output for " + fileName, () => {
|
||||
if (hasNonDtsFiles && this.emit) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline("Correct JS output for " + fileName, justName.replace(/\.tsx?/, ".js"), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
tsCode += "//// [" + fileName + "] ////\r\n\r\n";
|
||||
}
|
||||
for (let i = 0; i < tsSources.length; i++) {
|
||||
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
|
||||
}
|
||||
|
||||
let jsCode = "";
|
||||
for (let i = 0; i < result.files.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.files[i]);
|
||||
jsCode += result.files[i].code;
|
||||
}
|
||||
|
||||
if (result.declFilesCode.length > 0) {
|
||||
jsCode += "\r\n\r\n";
|
||||
for (let i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
|
||||
jsCode += result.declFilesCode[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
jsCode += "\r\n\r\n";
|
||||
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
return tsCode + "\r\n\r\n" + jsCode;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, toBeCompiled, otherFiles, harnessSettings);
|
||||
}
|
||||
});
|
||||
|
||||
it("Correct Sourcemap output for " + fileName, () => {
|
||||
if (options.inlineSourceMap) {
|
||||
if (result.sourceMaps.length > 0) {
|
||||
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (options.sourceMap) {
|
||||
if (result.sourceMaps.length !== result.files.length) {
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline("Correct Sourcemap output for " + fileName, justName.replace(/\.tsx?/, ".js.map"), () => {
|
||||
if ((options.noEmitOnError && result.errors.length !== 0) || result.sourceMaps.length === 0) {
|
||||
// We need to return null here or the runBaseLine will actually create a empty file.
|
||||
// Baselining isn't required here because there is no output.
|
||||
return null;
|
||||
}
|
||||
|
||||
let sourceMapCode = "";
|
||||
for (let i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
|
||||
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
|
||||
sourceMapCode += result.sourceMaps[i].code;
|
||||
}
|
||||
|
||||
return sourceMapCode;
|
||||
});
|
||||
}
|
||||
Harness.Compiler.doSourcemapBaseline(justName, options, result);
|
||||
});
|
||||
|
||||
it("Correct type/symbol baselines for " + fileName, () => {
|
||||
@@ -266,129 +180,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
return;
|
||||
}
|
||||
|
||||
// NEWTODO: Type baselines
|
||||
if (result.errors.length !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type displayed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
const program = result.program;
|
||||
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
|
||||
|
||||
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
|
||||
|
||||
const fullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
const pullResults: ts.Map<TypeWriterResult[]> = {};
|
||||
|
||||
for (const sourceFile of allFiles) {
|
||||
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
}
|
||||
|
||||
// Produce baselines. The first gives the types for all expressions.
|
||||
// The second gives symbols for all identifiers.
|
||||
let e1: Error, e2: Error;
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ false);
|
||||
}
|
||||
catch (e) {
|
||||
e1 = e;
|
||||
}
|
||||
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ true);
|
||||
}
|
||||
catch (e) {
|
||||
e2 = e;
|
||||
}
|
||||
|
||||
if (e1 || e2) {
|
||||
throw e1 || e2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function checkBaseLines(isSymbolBaseLine: boolean) {
|
||||
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
|
||||
|
||||
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
|
||||
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
|
||||
|
||||
if (fullBaseLine !== pullBaseLine) {
|
||||
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
Harness.Baseline.runBaseline("Correct pull information for " + fileName, justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
|
||||
}
|
||||
else {
|
||||
Harness.Baseline.runBaseline("Correct information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
|
||||
}
|
||||
}
|
||||
|
||||
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
|
||||
const typeLines: string[] = [];
|
||||
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
|
||||
allFiles.forEach(file => {
|
||||
const codeLines = file.content.split("\n");
|
||||
typeWriterResults[file.unitName].forEach(result => {
|
||||
if (isSymbolBaseline && !result.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
if (!typeMap[file.unitName]) {
|
||||
typeMap[file.unitName] = {};
|
||||
}
|
||||
|
||||
let typeInfo = [formattedLine];
|
||||
const existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
if (existingTypeInfo) {
|
||||
typeInfo = existingTypeInfo.concat(typeInfo);
|
||||
}
|
||||
typeMap[file.unitName][result.line] = typeInfo;
|
||||
});
|
||||
|
||||
typeLines.push("=== " + file.unitName + " ===\r\n");
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
const currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + "\r\n");
|
||||
if (typeMap[file.unitName]) {
|
||||
const typeInfo = typeMap[file.unitName][i];
|
||||
if (typeInfo) {
|
||||
typeInfo.forEach(ty => {
|
||||
typeLines.push(">" + ty + "\r\n");
|
||||
});
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
|
||||
}
|
||||
else {
|
||||
typeLines.push("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeLines.push("No type information for this code.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeLines.join("");
|
||||
}
|
||||
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(justName, result, toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+52
-91
@@ -95,14 +95,14 @@ namespace FourSlash {
|
||||
|
||||
export import IndentStyle = ts.IndentStyle;
|
||||
|
||||
const entityMap: ts.Map<string> = {
|
||||
const entityMap = ts.createMap({
|
||||
"&": "&",
|
||||
"\"": """,
|
||||
"'": "'",
|
||||
"/": "/",
|
||||
"<": "<",
|
||||
">": ">"
|
||||
};
|
||||
});
|
||||
|
||||
export function escapeXmlAttributeValue(s: string) {
|
||||
return s.replace(/[&<>"'\/]/g, ch => entityMap[ch]);
|
||||
@@ -204,7 +204,7 @@ namespace FourSlash {
|
||||
|
||||
public formatCodeOptions: ts.FormatCodeOptions;
|
||||
|
||||
private inputFiles: ts.Map<string> = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
|
||||
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
|
||||
|
||||
// Add input file which has matched file name with the given reference-file path.
|
||||
// This is necessary when resolveReference flag is specified
|
||||
@@ -249,6 +249,7 @@ namespace FourSlash {
|
||||
if (compilationOptions.typeRoots) {
|
||||
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
|
||||
}
|
||||
compilationOptions.skipDefaultLibCheck = true;
|
||||
|
||||
const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions);
|
||||
this.languageServiceAdapterHost = languageServiceAdapter.getHost();
|
||||
@@ -300,11 +301,11 @@ namespace FourSlash {
|
||||
}
|
||||
else {
|
||||
// resolveReference file-option is not specified then do not resolve any files and include all inputFiles
|
||||
ts.forEachKey(this.inputFiles, fileName => {
|
||||
for (const fileName in this.inputFiles) {
|
||||
if (!Harness.isDefaultLibraryFile(fileName)) {
|
||||
this.languageServiceAdapterHost.addScript(fileName, this.inputFiles[fileName], /*isRootFile*/ true);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName,
|
||||
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
|
||||
}
|
||||
@@ -376,7 +377,7 @@ namespace FourSlash {
|
||||
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
|
||||
const startMarker = this.getMarkerByName(startMarkerName);
|
||||
const endMarker = this.getMarkerByName(endMarkerName);
|
||||
const predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
const predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false;
|
||||
};
|
||||
|
||||
@@ -428,12 +429,12 @@ namespace FourSlash {
|
||||
let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean;
|
||||
|
||||
if (after) {
|
||||
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false;
|
||||
};
|
||||
}
|
||||
else {
|
||||
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
|
||||
return ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false;
|
||||
};
|
||||
}
|
||||
@@ -458,7 +459,7 @@ namespace FourSlash {
|
||||
endPos = endMarker.position;
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
errors.forEach(function(error: ts.Diagnostic) {
|
||||
if (predicate(error.start, error.start + error.length, startPos, endPos)) {
|
||||
exists = true;
|
||||
}
|
||||
@@ -475,7 +476,7 @@ namespace FourSlash {
|
||||
Harness.IO.log("Unexpected error(s) found. Error list is:");
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
errors.forEach(function(error: ts.Diagnostic) {
|
||||
Harness.IO.log(" minChar: " + error.start +
|
||||
", limChar: " + (error.start + error.length) +
|
||||
", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n");
|
||||
@@ -593,9 +594,9 @@ namespace FourSlash {
|
||||
|
||||
public noItemsWithSameNameButDifferentKind(): void {
|
||||
const completions = this.getCompletionListAtCaret();
|
||||
const uniqueItems: ts.Map<string> = {};
|
||||
const uniqueItems = ts.createMap<string>();
|
||||
for (const item of completions.entries) {
|
||||
if (!ts.hasProperty(uniqueItems, item.name)) {
|
||||
if (!(item.name in uniqueItems)) {
|
||||
uniqueItems[item.name] = item.kind;
|
||||
}
|
||||
else {
|
||||
@@ -773,7 +774,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public verifyRangesWithSameTextReferenceEachOther() {
|
||||
ts.forEachValue(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
|
||||
ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
|
||||
}
|
||||
|
||||
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
|
||||
@@ -1131,12 +1132,10 @@ namespace FourSlash {
|
||||
|
||||
}
|
||||
Harness.Baseline.runBaseline(
|
||||
"Breakpoint Locations for " + this.activeFile.fileName,
|
||||
baselineFile,
|
||||
() => {
|
||||
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos));
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput() {
|
||||
@@ -1158,7 +1157,6 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(
|
||||
"Generate getEmitOutput baseline : " + emitFiles.join(" "),
|
||||
this.testData.globalOptions[metadataOptionNames.baselineFile],
|
||||
() => {
|
||||
let resultString = "";
|
||||
@@ -1184,8 +1182,7 @@ namespace FourSlash {
|
||||
});
|
||||
|
||||
return resultString;
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public printBreakpointLocation(pos: number) {
|
||||
@@ -1348,14 +1345,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
// Enters lines of text at the current caret position
|
||||
public type(text: string) {
|
||||
return this.typeHighFidelity(text);
|
||||
}
|
||||
|
||||
// Enters lines of text at the current caret position, invoking
|
||||
// language service APIs to mimic Visual Studio's behavior
|
||||
// as much as possible
|
||||
private typeHighFidelity(text: string) {
|
||||
public type(text: string, highFidelity = false) {
|
||||
let offset = this.currentCaretPosition;
|
||||
const prevChar = " ";
|
||||
const checkCadence = (text.length >> 2) + 1;
|
||||
@@ -1364,24 +1354,26 @@ namespace FourSlash {
|
||||
// Make the edit
|
||||
const ch = text.charAt(i);
|
||||
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, ch);
|
||||
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||
if (highFidelity) {
|
||||
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
||||
offset++;
|
||||
|
||||
if (ch === "(" || ch === ",") {
|
||||
/* Signature help*/
|
||||
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
if (highFidelity) {
|
||||
if (ch === "(" || ch === ",") {
|
||||
/* Signature help*/
|
||||
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
|
||||
}
|
||||
|
||||
if (i % checkCadence === 0) {
|
||||
this.checkPostEditInvariants();
|
||||
// this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
|
||||
// this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
|
||||
if (i % checkCadence === 0) {
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle post-keystroke formatting
|
||||
@@ -1389,14 +1381,12 @@ namespace FourSlash {
|
||||
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
|
||||
if (edits.length) {
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
|
||||
// this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move the caret to wherever we ended up
|
||||
this.currentCaretPosition = offset;
|
||||
|
||||
this.fixCaretPosition();
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
@@ -1415,7 +1405,6 @@ namespace FourSlash {
|
||||
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
|
||||
if (edits.length) {
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1639,10 +1628,11 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public rangesByText(): ts.Map<Range[]> {
|
||||
const result: ts.Map<Range[]> = {};
|
||||
const result = ts.createMap<Range[]>();
|
||||
for (const range of this.getRanges()) {
|
||||
const text = this.rangeText(range);
|
||||
(ts.getProperty(result, text) || (result[text] = [])).push(range);
|
||||
const ranges = result[text] || (result[text] = []);
|
||||
ranges.push(range);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1736,13 +1726,11 @@ namespace FourSlash {
|
||||
|
||||
public baselineCurrentFileNameOrDottedNameSpans() {
|
||||
Harness.Baseline.runBaseline(
|
||||
"Name OrDottedNameSpans for " + this.activeFile.fileName,
|
||||
this.testData.globalOptions[metadataOptionNames.baselineFile],
|
||||
() => {
|
||||
return this.baselineCurrentFileLocations(pos =>
|
||||
this.getNameOrDottedNameSpan(pos));
|
||||
},
|
||||
true /* run immediately */);
|
||||
});
|
||||
}
|
||||
|
||||
public printNameOrDottedNameSpans(pos: number) {
|
||||
@@ -1897,7 +1885,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
|
||||
|
||||
const openBraceMap: ts.Map<ts.CharacterCodes> = {
|
||||
const openBraceMap = ts.createMap<ts.CharacterCodes>({
|
||||
"(": ts.CharacterCodes.openParen,
|
||||
"{": ts.CharacterCodes.openBrace,
|
||||
"[": ts.CharacterCodes.openBracket,
|
||||
@@ -1905,7 +1893,7 @@ namespace FourSlash {
|
||||
'"': ts.CharacterCodes.doubleQuote,
|
||||
"`": ts.CharacterCodes.backtick,
|
||||
"<": ts.CharacterCodes.lessThan
|
||||
};
|
||||
});
|
||||
|
||||
const charCode = openBraceMap[openingBrace];
|
||||
|
||||
@@ -2269,40 +2257,12 @@ namespace FourSlash {
|
||||
export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
|
||||
// Parse out the files and their metadata
|
||||
const testData = parseTestData(basePath, content, fileName);
|
||||
|
||||
const state = new TestState(basePath, testType, testData);
|
||||
|
||||
let result = "";
|
||||
const fourslashFile: Harness.Compiler.TestFile = {
|
||||
unitName: Harness.Compiler.fourslashFileName,
|
||||
content: undefined,
|
||||
};
|
||||
const testFile: Harness.Compiler.TestFile = {
|
||||
unitName: fileName,
|
||||
content: content
|
||||
};
|
||||
|
||||
const host = Harness.Compiler.createCompilerHost(
|
||||
[fourslashFile, testFile],
|
||||
(fn, contents) => result = contents,
|
||||
ts.ScriptTarget.Latest,
|
||||
Harness.IO.useCaseSensitiveFileNames(),
|
||||
Harness.IO.getCurrentDirectory());
|
||||
|
||||
const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
|
||||
|
||||
const sourceFile = host.getSourceFile(fileName, ts.ScriptTarget.ES3);
|
||||
|
||||
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
|
||||
if (diagnostics.length > 0) {
|
||||
throw new Error(`Error compiling ${fileName}: ` +
|
||||
diagnostics.map(e => ts.flattenDiagnosticMessageText(e.messageText, Harness.IO.newLine())).join("\r\n"));
|
||||
const output = ts.transpileModule(content, { reportDiagnostics: true });
|
||||
if (output.diagnostics.length > 0) {
|
||||
throw new Error(`Syntax error in ${basePath}: ${output.diagnostics[0].messageText}`);
|
||||
}
|
||||
|
||||
program.emit(sourceFile);
|
||||
|
||||
ts.Debug.assert(!!result);
|
||||
runCode(result, state);
|
||||
runCode(output.outputText, state);
|
||||
}
|
||||
|
||||
function runCode(code: string, state: TestState): void {
|
||||
@@ -2395,13 +2355,14 @@ ${code}
|
||||
// Comment line, check for global/file @options and record them
|
||||
const match = optionRegex.exec(line.substr(2));
|
||||
if (match) {
|
||||
const fileMetadataNamesIndex = fileMetadataNames.indexOf(match[1]);
|
||||
const [key, value] = match.slice(1);
|
||||
const fileMetadataNamesIndex = fileMetadataNames.indexOf(key);
|
||||
if (fileMetadataNamesIndex === -1) {
|
||||
// Check if the match is already existed in the global options
|
||||
if (globalOptions[match[1]] !== undefined) {
|
||||
throw new Error("Global Option : '" + match[1] + "' is already existed");
|
||||
if (globalOptions[key] !== undefined) {
|
||||
throw new Error(`Global option '${key}' already exists`);
|
||||
}
|
||||
globalOptions[match[1]] = match[2];
|
||||
globalOptions[key] = value;
|
||||
}
|
||||
else {
|
||||
if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) {
|
||||
@@ -2416,12 +2377,12 @@ ${code}
|
||||
resetLocalData();
|
||||
}
|
||||
|
||||
currentFileName = basePath + "/" + match[2];
|
||||
currentFileOptions[match[1]] = match[2];
|
||||
currentFileName = basePath + "/" + value;
|
||||
currentFileOptions[key] = value;
|
||||
}
|
||||
else {
|
||||
// Add other fileMetadata flag
|
||||
currentFileOptions[match[1]] = match[2];
|
||||
currentFileOptions[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2509,7 +2470,7 @@ ${code}
|
||||
}
|
||||
|
||||
const marker: Marker = {
|
||||
fileName: fileName,
|
||||
fileName,
|
||||
position: location.position,
|
||||
data: markerValue
|
||||
};
|
||||
@@ -2526,7 +2487,7 @@ ${code}
|
||||
|
||||
function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker {
|
||||
const marker: Marker = {
|
||||
fileName: fileName,
|
||||
fileName,
|
||||
position: location.position
|
||||
};
|
||||
|
||||
|
||||
+269
-76
@@ -822,7 +822,7 @@ namespace Harness {
|
||||
|
||||
export function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]) {
|
||||
const fs = new Utils.VirtualFileSystem(path, useCaseSensitiveFileNames());
|
||||
for (const file in listFiles(path)) {
|
||||
for (const file of listFiles(path)) {
|
||||
fs.addFile(file);
|
||||
}
|
||||
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), path => {
|
||||
@@ -922,9 +922,9 @@ namespace Harness {
|
||||
export const defaultLibFileName = "lib.d.ts";
|
||||
export const es2015DefaultLibFileName = "lib.es2015.d.ts";
|
||||
|
||||
const libFileNameSourceFileMap: ts.Map<ts.SourceFile> = {
|
||||
const libFileNameSourceFileMap= ts.createMap<ts.SourceFile>({
|
||||
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
|
||||
};
|
||||
});
|
||||
|
||||
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile {
|
||||
if (!isDefaultLibraryFile(fileName)) {
|
||||
@@ -1079,13 +1079,13 @@ namespace Harness {
|
||||
let optionsIndex: ts.Map<ts.CommandLineOption>;
|
||||
function getCommandLineOption(name: string): ts.CommandLineOption {
|
||||
if (!optionsIndex) {
|
||||
optionsIndex = {};
|
||||
optionsIndex = ts.createMap<ts.CommandLineOption>();
|
||||
const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations);
|
||||
for (const option of optionDeclarations) {
|
||||
optionsIndex[option.name.toLowerCase()] = option;
|
||||
}
|
||||
}
|
||||
return ts.lookUp(optionsIndex, name.toLowerCase());
|
||||
return optionsIndex[name.toLowerCase()];
|
||||
}
|
||||
|
||||
export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {
|
||||
@@ -1402,6 +1402,220 @@ namespace Harness {
|
||||
Harness.IO.newLine() + Harness.IO.newLine() + outputLines.join("\r\n");
|
||||
}
|
||||
|
||||
export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[]) {
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => {
|
||||
if (errors.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
return getErrorBaseline(inputFiles, errors);
|
||||
});
|
||||
}
|
||||
|
||||
export function doTypeAndSymbolBaseline(baselinePath: string, result: CompilerResult, allFiles: {unitName: string, content: string}[], opts?: Harness.Baseline.BaselineOptions) {
|
||||
if (result.errors.length !== 0) {
|
||||
return;
|
||||
}
|
||||
// The full walker simulates the types that you would get from doing a full
|
||||
// compile. The pull walker simulates the types you get when you just do
|
||||
// a type query for a random node (like how the LS would do it). Most of the
|
||||
// time, these will be the same. However, occasionally, they can be different.
|
||||
// Specifically, when the compiler internally depends on symbol IDs to order
|
||||
// things, then we may see different results because symbols can be created in a
|
||||
// different order with 'pull' operations, and thus can produce slightly differing
|
||||
// output.
|
||||
//
|
||||
// For example, with a full type check, we may see a type displayed as: number | string
|
||||
// But with a pull type check, we may see it as: string | number
|
||||
//
|
||||
// These types are equivalent, but depend on what order the compiler observed
|
||||
// certain parts of the program.
|
||||
|
||||
const program = result.program;
|
||||
|
||||
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
|
||||
|
||||
const fullResults = ts.createMap<TypeWriterResult[]>();
|
||||
|
||||
for (const sourceFile of allFiles) {
|
||||
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
|
||||
}
|
||||
|
||||
// Produce baselines. The first gives the types for all expressions.
|
||||
// The second gives symbols for all identifiers.
|
||||
let e1: Error, e2: Error;
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ false);
|
||||
}
|
||||
catch (e) {
|
||||
e1 = e;
|
||||
}
|
||||
|
||||
try {
|
||||
checkBaseLines(/*isSymbolBaseLine*/ true);
|
||||
}
|
||||
catch (e) {
|
||||
e2 = e;
|
||||
}
|
||||
|
||||
if (e1 || e2) {
|
||||
throw e1 || e2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
function checkBaseLines(isSymbolBaseLine: boolean) {
|
||||
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
|
||||
|
||||
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
|
||||
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, fullExtension), () => fullBaseLine, opts);
|
||||
}
|
||||
|
||||
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
|
||||
const typeLines: string[] = [];
|
||||
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
|
||||
|
||||
allFiles.forEach(file => {
|
||||
const codeLines = file.content.split("\n");
|
||||
typeWriterResults[file.unitName].forEach(result => {
|
||||
if (isSymbolBaseline && !result.symbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
|
||||
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
|
||||
if (!typeMap[file.unitName]) {
|
||||
typeMap[file.unitName] = {};
|
||||
}
|
||||
|
||||
let typeInfo = [formattedLine];
|
||||
const existingTypeInfo = typeMap[file.unitName][result.line];
|
||||
if (existingTypeInfo) {
|
||||
typeInfo = existingTypeInfo.concat(typeInfo);
|
||||
}
|
||||
typeMap[file.unitName][result.line] = typeInfo;
|
||||
});
|
||||
|
||||
typeLines.push("=== " + file.unitName + " ===\r\n");
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
const currentCodeLine = codeLines[i];
|
||||
typeLines.push(currentCodeLine + "\r\n");
|
||||
if (typeMap[file.unitName]) {
|
||||
const typeInfo = typeMap[file.unitName][i];
|
||||
if (typeInfo) {
|
||||
typeInfo.forEach(ty => {
|
||||
typeLines.push(">" + ty + "\r\n");
|
||||
});
|
||||
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
|
||||
}
|
||||
else {
|
||||
typeLines.push("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeLines.push("No type information for this code.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return typeLines.join("");
|
||||
}
|
||||
}
|
||||
|
||||
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
|
||||
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
|
||||
}
|
||||
|
||||
export function doSourcemapBaseline(baselinePath: string, options: ts.CompilerOptions, result: CompilerResult) {
|
||||
if (options.inlineSourceMap) {
|
||||
if (result.sourceMaps.length > 0) {
|
||||
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (options.sourceMap) {
|
||||
if (result.sourceMaps.length !== result.files.length) {
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js.map"), () => {
|
||||
if ((options.noEmitOnError && result.errors.length !== 0) || result.sourceMaps.length === 0) {
|
||||
// We need to return null here or the runBaseLine will actually create a empty file.
|
||||
// Baselining isn't required here because there is no output.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
|
||||
let sourceMapCode = "";
|
||||
for (let i = 0; i < result.sourceMaps.length; i++) {
|
||||
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
|
||||
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
|
||||
sourceMapCode += result.sourceMaps[i].code;
|
||||
}
|
||||
|
||||
return sourceMapCode;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js"), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
tsCode += "//// [" + header + "] ////\r\n\r\n";
|
||||
}
|
||||
for (let i = 0; i < tsSources.length; i++) {
|
||||
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
|
||||
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
|
||||
}
|
||||
|
||||
let jsCode = "";
|
||||
for (let i = 0; i < result.files.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.files[i]);
|
||||
jsCode += result.files[i].code;
|
||||
}
|
||||
|
||||
if (result.declFilesCode.length > 0) {
|
||||
jsCode += "\r\n\r\n";
|
||||
for (let i = 0; i < result.declFilesCode.length; i++) {
|
||||
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
|
||||
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
|
||||
jsCode += result.declFilesCode[i].code;
|
||||
}
|
||||
}
|
||||
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
jsCode += "\r\n\r\n";
|
||||
jsCode += Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}
|
||||
|
||||
if (jsCode.length > 0) {
|
||||
return tsCode + "\r\n\r\n" + jsCode;
|
||||
}
|
||||
else {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string {
|
||||
// Collect, test, and sort the fileNames
|
||||
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
|
||||
@@ -1643,6 +1857,7 @@ namespace Harness {
|
||||
|
||||
/** Support class for baseline files */
|
||||
export namespace Baseline {
|
||||
const NoContent = "<no content>";
|
||||
|
||||
export interface BaselineOptions {
|
||||
Subfolder?: string;
|
||||
@@ -1677,7 +1892,42 @@ namespace Harness {
|
||||
}
|
||||
|
||||
const fileCache: { [idx: string]: boolean } = {};
|
||||
function generateActual(actualFileName: string, generateContent: () => string): string {
|
||||
function generateActual(generateContent: () => string): string {
|
||||
|
||||
const actual = generateContent();
|
||||
|
||||
if (actual === undefined) {
|
||||
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) {
|
||||
// actual is now either undefined (the generator had an error), null (no file requested),
|
||||
// or some real output of the function
|
||||
if (actual === undefined) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual === null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
actual = NoContent;
|
||||
}
|
||||
|
||||
let expected = "<no content>";
|
||||
if (IO.fileExists(refFileName)) {
|
||||
expected = IO.readFile(refFileName);
|
||||
}
|
||||
|
||||
return { expected, actual };
|
||||
}
|
||||
|
||||
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string) {
|
||||
// For now this is written using TypeScript, because sys is not available when running old test cases.
|
||||
// But we need to move to sys once we have
|
||||
// Creates the directory including its parent if not already present
|
||||
@@ -1703,81 +1953,24 @@ namespace Harness {
|
||||
IO.deleteFile(actualFileName);
|
||||
}
|
||||
|
||||
const actual = generateContent();
|
||||
|
||||
if (actual === undefined) {
|
||||
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
|
||||
}
|
||||
|
||||
// Store the content in the 'local' folder so we
|
||||
// can accept it later (manually)
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual !== null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
IO.writeFile(actualFileName, actual);
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
function compareToBaseline(actual: string, relativeFileName: string, opts: BaselineOptions) {
|
||||
// actual is now either undefined (the generator had an error), null (no file requested),
|
||||
// or some real output of the function
|
||||
if (actual === undefined) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
/* tslint:disable:no-null-keyword */
|
||||
if (actual === null) {
|
||||
/* tslint:enable:no-null-keyword */
|
||||
actual = "<no content>";
|
||||
}
|
||||
|
||||
let expected = "<no content>";
|
||||
if (IO.fileExists(refFileName)) {
|
||||
expected = IO.readFile(refFileName);
|
||||
}
|
||||
|
||||
return { expected, actual };
|
||||
}
|
||||
|
||||
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, descriptionForDescribe: string) {
|
||||
const encoded_actual = Utils.encodeString(actual);
|
||||
if (expected != encoded_actual) {
|
||||
// Overwrite & issue error
|
||||
const errMsg = "The baseline file " + relativeFileName + " has changed.";
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
export function runBaseline(
|
||||
descriptionForDescribe: string,
|
||||
relativeFileName: string,
|
||||
generateContent: () => string,
|
||||
runImmediately = false,
|
||||
opts?: BaselineOptions): void {
|
||||
|
||||
let actual = <string>undefined;
|
||||
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
try {
|
||||
if (runImmediately) {
|
||||
actual = generateActual(actualFileName, generateContent);
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
|
||||
if (expected !== encoded_actual) {
|
||||
if (actual === NoContent) {
|
||||
IO.writeFile(actualFileName + ".delete", "");
|
||||
}
|
||||
else {
|
||||
actual = generateActual(actualFileName, generateContent);
|
||||
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
|
||||
IO.writeFile(actualFileName, actual);
|
||||
}
|
||||
throw new Error(`The baseline file ${relativeFileName} has changed.`);
|
||||
}
|
||||
catch (e) {
|
||||
throw Utils.filterStack(e);
|
||||
}
|
||||
}
|
||||
|
||||
export function runBaseline(relativeFileName: string, generateContent: () => string, opts?: BaselineOptions): void {
|
||||
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
|
||||
|
||||
const actual = generateActual(generateContent);
|
||||
const comparison = compareToBaseline(actual, relativeFileName, opts);
|
||||
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
export class LanguageServiceAdapterHost {
|
||||
protected fileNameToScript: ts.Map<ScriptInfo> = {};
|
||||
protected fileNameToScript = ts.createMap<ScriptInfo>();
|
||||
|
||||
constructor(protected cancellationToken = DefaultHostCancellationToken.Instance,
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
@@ -135,7 +135,7 @@ namespace Harness.LanguageService {
|
||||
|
||||
public getFilenames(): string[] {
|
||||
const fileNames: string[] = [];
|
||||
ts.forEachValue(this.fileNameToScript, (scriptInfo) => {
|
||||
ts.forEachProperty(this.fileNameToScript, (scriptInfo) => {
|
||||
if (scriptInfo.isRootFile) {
|
||||
// only include root files here
|
||||
// usually it means that we won't include lib.d.ts in the list of root files so it won't mess the computation of compilation root dir.
|
||||
@@ -146,7 +146,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
public getScriptInfo(fileName: string): ScriptInfo {
|
||||
return ts.lookUp(this.fileNameToScript, fileName);
|
||||
return this.fileNameToScript[fileName];
|
||||
}
|
||||
|
||||
public addScript(fileName: string, content: string, isRootFile: boolean): void {
|
||||
@@ -235,7 +235,7 @@ namespace Harness.LanguageService {
|
||||
this.getModuleResolutionsForFile = (fileName) => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
|
||||
const imports: ts.Map<string> = {};
|
||||
const imports = ts.createMap<string>();
|
||||
for (const module of preprocessInfo.importedFiles) {
|
||||
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
|
||||
if (resolutionInfo.resolvedModule) {
|
||||
@@ -248,7 +248,7 @@ namespace Harness.LanguageService {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
if (scriptInfo) {
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ false);
|
||||
const resolutions: ts.Map<ts.ResolvedTypeReferenceDirective> = {};
|
||||
const resolutions = ts.createMap<ts.ResolvedTypeReferenceDirective>();
|
||||
const settings = this.nativeHost.getCompilationSettings();
|
||||
for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) {
|
||||
const resolutionInfo = ts.resolveTypeReferenceDirective(typeReferenceDirective.fileName, fileName, settings, moduleResolutionHost);
|
||||
|
||||
@@ -253,18 +253,15 @@ class ProjectRunner extends RunnerBase {
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
|
||||
};
|
||||
// Set the values specified using json
|
||||
const optionNameMap: ts.Map<ts.CommandLineOption> = {};
|
||||
ts.forEach(ts.optionDeclarations, option => {
|
||||
optionNameMap[option.name] = option;
|
||||
});
|
||||
const optionNameMap = ts.arrayToMap(ts.optionDeclarations, option => option.name);
|
||||
for (const name in testCase) {
|
||||
if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) {
|
||||
if (name !== "mapRoot" && name !== "sourceRoot" && name in optionNameMap) {
|
||||
const option = optionNameMap[name];
|
||||
const optType = option.type;
|
||||
let value = <any>testCase[name];
|
||||
if (typeof optType !== "string") {
|
||||
const key = value.toLowerCase();
|
||||
if (ts.hasProperty(optType, key)) {
|
||||
if (key in optType) {
|
||||
value = optType[key];
|
||||
}
|
||||
}
|
||||
@@ -462,7 +459,7 @@ class ProjectRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("Resolution information of (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
Harness.Baseline.runBaseline("Resolution information of (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".json", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".json", () => {
|
||||
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
|
||||
});
|
||||
});
|
||||
@@ -470,7 +467,7 @@ class ProjectRunner extends RunnerBase {
|
||||
|
||||
it("Errors for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
if (compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".errors.txt", () => {
|
||||
return getErrorsBaseline(compilerResult);
|
||||
});
|
||||
}
|
||||
@@ -483,7 +480,7 @@ class ProjectRunner extends RunnerBase {
|
||||
// There may be multiple files with different baselines. Run all and report at the end, else
|
||||
// it stops copying the remaining emitted files from 'local/projectOutput' to 'local/project'.
|
||||
try {
|
||||
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
|
||||
try {
|
||||
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
|
||||
}
|
||||
@@ -502,10 +499,9 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// it("SourceMapRecord for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
|
||||
// if (compilerResult.sourceMapData) {
|
||||
// Harness.Baseline.runBaseline("SourceMapRecord for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
|
||||
// Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".sourcemap.txt", () => {
|
||||
// return Harness.SourceMapRecorder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
|
||||
// ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
|
||||
// });
|
||||
@@ -518,7 +514,7 @@ class ProjectRunner extends RunnerBase {
|
||||
if (!compilerResult.errors.length && testCase.declaration) {
|
||||
const dTsCompileResult = compileCompileDTsFiles(compilerResult);
|
||||
if (dTsCompileResult && dTsCompileResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
|
||||
return getErrorsBaseline(dTsCompileResult);
|
||||
});
|
||||
}
|
||||
|
||||
+20
-14
@@ -158,55 +158,56 @@ namespace RWC {
|
||||
|
||||
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", baseName + ".output.js", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.output.js`, () => {
|
||||
return Harness.Compiler.collateOutputs(compilerResult.files);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
it("has the expected declaration file content", () => {
|
||||
Harness.Baseline.runBaseline("has the expected declaration file content", baseName + ".d.ts", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.d.ts`, () => {
|
||||
if (!compilerResult.declFilesCode.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.collateOutputs(compilerResult.declFilesCode);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
it("has the expected source maps", () => {
|
||||
Harness.Baseline.runBaseline("has the expected source maps", baseName + ".map", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.map`, () => {
|
||||
if (!compilerResult.sourceMaps.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.collateOutputs(compilerResult.sourceMaps);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
/*it("has correct source map record", () => {
|
||||
if (compilerOptions.sourceMap) {
|
||||
Harness.Baseline.runBaseline("has correct source map record", baseName + ".sourcemap.txt", () => {
|
||||
Harness.Baseline.runBaseline(baseName + ".sourcemap.txt", () => {
|
||||
return compilerResult.getSourceMapRecord();
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
}
|
||||
});*/
|
||||
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", baseName + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.errors.txt`, () => {
|
||||
if (compilerResult.errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
// Do not include the library in the baselines to avoid noise
|
||||
const baselineFiles = inputFiles.concat(otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
|
||||
return Harness.Compiler.getErrorBaseline(baselineFiles, compilerResult.errors);
|
||||
}, false, baselineOpts);
|
||||
const errors = compilerResult.errors.filter(e => !Harness.isDefaultLibraryFile(e.file.fileName));
|
||||
return Harness.Compiler.getErrorBaseline(baselineFiles, errors);
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
// Ideally, a generated declaration file will have no errors. But we allow generated
|
||||
// declaration file errors as part of the baseline.
|
||||
it("has the expected errors in generated declaration files", () => {
|
||||
if (compilerOptions.declaration && !compilerResult.errors.length) {
|
||||
Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(`${baseName}.dts.errors.txt`, () => {
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
|
||||
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
|
||||
|
||||
@@ -217,11 +218,16 @@ namespace RWC {
|
||||
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
|
||||
Harness.IO.newLine() + Harness.IO.newLine() +
|
||||
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
|
||||
}, false, baselineOpts);
|
||||
}, baselineOpts);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Type baselines (need to refactor out from compilerRunner)
|
||||
it("has the expected types", () => {
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(`${baseName}.types`, compilerResult, inputFiles
|
||||
.concat(otherFiles)
|
||||
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
|
||||
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,21 +67,21 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("has the expected emitted code", () => {
|
||||
Harness.Baseline.runBaseline("has the expected emitted code", testState.filename + ".output.js", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".output.js", () => {
|
||||
const files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath);
|
||||
return Harness.Compiler.collateOutputs(files);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it("has the expected errors", () => {
|
||||
Harness.Baseline.runBaseline("has the expected errors", testState.filename + ".errors.txt", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".errors.txt", () => {
|
||||
const errors = testState.compilerResult.errors;
|
||||
if (errors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(testState.inputFiles, errors);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
|
||||
it("satisfies invariants", () => {
|
||||
@@ -90,10 +90,10 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
});
|
||||
|
||||
it("has the expected AST", () => {
|
||||
Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => {
|
||||
Harness.Baseline.runBaseline(testState.filename + ".AST.txt", () => {
|
||||
const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
return Utils.sourceFileToJSON(sourceFile);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
}, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
"./unittests/convertCompilerOptionsFromJson.ts",
|
||||
"./unittests/convertTypingOptionsFromJson.ts",
|
||||
"./unittests/tsserverProjectSystem.ts",
|
||||
"./unittests/matchFiles.ts"
|
||||
"./unittests/matchFiles.ts",
|
||||
"./unittests/initializeTSConfig.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
|
||||
const existingDirectories: Map<boolean> = {};
|
||||
forEachValue(fileMap, v => {
|
||||
let dir = getDirectoryPath(v.name);
|
||||
const existingDirectories = createMap<boolean>();
|
||||
for (const name in fileMap) {
|
||||
let dir = getDirectoryPath(name);
|
||||
let previous: string;
|
||||
do {
|
||||
existingDirectories[dir] = true;
|
||||
previous = dir;
|
||||
dir = getDirectoryPath(dir);
|
||||
} while (dir !== previous);
|
||||
});
|
||||
}
|
||||
return {
|
||||
args: <string[]>[],
|
||||
newLine: "\r\n",
|
||||
@@ -24,7 +24,7 @@ namespace ts {
|
||||
write: (s: string) => {
|
||||
},
|
||||
readFile: (path: string, encoding?: string): string => {
|
||||
return hasProperty(fileMap, path) && fileMap[path].content;
|
||||
return path in fileMap ? fileMap[path].content : undefined;
|
||||
},
|
||||
writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => {
|
||||
throw new Error("NYI");
|
||||
@@ -33,10 +33,10 @@ namespace ts {
|
||||
throw new Error("NYI");
|
||||
},
|
||||
fileExists: (path: string): boolean => {
|
||||
return hasProperty(fileMap, path);
|
||||
return path in fileMap;
|
||||
},
|
||||
directoryExists: (path: string): boolean => {
|
||||
return hasProperty(existingDirectories, path);
|
||||
return existingDirectories[path] || false;
|
||||
},
|
||||
createDirectory: (path: string) => {
|
||||
},
|
||||
@@ -102,7 +102,7 @@ namespace ts {
|
||||
content: `foo()`
|
||||
};
|
||||
|
||||
const serverHost = createDefaultServerHost({ [root.name]: root, [imported.name]: imported });
|
||||
const serverHost = createDefaultServerHost(createMap({ [root.name]: root, [imported.name]: imported }));
|
||||
const { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
|
||||
// ensure that imported file was found
|
||||
@@ -194,7 +194,7 @@ namespace ts {
|
||||
content: `export var y = 1`
|
||||
};
|
||||
|
||||
const fileMap: Map<File> = { [root.name]: root };
|
||||
const fileMap = createMap({ [root.name]: root });
|
||||
const serverHost = createDefaultServerHost(fileMap);
|
||||
const originalFileExists = serverHost.fileExists;
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("initTSConfig", () => {
|
||||
function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) {
|
||||
describe(name, () => {
|
||||
const commandLine = parseCommandLine(commandLinesArgs);
|
||||
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames);
|
||||
const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
|
||||
|
||||
it(`Correct output for ${outputFileName}`, () => {
|
||||
Harness.Baseline.runBaseline(outputFileName, () => {
|
||||
if (initResult) {
|
||||
return JSON.stringify(initResult, undefined, 4);
|
||||
}
|
||||
else {
|
||||
// This can happen if compiler recieve invalid compiler-options
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initTSConfigCorrectly("Default initialized TSConfig", ["--init"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with files options", ["--init", "file0.st", "file1.ts", "file2.ts"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with boolean value compiler options", ["--init", "--noUnusedLocals"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with enum value compiler options", ["--init", "--target", "es5", "--jsx", "react"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with list compiler options", ["--init", "--types", "jquery,mocha"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with list compiler options with enum value", ["--init", "--lib", "es5,es2015.core"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option", ["--init", "--someNonExistOption"]);
|
||||
|
||||
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option value", ["--init", "--lib", "nonExistLib,es5,es2015.promise"]);
|
||||
});
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace ts {
|
||||
const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content);
|
||||
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0);
|
||||
|
||||
Harness.Baseline.runBaseline("parseCorrectly", "JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json",
|
||||
Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json",
|
||||
() => Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type));
|
||||
});
|
||||
}
|
||||
@@ -99,7 +99,7 @@ namespace ts {
|
||||
Debug.fail("Comment has at least one diagnostic: " + comment.diagnostics[0].messageText);
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline("parseCorrectly", "JSDocParsing/DocComments.parsesCorrectly." + name + ".json",
|
||||
Harness.Baseline.runBaseline("JSDocParsing/DocComments.parsesCorrectly." + name + ".json",
|
||||
() => JSON.stringify(comment.jsDocComment,
|
||||
(k, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, 4));
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ts {
|
||||
const map = arrayToMap(files, f => f.name);
|
||||
|
||||
if (hasDirectoryExists) {
|
||||
const directories: Map<string> = {};
|
||||
const directories = createMap<string>();
|
||||
for (const f of files) {
|
||||
let name = getDirectoryPath(f.name);
|
||||
while (true) {
|
||||
@@ -25,19 +25,19 @@ namespace ts {
|
||||
return {
|
||||
readFile,
|
||||
directoryExists: path => {
|
||||
return hasProperty(directories, path);
|
||||
return path in directories;
|
||||
},
|
||||
fileExists: path => {
|
||||
assert.isTrue(hasProperty(directories, getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`);
|
||||
return hasProperty(map, path);
|
||||
assert.isTrue(getDirectoryPath(path) in directories, `'fileExists' '${path}' request in non-existing directory`);
|
||||
return path in map;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return { readFile, fileExists: path => hasProperty(map, path), };
|
||||
return { readFile, fileExists: path => path in map, };
|
||||
}
|
||||
function readFile(path: string): string {
|
||||
return hasProperty(map, path) ? map[path].content : undefined;
|
||||
return path in map ? map[path].content : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace ts {
|
||||
const host: CompilerHost = {
|
||||
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
return path in files ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
|
||||
@@ -298,7 +298,7 @@ namespace ts {
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
fileExists: fileName => {
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path);
|
||||
return path in files;
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
};
|
||||
@@ -318,7 +318,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
it("should find all modules", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c/first/shared.ts": `
|
||||
class A {}
|
||||
export = A`,
|
||||
@@ -332,23 +332,23 @@ import Shared = require('../first/shared');
|
||||
class C {}
|
||||
export = C;
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, "/a/b/c/first/second", ["class_a.ts"], 3, ["../../../c/third/class_c.ts"]);
|
||||
});
|
||||
|
||||
it("should find modules in node_modules", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/parent/node_modules/mod/index.d.ts": "export var x",
|
||||
"/parent/app/myapp.ts": `import {x} from "mod"`
|
||||
};
|
||||
});
|
||||
test(files, "/parent/app", ["myapp.ts"], 2, []);
|
||||
});
|
||||
|
||||
it("should find file referenced via absolute and relative names", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="b.ts"/>`,
|
||||
"/a/b/b.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, "/a/b", ["c.ts", "/a/b/b.ts"], 2, []);
|
||||
});
|
||||
});
|
||||
@@ -358,11 +358,7 @@ export = C;
|
||||
function test(files: Map<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void {
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
if (!useCaseSensitiveFileNames) {
|
||||
const f: Map<string> = {};
|
||||
for (const fileName in files) {
|
||||
f[getCanonicalFileName(fileName)] = files[fileName];
|
||||
}
|
||||
files = f;
|
||||
files = reduceProperties(files, (files, file, fileName) => (files[getCanonicalFileName(fileName)] = file, files), createMap<string>());
|
||||
}
|
||||
|
||||
const host: CompilerHost = {
|
||||
@@ -371,7 +367,7 @@ export = C;
|
||||
return library;
|
||||
}
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
return path in files ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
|
||||
@@ -382,7 +378,7 @@ export = C;
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
fileExists: fileName => {
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path);
|
||||
return path in files;
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
};
|
||||
@@ -395,77 +391,77 @@ export = C;
|
||||
}
|
||||
|
||||
it("should succeed when the same file is referenced using absolute and relative names", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
|
||||
"/a/b/d.ts": "var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `import {x} from "D"`,
|
||||
"/a/b/d.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"moduleA.ts": `import {x} from "./ModuleB"`,
|
||||
"moduleB.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when two files exist on disk that differs only in casing", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/b/c.ts": `import {x} from "D"`,
|
||||
"/a/b/D.ts": "export var x",
|
||||
"/a/b/d.ts": "export var y"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
|
||||
});
|
||||
|
||||
it("should fail when module name in 'require' calls has inconsistent casing", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"moduleA.ts": `import a = require("./ModuleC")`,
|
||||
"moduleB.ts": `import a = require("./moduleC")`,
|
||||
"moduleC.ts": "export var x"
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
|
||||
});
|
||||
|
||||
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/B/c/moduleA.ts": `import a = require("./ModuleC")`,
|
||||
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleC.ts": "export var x",
|
||||
"/a/B/c/moduleD.ts": `
|
||||
import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
|
||||
});
|
||||
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
|
||||
const files: Map<string> = {
|
||||
const files = createMap({
|
||||
"/a/B/c/moduleA.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
|
||||
"/a/B/c/moduleC.ts": "export var x",
|
||||
"/a/B/c/moduleD.ts": `
|
||||
import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
import a = require("./moduleA");
|
||||
import b = require("./moduleB");
|
||||
`
|
||||
};
|
||||
});
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
|
||||
});
|
||||
});
|
||||
@@ -1023,7 +1019,7 @@ import b = require("./moduleB.ts");
|
||||
const names = map(files, f => f.name);
|
||||
const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES6)), f => f.fileName);
|
||||
const compilerHost: CompilerHost = {
|
||||
fileExists : fileName => hasProperty(sourceFiles, fileName),
|
||||
fileExists : fileName => fileName in sourceFiles,
|
||||
getSourceFile: fileName => sourceFiles[fileName],
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
writeFile(file, text) {
|
||||
@@ -1034,7 +1030,7 @@ import b = require("./moduleB.ts");
|
||||
getCanonicalFileName: f => f.toLowerCase(),
|
||||
getNewLine: () => "\r\n",
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
readFile: fileName => hasProperty(sourceFiles, fileName) ? sourceFiles[fileName].text : undefined
|
||||
readFile: fileName => fileName in sourceFiles ? sourceFiles[fileName].text : undefined
|
||||
};
|
||||
const program1 = createProgram(names, {}, compilerHost);
|
||||
const diagnostics1 = program1.getFileProcessingDiagnostics().getDiagnostics();
|
||||
|
||||
@@ -95,13 +95,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createSourceFileWithText(fileName: string, sourceText: SourceText, target: ScriptTarget) {
|
||||
const file = <SourceFileWithText>createSourceFile(fileName, sourceText.getFullText(), target);
|
||||
file.sourceText = sourceText;
|
||||
return file;
|
||||
}
|
||||
|
||||
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget): CompilerHost {
|
||||
const files: Map<SourceFileWithText> = {};
|
||||
for (const t of texts) {
|
||||
const file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target);
|
||||
file.sourceText = t.text;
|
||||
files[t.name] = file;
|
||||
}
|
||||
const files = arrayToMap(texts, t => t.name, t => createSourceFileWithText(t.name, t.text, target));
|
||||
|
||||
return {
|
||||
getSourceFile(fileName): SourceFile {
|
||||
@@ -128,10 +129,9 @@ namespace ts {
|
||||
getNewLine(): string {
|
||||
return sys ? sys.newLine : newLine;
|
||||
},
|
||||
fileExists: fileName => hasProperty(files, fileName),
|
||||
fileExists: fileName => fileName in files,
|
||||
readFile: fileName => {
|
||||
const file = lookUp(files, fileName);
|
||||
return file && file.text;
|
||||
return fileName in files ? files[fileName].text : undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -152,29 +152,29 @@ namespace ts {
|
||||
return program;
|
||||
}
|
||||
|
||||
function getSizeOfMap(map: Map<any>): number {
|
||||
let size = 0;
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
size++;
|
||||
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return size;
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): void {
|
||||
assert.isTrue(actual !== undefined);
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
function checkResolvedTypeDirective(expected: ResolvedTypeReferenceDirective, actual: ResolvedTypeReferenceDirective): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedTypeDirective(expected: ResolvedTypeReferenceDirective, actual: ResolvedTypeReferenceDirective): void {
|
||||
assert.isTrue(actual !== undefined);
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => void): void {
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => boolean): void {
|
||||
const file = program.getSourceFile(fileName);
|
||||
assert.isTrue(file !== undefined, `cannot find file ${fileName}`);
|
||||
const cache = getCache(file);
|
||||
@@ -183,23 +183,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
assert.isTrue(cache !== undefined, `expected ${caption} to be set`);
|
||||
const actualCacheSize = getSizeOfMap(cache);
|
||||
const expectedSize = getSizeOfMap(expectedContent);
|
||||
assert.isTrue(actualCacheSize === expectedSize, `expected actual size: ${actualCacheSize} to be equal to ${expectedSize}`);
|
||||
|
||||
for (const id in expectedContent) {
|
||||
if (hasProperty(expectedContent, id)) {
|
||||
|
||||
if (expectedContent[id]) {
|
||||
const expected = expectedContent[id];
|
||||
const actual = cache[id];
|
||||
entryChecker(expected, actual);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert.isTrue(cache[id] === undefined);
|
||||
}
|
||||
}
|
||||
assert.isTrue(equalOwnProperties(expectedContent, cache, entryChecker), `contents of ${caption} did not match the expected contents.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +297,8 @@ namespace ts {
|
||||
});
|
||||
|
||||
it("resolution cache follows imports", () => {
|
||||
(<any>Error).stackTraceLimit = Infinity;
|
||||
|
||||
const files = [
|
||||
{ name: "a.ts", text: SourceText.New("", "import {_} from 'b'", "var x = 1") },
|
||||
{ name: "b.ts", text: SourceText.New("", "", "var y = 2") },
|
||||
@@ -320,7 +306,7 @@ namespace ts {
|
||||
const options: CompilerOptions = { target };
|
||||
|
||||
const program_1 = newProgram(files, ["a.ts"], options);
|
||||
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
@@ -329,7 +315,7 @@ namespace ts {
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
// imports has changed - program is not reused
|
||||
@@ -346,7 +332,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateImportsAndExports(newImports);
|
||||
});
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedModulesCache(program_4, "a.ts", { "b": { resolvedFileName: "b.ts" }, "c": undefined });
|
||||
checkResolvedModulesCache(program_4, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" }, "c": undefined }));
|
||||
});
|
||||
|
||||
it("resolved type directives cache follows type directives", () => {
|
||||
@@ -357,7 +343,7 @@ namespace ts {
|
||||
const options: CompilerOptions = { target, typeRoots: ["/types"] };
|
||||
|
||||
const program_1 = newProgram(files, ["/a.ts"], options);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
@@ -366,7 +352,7 @@ namespace ts {
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
// type reference directives has changed - program is not reused
|
||||
@@ -384,7 +370,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
});
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMap({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace ts.server {
|
||||
describe("onMessage", () => {
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
let i = 0;
|
||||
for (name in CommandNames) {
|
||||
for (const name in CommandNames) {
|
||||
if (!Object.prototype.hasOwnProperty.call(CommandNames, name)) {
|
||||
continue;
|
||||
}
|
||||
@@ -363,13 +363,13 @@ namespace ts.server {
|
||||
class InProcClient {
|
||||
private server: InProcSession;
|
||||
private seq = 0;
|
||||
private callbacks: ts.Map<(resp: protocol.Response) => void> = {};
|
||||
private eventHandlers: ts.Map<(args: any) => void> = {};
|
||||
private callbacks = createMap<(resp: protocol.Response) => void>();
|
||||
private eventHandlers = createMap<(args: any) => void>();
|
||||
|
||||
handle(msg: protocol.Message): void {
|
||||
if (msg.type === "response") {
|
||||
const response = <protocol.Response>msg;
|
||||
if (this.callbacks[response.request_seq]) {
|
||||
if (response.request_seq in this.callbacks) {
|
||||
this.callbacks[response.request_seq](response);
|
||||
delete this.callbacks[response.request_seq];
|
||||
}
|
||||
@@ -381,7 +381,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
emit(name: string, args: any): void {
|
||||
if (this.eventHandlers[name]) {
|
||||
if (name in this.eventHandlers) {
|
||||
this.eventHandlers[name](args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ namespace ts {
|
||||
oldTranspileDiagnostics = undefined;
|
||||
});
|
||||
|
||||
it("Correct errors", () => {
|
||||
Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".errors.txt"), () => {
|
||||
it("Correct errors for " + justName, () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), () => {
|
||||
if (transpileResult.diagnostics.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
@@ -74,8 +74,8 @@ namespace ts {
|
||||
});
|
||||
|
||||
if (canUseOldTranspile) {
|
||||
it("Correct errors (old transpile)", () => {
|
||||
Harness.Baseline.runBaseline("Correct errors", justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => {
|
||||
it("Correct errors (old transpile) for " + justName, () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), () => {
|
||||
if (oldTranspileDiagnostics.length === 0) {
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
@@ -87,8 +87,8 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
it("Correct output", () => {
|
||||
Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".js"), () => {
|
||||
it("Correct output for " + justName, () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".js"), () => {
|
||||
if (transpileResult.outputText) {
|
||||
return transpileResult.outputText;
|
||||
}
|
||||
@@ -102,8 +102,8 @@ namespace ts {
|
||||
});
|
||||
|
||||
if (canUseOldTranspile) {
|
||||
it("Correct output (old transpile)", () => {
|
||||
Harness.Baseline.runBaseline("Correct output", justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => {
|
||||
it("Correct output (old transpile) for " + justName, () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.js"), () => {
|
||||
return oldTranspileResult;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -181,5 +181,25 @@ namespace ts {
|
||||
["/d.ts", "/folder/e.ts"]
|
||||
);
|
||||
});
|
||||
|
||||
it("parse and re-emit tsconfig.json file with diagnostics", () => {
|
||||
const content = `{
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
"outDir": "bin"
|
||||
}
|
||||
"files": ["file1.ts"]
|
||||
}`;
|
||||
const { configJsonObject, diagnostics } = parseAndReEmitConfigJSONFile(content);
|
||||
const expectedResult = {
|
||||
compilerOptions: {
|
||||
allowJs: true,
|
||||
outDir: "bin"
|
||||
},
|
||||
files: ["file1.ts"]
|
||||
};
|
||||
assert.isTrue(diagnostics.length === 2);
|
||||
assert.equal(JSON.stringify(configJsonObject), JSON.stringify(expectedResult));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,20 +68,10 @@ namespace ts {
|
||||
return entry;
|
||||
}
|
||||
|
||||
function sizeOfMap(map: Map<any>): number {
|
||||
let n = 0;
|
||||
for (const name in map) {
|
||||
if (hasProperty(map, name)) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
|
||||
assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
assert.equal(reduceProperties(map, count => count + 1, 0), expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
for (const name of expectedKeys) {
|
||||
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`);
|
||||
assert.isTrue(name in map, `${caption} is expected to contain ${name}, actual keys: ${Object.keys(map)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,8 +116,8 @@ namespace ts {
|
||||
private getCanonicalFileName: (s: string) => string;
|
||||
private toPath: (f: string) => Path;
|
||||
private callbackQueue: TimeOutCallback[] = [];
|
||||
readonly watchedDirectories: Map<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {};
|
||||
readonly watchedFiles: Map<FileWatcherCallback[]> = {};
|
||||
readonly watchedDirectories = createMap<{ cb: DirectoryWatcherCallback, recursive: boolean }[]>();
|
||||
readonly watchedFiles = createMap<FileWatcherCallback[]>();
|
||||
|
||||
constructor(public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: FileOrFolder[]) {
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
@@ -208,7 +198,7 @@ namespace ts {
|
||||
|
||||
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
|
||||
const path = this.toPath(directoryName);
|
||||
const callbacks = lookUp(this.watchedDirectories, path) || (this.watchedDirectories[path] = []);
|
||||
const callbacks = this.watchedDirectories[path] || (this.watchedDirectories[path] = []);
|
||||
callbacks.push({ cb: callback, recursive });
|
||||
return {
|
||||
referenceCount: 0,
|
||||
@@ -229,7 +219,7 @@ namespace ts {
|
||||
|
||||
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
|
||||
const path = this.toPath(directoryName);
|
||||
const callbacks = lookUp(this.watchedDirectories, path);
|
||||
const callbacks = this.watchedDirectories[path];
|
||||
if (callbacks) {
|
||||
for (const callback of callbacks) {
|
||||
callback.cb(fileName);
|
||||
@@ -239,7 +229,7 @@ namespace ts {
|
||||
|
||||
triggerFileWatcherCallback(fileName: string, removed?: boolean): void {
|
||||
const path = this.toPath(fileName);
|
||||
const callbacks = lookUp(this.watchedFiles, path);
|
||||
const callbacks = this.watchedFiles[path];
|
||||
if (callbacks) {
|
||||
for (const callback of callbacks) {
|
||||
callback(path, removed);
|
||||
@@ -249,7 +239,7 @@ namespace ts {
|
||||
|
||||
watchFile(fileName: string, callback: FileWatcherCallback) {
|
||||
const path = this.toPath(fileName);
|
||||
const callbacks = lookUp(this.watchedFiles, path) || (this.watchedFiles[path] = []);
|
||||
const callbacks = this.watchedFiles[path] || (this.watchedFiles[path] = []);
|
||||
callbacks.push(callback);
|
||||
return {
|
||||
close: () => {
|
||||
@@ -596,7 +586,7 @@ namespace ts {
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
},
|
||||
},
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
@@ -623,7 +613,7 @@ namespace ts {
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
},
|
||||
},
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
@@ -635,5 +625,23 @@ namespace ts {
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkNumberOfInferredProjects(projectService, 0);
|
||||
});
|
||||
|
||||
it("should tolerate config file errors and still try to build a project", () => {
|
||||
const configFile: FileOrFolder = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"allowAnything": true
|
||||
},
|
||||
"someOtherProperty": {}
|
||||
}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, libFile, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkConfiguredProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
Vendored
+55
-15
@@ -126,6 +126,7 @@ interface KeyAlgorithm {
|
||||
}
|
||||
|
||||
interface KeyboardEventInit extends EventModifierInit {
|
||||
code?: string;
|
||||
key?: string;
|
||||
location?: number;
|
||||
repeat?: boolean;
|
||||
@@ -2288,7 +2289,7 @@ declare var DeviceRotationRate: {
|
||||
new(): DeviceRotationRate;
|
||||
}
|
||||
|
||||
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent {
|
||||
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent, ParentNode {
|
||||
/**
|
||||
* Sets or gets the URL for the current document.
|
||||
*/
|
||||
@@ -3351,7 +3352,7 @@ declare var Document: {
|
||||
new(): Document;
|
||||
}
|
||||
|
||||
interface DocumentFragment extends Node, NodeSelector {
|
||||
interface DocumentFragment extends Node, NodeSelector, ParentNode {
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -3420,7 +3421,7 @@ declare var EXT_texture_filter_anisotropic: {
|
||||
readonly TEXTURE_MAX_ANISOTROPY_EXT: number;
|
||||
}
|
||||
|
||||
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode {
|
||||
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode, ParentNode {
|
||||
readonly classList: DOMTokenList;
|
||||
className: string;
|
||||
readonly clientHeight: number;
|
||||
@@ -3675,6 +3676,16 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
|
||||
getElementsByClassName(classNames: string): NodeListOf<Element>;
|
||||
matches(selector: string): boolean;
|
||||
closest(selector: string): Element | null;
|
||||
scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;
|
||||
scroll(options?: ScrollToOptions): void;
|
||||
scroll(x: number, y: number): void;
|
||||
scrollTo(options?: ScrollToOptions): void;
|
||||
scrollTo(x: number, y: number): void;
|
||||
scrollBy(options?: ScrollToOptions): void;
|
||||
scrollBy(x: number, y: number): void;
|
||||
insertAdjacentElement(position: string, insertedElement: Element): Element | null;
|
||||
insertAdjacentHTML(where: string, html: string): void;
|
||||
insertAdjacentText(where: string, text: string): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -4446,7 +4457,7 @@ interface HTMLCanvasElement extends HTMLElement {
|
||||
* @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.
|
||||
*/
|
||||
toDataURL(type?: string, ...args: any[]): string;
|
||||
toBlob(callback: (result: Blob | null) => void, ... arguments: any[]): void;
|
||||
toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void;
|
||||
}
|
||||
|
||||
declare var HTMLCanvasElement: {
|
||||
@@ -4621,11 +4632,7 @@ interface HTMLElement extends Element {
|
||||
click(): void;
|
||||
dragDrop(): boolean;
|
||||
focus(): void;
|
||||
insertAdjacentElement(position: string, insertedElement: Element): Element;
|
||||
insertAdjacentHTML(where: string, html: string): void;
|
||||
insertAdjacentText(where: string, text: string): void;
|
||||
msGetInputContext(): MSInputMethodContext;
|
||||
scrollIntoView(top?: boolean): void;
|
||||
setActive(): void;
|
||||
addEventListener(type: "MSContentZoom", listener: (this: this, ev: UIEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -5890,6 +5897,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle {
|
||||
*/
|
||||
type: string;
|
||||
import?: Document;
|
||||
integrity: string;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -6178,7 +6186,7 @@ interface HTMLMediaElement extends HTMLElement {
|
||||
*/
|
||||
canPlayType(type: string): string;
|
||||
/**
|
||||
* Fires immediately after the client loads the object.
|
||||
* Resets the audio or video object and loads a new media resource.
|
||||
*/
|
||||
load(): void;
|
||||
/**
|
||||
@@ -6751,6 +6759,7 @@ interface HTMLScriptElement extends HTMLElement {
|
||||
* Sets or retrieves the MIME type for the associated scripting engine.
|
||||
*/
|
||||
type: string;
|
||||
integrity: string;
|
||||
}
|
||||
|
||||
declare var HTMLScriptElement: {
|
||||
@@ -7756,6 +7765,7 @@ interface KeyboardEvent extends UIEvent {
|
||||
readonly repeat: boolean;
|
||||
readonly shiftKey: boolean;
|
||||
readonly which: number;
|
||||
readonly code: string;
|
||||
getModifierState(keyArg: string): boolean;
|
||||
initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;
|
||||
readonly DOM_KEY_LOCATION_JOYSTICK: number;
|
||||
@@ -9128,6 +9138,7 @@ interface PerformanceTiming {
|
||||
readonly responseStart: number;
|
||||
readonly unloadEventEnd: number;
|
||||
readonly unloadEventStart: number;
|
||||
readonly secureConnectionStart: number;
|
||||
toJSON(): any;
|
||||
}
|
||||
|
||||
@@ -11405,8 +11416,8 @@ declare var StereoPannerNode: {
|
||||
interface Storage {
|
||||
readonly length: number;
|
||||
clear(): void;
|
||||
getItem(key: string): string;
|
||||
key(index: number): string;
|
||||
getItem(key: string): string | null;
|
||||
key(index: number): string | null;
|
||||
removeItem(key: string): void;
|
||||
setItem(key: string, data: string): void;
|
||||
[key: string]: any;
|
||||
@@ -12947,7 +12958,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
|
||||
onunload: (this: this, ev: Event) => any;
|
||||
onvolumechange: (this: this, ev: Event) => any;
|
||||
onwaiting: (this: this, ev: Event) => any;
|
||||
readonly opener: Window;
|
||||
opener: any;
|
||||
orientation: string | number;
|
||||
readonly outerHeight: number;
|
||||
readonly outerWidth: number;
|
||||
@@ -13002,6 +13013,9 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
|
||||
webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
|
||||
scroll(options?: ScrollToOptions): void;
|
||||
scrollTo(options?: ScrollToOptions): void;
|
||||
scrollBy(options?: ScrollToOptions): void;
|
||||
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -14029,6 +14043,20 @@ interface ProgressEventInit extends EventInit {
|
||||
total?: number;
|
||||
}
|
||||
|
||||
interface ScrollOptions {
|
||||
behavior?: ScrollBehavior;
|
||||
}
|
||||
|
||||
interface ScrollToOptions extends ScrollOptions {
|
||||
left?: number;
|
||||
top?: number;
|
||||
}
|
||||
|
||||
interface ScrollIntoViewOptions extends ScrollOptions {
|
||||
block?: ScrollLogicalPosition;
|
||||
inline?: ScrollLogicalPosition;
|
||||
}
|
||||
|
||||
interface ClipboardEventInit extends EventInit {
|
||||
data?: string;
|
||||
dataType?: string;
|
||||
@@ -14072,7 +14100,7 @@ interface EcdsaParams extends Algorithm {
|
||||
}
|
||||
|
||||
interface EcKeyGenParams extends Algorithm {
|
||||
typedCurve: string;
|
||||
namedCurve: string;
|
||||
}
|
||||
|
||||
interface EcKeyAlgorithm extends KeyAlgorithm {
|
||||
@@ -14208,6 +14236,13 @@ interface JsonWebKey {
|
||||
k?: string;
|
||||
}
|
||||
|
||||
interface ParentNode {
|
||||
readonly children: HTMLCollection;
|
||||
readonly firstElementChild: Element;
|
||||
readonly lastElementChild: Element;
|
||||
readonly childElementCount: number;
|
||||
}
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface ErrorEventHandler {
|
||||
@@ -14278,7 +14313,7 @@ declare var location: Location;
|
||||
declare var locationbar: BarProp;
|
||||
declare var menubar: BarProp;
|
||||
declare var msCredentials: MSCredentials;
|
||||
declare var name: string;
|
||||
declare const name: never;
|
||||
declare var navigator: Navigator;
|
||||
declare var offscreenBuffering: string | boolean;
|
||||
declare var onabort: (this: Window, ev: UIEvent) => any;
|
||||
@@ -14372,7 +14407,7 @@ declare var ontouchstart: (ev: TouchEvent) => any;
|
||||
declare var onunload: (this: Window, ev: Event) => any;
|
||||
declare var onvolumechange: (this: Window, ev: Event) => any;
|
||||
declare var onwaiting: (this: Window, ev: Event) => any;
|
||||
declare var opener: Window;
|
||||
declare var opener: any;
|
||||
declare var orientation: string | number;
|
||||
declare var outerHeight: number;
|
||||
declare var outerWidth: number;
|
||||
@@ -14425,6 +14460,9 @@ declare function webkitCancelAnimationFrame(handle: number): void;
|
||||
declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
|
||||
declare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
|
||||
declare function scroll(options?: ScrollToOptions): void;
|
||||
declare function scrollTo(options?: ScrollToOptions): void;
|
||||
declare function scrollBy(options?: ScrollToOptions): void;
|
||||
declare function toString(): string;
|
||||
declare function addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
declare function dispatchEvent(evt: Event): boolean;
|
||||
@@ -14580,6 +14618,8 @@ type MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload;
|
||||
type RTCIceGatherCandidate = RTCIceCandidate | RTCIceCandidateComplete;
|
||||
type RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport;
|
||||
type payloadtype = number;
|
||||
type ScrollBehavior = "auto" | "instant" | "smooth";
|
||||
type ScrollLogicalPosition = "start" | "center" | "end" | "nearest";
|
||||
type IDBValidKey = number | string | Date | IDBArrayKey;
|
||||
type BufferSource = ArrayBuffer | ArrayBufferView;
|
||||
type MouseWheelEvent = WheelEvent;
|
||||
Vendored
+28
@@ -68,6 +68,10 @@ interface ArrayConstructor {
|
||||
of<T>(...items: T[]): Array<T>;
|
||||
}
|
||||
|
||||
interface DateConstructor {
|
||||
new (value: Date): Date;
|
||||
}
|
||||
|
||||
interface Function {
|
||||
/**
|
||||
* Returns the name of the function. Function names are read-only and can not be changed.
|
||||
@@ -343,6 +347,30 @@ interface ObjectConstructor {
|
||||
defineProperty(o: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): any;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found,
|
||||
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T) => boolean, thisArg?: any): number;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
|
||||
|
||||
Vendored
+20
@@ -63,6 +63,26 @@ interface ArrayConstructor {
|
||||
from<T>(iterable: Iterable<T>): Array<T>;
|
||||
}
|
||||
|
||||
interface ReadonlyArray<T> {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<T>;
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIterator<[number, T]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
|
||||
interface IArguments {
|
||||
/** Iterator */
|
||||
[Symbol.iterator](): IterableIterator<any>;
|
||||
|
||||
Vendored
+6
-1
@@ -1006,7 +1006,12 @@ interface ReadonlyArray<T> {
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(...items: T[]): T[];
|
||||
concat(...items: T[][]): T[];
|
||||
/**
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(...items: (T | T[])[]): T[];
|
||||
/**
|
||||
* Adds all the elements of an array separated by the specified separator string.
|
||||
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
||||
|
||||
Vendored
+1
-1
@@ -1000,7 +1000,7 @@ interface EcdsaParams extends Algorithm {
|
||||
}
|
||||
|
||||
interface EcKeyGenParams extends Algorithm {
|
||||
typedCurve: string;
|
||||
namedCurve: string;
|
||||
}
|
||||
|
||||
interface EcKeyAlgorithm extends KeyAlgorithm {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ts.server {
|
||||
|
||||
export class SessionClient implements LanguageService {
|
||||
private sequence: number = 0;
|
||||
private lineMaps: ts.Map<number[]> = {};
|
||||
private lineMaps: ts.Map<number[]> = ts.createMap<number[]>();
|
||||
private messages: string[] = [];
|
||||
private lastRenameEntry: RenameEntry;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getLineMap(fileName: string): number[] {
|
||||
let lineMap = ts.lookUp(this.lineMaps, fileName);
|
||||
let lineMap = this.lineMaps[fileName];
|
||||
if (!lineMap) {
|
||||
const scriptSnapshot = this.host.getScriptSnapshot(fileName);
|
||||
lineMap = this.lineMaps[fileName] = ts.computeLineStarts(scriptSnapshot.getText(0, scriptSnapshot.getLength()));
|
||||
|
||||
+126
-107
@@ -130,15 +130,15 @@ namespace ts.server {
|
||||
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
|
||||
const currentResolutionsInFile = cache.get(path);
|
||||
|
||||
const newResolutions: Map<T> = {};
|
||||
const newResolutions = createMap<T>();
|
||||
const resolvedModules: R[] = [];
|
||||
const compilerOptions = this.getCompilationSettings();
|
||||
|
||||
for (const name of names) {
|
||||
// check if this is a duplicate entry in the list
|
||||
let resolution = lookUp(newResolutions, name);
|
||||
let resolution = newResolutions[name];
|
||||
if (!resolution) {
|
||||
const existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, name);
|
||||
const existingResolution = currentResolutionsInFile && currentResolutionsInFile[name];
|
||||
if (moduleResolutionIsValid(existingResolution)) {
|
||||
// ok, it is safe to use existing name resolution results
|
||||
resolution = existingResolution;
|
||||
@@ -378,7 +378,7 @@ namespace ts.server {
|
||||
export interface ProjectOptions {
|
||||
// these fields can be present in the project file
|
||||
files?: string[];
|
||||
wildcardDirectories?: ts.Map<ts.WatchDirectoryFlags>;
|
||||
wildcardDirectories?: ts.MapLike<ts.WatchDirectoryFlags>;
|
||||
compilerOptions?: ts.CompilerOptions;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ namespace ts.server {
|
||||
// Used to keep track of what directories are watched for this project
|
||||
directoriesWatchedForTsconfig: string[] = [];
|
||||
program: ts.Program;
|
||||
filenameToSourceFile: ts.Map<ts.SourceFile> = {};
|
||||
filenameToSourceFile = ts.createMap<ts.SourceFile>();
|
||||
updateGraphSeq = 0;
|
||||
/** Used for configured projects which may have multiple open roots */
|
||||
openRefCount = 0;
|
||||
@@ -504,7 +504,7 @@ namespace ts.server {
|
||||
return;
|
||||
}
|
||||
|
||||
this.filenameToSourceFile = {};
|
||||
this.filenameToSourceFile = createMap<SourceFile>();
|
||||
const sourceFiles = this.program.getSourceFiles();
|
||||
for (let i = 0, len = sourceFiles.length; i < len; i++) {
|
||||
const normFilename = ts.normalizePath(sourceFiles[i].fileName);
|
||||
@@ -563,7 +563,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
let strBuilder = "";
|
||||
ts.forEachValue(this.filenameToSourceFile,
|
||||
ts.forEachProperty(this.filenameToSourceFile,
|
||||
sourceFile => { strBuilder += sourceFile.fileName + "\n"; });
|
||||
return strBuilder;
|
||||
}
|
||||
@@ -603,8 +603,11 @@ namespace ts.server {
|
||||
return projects.length > 1 ? deduplicate(result, areEqual) : result;
|
||||
}
|
||||
|
||||
export type ProjectServiceEvent =
|
||||
{ eventName: "context", data: { project: Project, fileName: string } } | { eventName: "configFileDiag", data: { triggerFile?: string, configFileName: string, diagnostics: Diagnostic[] } }
|
||||
|
||||
export interface ProjectServiceEventHandler {
|
||||
(eventName: string, project: Project, fileName: string): void;
|
||||
(event: ProjectServiceEvent): void;
|
||||
}
|
||||
|
||||
export interface HostConfiguration {
|
||||
@@ -613,7 +616,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
export class ProjectService {
|
||||
filenameToScriptInfo: ts.Map<ScriptInfo> = {};
|
||||
filenameToScriptInfo = ts.createMap<ScriptInfo>();
|
||||
// open, non-configured root files
|
||||
openFileRoots: ScriptInfo[] = [];
|
||||
// projects built from openFileRoots
|
||||
@@ -625,12 +628,12 @@ namespace ts.server {
|
||||
// open files that are roots of a configured project
|
||||
openFileRootsConfigured: ScriptInfo[] = [];
|
||||
// a path to directory watcher map that detects added tsconfig files
|
||||
directoryWatchersForTsconfig: ts.Map<FileWatcher> = {};
|
||||
directoryWatchersForTsconfig = ts.createMap<FileWatcher>();
|
||||
// count of how many projects are using the directory watcher. If the
|
||||
// number becomes 0 for a watcher, then we should close it.
|
||||
directoryWatchersRefCount: ts.Map<number> = {};
|
||||
directoryWatchersRefCount = ts.createMap<number>();
|
||||
hostConfiguration: HostConfiguration;
|
||||
timerForDetectingProjectFileListChanges: Map<any> = {};
|
||||
timerForDetectingProjectFileListChanges = createMap<any>();
|
||||
|
||||
constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) {
|
||||
// ts.disableIncrementalParsing = true;
|
||||
@@ -699,7 +702,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
handleProjectFileListChanges(project: Project) {
|
||||
const { projectOptions } = this.configFileToProjectOptions(project.projectFilename);
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
this.reportConfigFileDiagnostics(project.projectFilename, errors);
|
||||
|
||||
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
|
||||
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
|
||||
@@ -717,18 +721,32 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile?: string) {
|
||||
if (diagnostics && diagnostics.length > 0) {
|
||||
this.eventHandler({
|
||||
eventName: "configFileDiag",
|
||||
data: { configFileName, diagnostics, triggerFile }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the callback function when a watched directory has an added tsconfig file.
|
||||
*/
|
||||
directoryWatchedForTsconfigChanged(fileName: string) {
|
||||
if (ts.getBaseFileName(fileName) != "tsconfig.json") {
|
||||
if (ts.getBaseFileName(fileName) !== "tsconfig.json") {
|
||||
this.log(fileName + " is not tsconfig.json");
|
||||
return;
|
||||
}
|
||||
|
||||
this.log("Detected newly added tsconfig file: " + fileName);
|
||||
|
||||
const { projectOptions } = this.configFileToProjectOptions(fileName);
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(fileName);
|
||||
this.reportConfigFileDiagnostics(fileName, errors);
|
||||
|
||||
if (!projectOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootFilesInTsconfig = projectOptions.files.map(f => this.getCanonicalFileName(f));
|
||||
const openFileRoots = this.openFileRoots.map(s => this.getCanonicalFileName(s.fileName));
|
||||
@@ -748,10 +766,13 @@ namespace ts.server {
|
||||
return ts.normalizePath(name);
|
||||
}
|
||||
|
||||
watchedProjectConfigFileChanged(project: Project) {
|
||||
watchedProjectConfigFileChanged(project: Project): void {
|
||||
this.log("Config file changed: " + project.projectFilename);
|
||||
this.updateConfiguredProject(project);
|
||||
const configFileErrors = this.updateConfiguredProject(project);
|
||||
this.updateProjectStructure();
|
||||
if (configFileErrors && configFileErrors.length > 0) {
|
||||
this.eventHandler({ eventName: "configFileDiag", data: { triggerFile: project.projectFilename, configFileName: project.projectFilename, diagnostics: configFileErrors } });
|
||||
}
|
||||
}
|
||||
|
||||
log(msg: string, type = "Err") {
|
||||
@@ -828,13 +849,13 @@ namespace ts.server {
|
||||
for (let j = 0, flen = this.openFileRoots.length; j < flen; j++) {
|
||||
const openFile = this.openFileRoots[j];
|
||||
if (this.eventHandler) {
|
||||
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
|
||||
this.eventHandler({ eventName: "context", data: { project: openFile.defaultProject, fileName: openFile.fileName } });
|
||||
}
|
||||
}
|
||||
for (let j = 0, flen = this.openFilesReferenced.length; j < flen; j++) {
|
||||
const openFile = this.openFilesReferenced[j];
|
||||
if (this.eventHandler) {
|
||||
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
|
||||
this.eventHandler({ eventName: "context", data: { project: openFile.defaultProject, fileName: openFile.fileName } });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -857,7 +878,7 @@ namespace ts.server {
|
||||
if (project.isConfiguredProject()) {
|
||||
project.projectFileWatcher.close();
|
||||
project.directoryWatcher.close();
|
||||
forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
|
||||
forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
|
||||
delete project.directoriesWatchedForWildcards;
|
||||
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
|
||||
}
|
||||
@@ -1124,7 +1145,7 @@ namespace ts.server {
|
||||
|
||||
getScriptInfo(filename: string) {
|
||||
filename = ts.normalizePath(filename);
|
||||
return ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
return this.filenameToScriptInfo[filename];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1133,7 +1154,7 @@ namespace ts.server {
|
||||
*/
|
||||
openFile(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
|
||||
let info = this.filenameToScriptInfo[fileName];
|
||||
if (!info) {
|
||||
let content: string;
|
||||
if (this.host.fileExists(fileName)) {
|
||||
@@ -1218,7 +1239,7 @@ namespace ts.server {
|
||||
const project = this.findConfiguredProjectByConfigFile(configFileName);
|
||||
if (!project) {
|
||||
const configResult = this.openConfigFile(configFileName, fileName);
|
||||
if (!configResult.success) {
|
||||
if (!configResult.project) {
|
||||
return { configFileName, configFileErrors: configResult.errors };
|
||||
}
|
||||
else {
|
||||
@@ -1234,11 +1255,12 @@ namespace ts.server {
|
||||
else {
|
||||
this.updateConfiguredProject(project);
|
||||
}
|
||||
return { configFileName };
|
||||
}
|
||||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
return configFileName ? { configFileName } : {};
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1246,7 +1268,7 @@ namespace ts.server {
|
||||
* @param filename is absolute pathname
|
||||
*/
|
||||
closeClientFile(filename: string) {
|
||||
const info = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const info = this.filenameToScriptInfo[filename];
|
||||
if (info) {
|
||||
this.closeOpenFile(info);
|
||||
info.isOpen = false;
|
||||
@@ -1255,14 +1277,14 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getProjectForFile(filename: string) {
|
||||
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const scriptInfo = this.filenameToScriptInfo[filename];
|
||||
if (scriptInfo) {
|
||||
return scriptInfo.defaultProject;
|
||||
}
|
||||
}
|
||||
|
||||
printProjectsForFile(filename: string) {
|
||||
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
|
||||
const scriptInfo = this.filenameToScriptInfo[filename];
|
||||
if (scriptInfo) {
|
||||
this.psLogger.startGroup();
|
||||
this.psLogger.info("Projects for " + filename);
|
||||
@@ -1328,34 +1350,31 @@ namespace ts.server {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
configFileToProjectOptions(configFilename: string): { succeeded: boolean, projectOptions?: ProjectOptions, errors?: Diagnostic[] } {
|
||||
configFileToProjectOptions(configFilename: string): { projectOptions?: ProjectOptions, errors: Diagnostic[] } {
|
||||
configFilename = ts.normalizePath(configFilename);
|
||||
let errors: Diagnostic[] = [];
|
||||
// file references will be relative to dirPath (or absolute)
|
||||
const dirPath = ts.getDirectoryPath(configFilename);
|
||||
const contents = this.host.readFile(configFilename);
|
||||
const rawConfig: { config?: ProjectOptions; error?: Diagnostic; } = ts.parseConfigFileTextToJson(configFilename, contents);
|
||||
if (rawConfig.error) {
|
||||
return { succeeded: false, errors: [rawConfig.error] };
|
||||
const { configJsonObject, diagnostics } = ts.parseAndReEmitConfigJSONFile(contents);
|
||||
errors = concatenate(errors, diagnostics);
|
||||
const parsedCommandLine = ts.parseJsonConfigFileContent(configJsonObject, this.host, dirPath, /*existingOptions*/ {}, configFilename);
|
||||
errors = concatenate(errors, parsedCommandLine.errors);
|
||||
Debug.assert(!!parsedCommandLine.fileNames);
|
||||
|
||||
if (parsedCommandLine.fileNames.length === 0) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename));
|
||||
return { errors };
|
||||
}
|
||||
else {
|
||||
const parsedCommandLine = ts.parseJsonConfigFileContent(rawConfig.config, this.host, dirPath, /*existingOptions*/ {}, configFilename);
|
||||
Debug.assert(!!parsedCommandLine.fileNames);
|
||||
|
||||
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
|
||||
return { succeeded: false, errors: parsedCommandLine.errors };
|
||||
}
|
||||
else if (parsedCommandLine.fileNames.length === 0) {
|
||||
const error = createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename);
|
||||
return { succeeded: false, errors: [error] };
|
||||
}
|
||||
else {
|
||||
const projectOptions: ProjectOptions = {
|
||||
files: parsedCommandLine.fileNames,
|
||||
wildcardDirectories: parsedCommandLine.wildcardDirectories,
|
||||
compilerOptions: parsedCommandLine.options,
|
||||
};
|
||||
return { succeeded: true, projectOptions };
|
||||
}
|
||||
// if the project has some files, we can continue with the parsed options and tolerate
|
||||
// errors in the parsedCommandLine
|
||||
const projectOptions: ProjectOptions = {
|
||||
files: parsedCommandLine.fileNames,
|
||||
wildcardDirectories: parsedCommandLine.wildcardDirectories,
|
||||
compilerOptions: parsedCommandLine.options,
|
||||
};
|
||||
return { projectOptions, errors };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1377,64 +1396,63 @@ namespace ts.server {
|
||||
return false;
|
||||
}
|
||||
|
||||
openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } {
|
||||
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename);
|
||||
if (!succeeded) {
|
||||
return { success: false, errors };
|
||||
openConfigFile(configFilename: string, clientFileName?: string): { project?: Project, errors: Diagnostic[] } {
|
||||
const parseConfigFileResult = this.configFileToProjectOptions(configFilename);
|
||||
let errors = parseConfigFileResult.errors;
|
||||
if (!parseConfigFileResult.projectOptions) {
|
||||
return { errors };
|
||||
}
|
||||
else {
|
||||
if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
|
||||
const projectOptions = parseConfigFileResult.projectOptions;
|
||||
if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
|
||||
|
||||
// for configured projects with languageService disabled, we only watch its config file,
|
||||
// do not care about the directory changes in the folder.
|
||||
project.projectFileWatcher = this.host.watchFile(
|
||||
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
_ => this.watchedProjectConfigFileChanged(project));
|
||||
return { success: true, project };
|
||||
}
|
||||
// for configured projects with languageService disabled, we only watch its config file,
|
||||
// do not care about the directory changes in the folder.
|
||||
project.projectFileWatcher = this.host.watchFile(
|
||||
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
_ => this.watchedProjectConfigFileChanged(project));
|
||||
return { project, errors };
|
||||
}
|
||||
}
|
||||
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
for (const rootFilename of projectOptions.files) {
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else {
|
||||
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename));
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
|
||||
|
||||
const configDirectoryPath = ts.getDirectoryPath(configFilename);
|
||||
|
||||
this.log("Add recursive watcher for: " + configDirectoryPath);
|
||||
project.directoryWatcher = this.host.watchDirectory(
|
||||
configDirectoryPath,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
|
||||
project.directoriesWatchedForWildcards = reduceProperties(createMap(projectOptions.wildcardDirectories), (watchers, flag, directory) => {
|
||||
if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
|
||||
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
|
||||
this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);
|
||||
watchers[directory] = this.host.watchDirectory(
|
||||
directory,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
recursive
|
||||
);
|
||||
}
|
||||
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
let errors: Diagnostic[];
|
||||
for (const rootFilename of projectOptions.files) {
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else {
|
||||
(errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename));
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
|
||||
return watchers;
|
||||
}, <Map<FileWatcher>>{});
|
||||
|
||||
const configDirectoryPath = ts.getDirectoryPath(configFilename);
|
||||
|
||||
this.log("Add recursive watcher for: " + configDirectoryPath);
|
||||
project.directoryWatcher = this.host.watchDirectory(
|
||||
configDirectoryPath,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
|
||||
project.directoriesWatchedForWildcards = reduceProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
|
||||
if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
|
||||
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
|
||||
this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);
|
||||
watchers[directory] = this.host.watchDirectory(
|
||||
directory,
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
recursive
|
||||
);
|
||||
}
|
||||
|
||||
return watchers;
|
||||
}, <Map<FileWatcher>>{});
|
||||
|
||||
return { success: true, project: project, errors };
|
||||
}
|
||||
return { project: project, errors };
|
||||
}
|
||||
|
||||
updateConfiguredProject(project: Project): Diagnostic[] {
|
||||
@@ -1443,15 +1461,15 @@ namespace ts.server {
|
||||
this.removeProject(project);
|
||||
}
|
||||
else {
|
||||
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
if (!succeeded) {
|
||||
const { projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename);
|
||||
if (!projectOptions) {
|
||||
return errors;
|
||||
}
|
||||
else {
|
||||
if (projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit && this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
project.setProjectOptions(projectOptions);
|
||||
if (project.languageServiceDiabled) {
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
project.disableLanguageService();
|
||||
@@ -1459,7 +1477,7 @@ namespace ts.server {
|
||||
project.directoryWatcher.close();
|
||||
project.directoryWatcher = undefined;
|
||||
}
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (project.languageServiceDiabled) {
|
||||
@@ -1478,7 +1496,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
project.finishGraph();
|
||||
return;
|
||||
return errors;
|
||||
}
|
||||
|
||||
// if the project is too large, the root files might not have been all loaded if the total
|
||||
@@ -1524,6 +1542,7 @@ namespace ts.server {
|
||||
project.setProjectOptions(projectOptions);
|
||||
project.finishGraph();
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-10
@@ -153,16 +153,22 @@ namespace ts.server {
|
||||
private logger: Logger
|
||||
) {
|
||||
this.projectService =
|
||||
new ProjectService(host, logger, (eventName, project, fileName) => {
|
||||
this.handleEvent(eventName, project, fileName);
|
||||
new ProjectService(host, logger, event => {
|
||||
this.handleEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
private handleEvent(eventName: string, project: Project, fileName: string) {
|
||||
if (eventName == "context") {
|
||||
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
|
||||
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
|
||||
(n) => n === this.changeSeq, 100);
|
||||
private handleEvent(event: ProjectServiceEvent) {
|
||||
switch (event.eventName) {
|
||||
case "context":
|
||||
const { project, fileName } = event.data;
|
||||
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
|
||||
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
|
||||
(n) => n === this.changeSeq, 100);
|
||||
break;
|
||||
case "configFileDiag":
|
||||
const { triggerFile, configFileName, diagnostics } = event.data;
|
||||
this.configFileDiagnosticEvent(triggerFile, configFileName, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1061,7 +1067,7 @@ namespace ts.server {
|
||||
return { response, responseRequired: true };
|
||||
}
|
||||
|
||||
private handlers: Map<(request: protocol.Request) => { response?: any, responseRequired?: boolean }> = {
|
||||
private handlers = createMap<(request: protocol.Request) => { response?: any, responseRequired?: boolean }>({
|
||||
[CommandNames.Exit]: () => {
|
||||
this.exit();
|
||||
return { responseRequired: false };
|
||||
@@ -1198,9 +1204,10 @@ namespace ts.server {
|
||||
this.reloadProjects();
|
||||
return { responseRequired: false };
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => { response?: any, responseRequired: boolean }) {
|
||||
if (this.handlers[command]) {
|
||||
if (command in this.handlers) {
|
||||
throw new Error(`Protocol handler already exists for command "${command}"`);
|
||||
}
|
||||
this.handlers[command] = handler;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
"types": []
|
||||
},
|
||||
"files": [
|
||||
"../services/shims.ts",
|
||||
"../services/utilities.ts",
|
||||
"editorServices.ts",
|
||||
"protocol.d.ts",
|
||||
"session.ts"
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ts.JsTyping {
|
||||
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
|
||||
|
||||
// A typing name to typing file path mapping
|
||||
const inferredTypings: Map<string> = {};
|
||||
const inferredTypings = createMap<string>();
|
||||
|
||||
if (!typingOptions || !typingOptions.enableAutoDiscovery) {
|
||||
return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
|
||||
@@ -58,12 +58,7 @@ namespace ts.JsTyping {
|
||||
|
||||
if (!safeList) {
|
||||
const result = readConfigFile(safeListPath, (path: string) => host.readFile(path));
|
||||
if (result.config) {
|
||||
safeList = result.config;
|
||||
}
|
||||
else {
|
||||
safeList = {};
|
||||
};
|
||||
safeList = createMap<string>(result.config);
|
||||
}
|
||||
|
||||
const filesToWatch: string[] = [];
|
||||
@@ -93,7 +88,7 @@ namespace ts.JsTyping {
|
||||
|
||||
// Add the cached typing locations for inferred typings that are already installed
|
||||
for (const name in packageNameToTypingLocation) {
|
||||
if (hasProperty(inferredTypings, name) && !inferredTypings[name]) {
|
||||
if (name in inferredTypings && !inferredTypings[name]) {
|
||||
inferredTypings[name] = packageNameToTypingLocation[name];
|
||||
}
|
||||
}
|
||||
@@ -124,7 +119,7 @@ namespace ts.JsTyping {
|
||||
}
|
||||
|
||||
for (const typing of typingNames) {
|
||||
if (!hasProperty(inferredTypings, typing)) {
|
||||
if (!(typing in inferredTypings)) {
|
||||
inferredTypings[typing] = undefined;
|
||||
}
|
||||
}
|
||||
@@ -139,16 +134,16 @@ namespace ts.JsTyping {
|
||||
const jsonConfig: PackageJson = result.config;
|
||||
filesToWatch.push(jsonPath);
|
||||
if (jsonConfig.dependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.dependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.dependencies));
|
||||
}
|
||||
if (jsonConfig.devDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.devDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.devDependencies));
|
||||
}
|
||||
if (jsonConfig.optionalDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.optionalDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.optionalDependencies));
|
||||
}
|
||||
if (jsonConfig.peerDependencies) {
|
||||
mergeTypings(getKeys(jsonConfig.peerDependencies));
|
||||
mergeTypings(getOwnKeys(jsonConfig.peerDependencies));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +162,7 @@ namespace ts.JsTyping {
|
||||
mergeTypings(cleanedTypingNames);
|
||||
}
|
||||
else {
|
||||
mergeTypings(filter(cleanedTypingNames, f => hasProperty(safeList, f)));
|
||||
mergeTypings(filter(cleanedTypingNames, f => f in safeList));
|
||||
}
|
||||
|
||||
const hasJsxFile = forEach(fileNames, f => scriptKindIs(f, /*LanguageServiceHost*/ undefined, ScriptKind.JSX));
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ts.NavigateTo {
|
||||
|
||||
const nameToDeclarations = sourceFile.getNamedDeclarations();
|
||||
for (const name in nameToDeclarations) {
|
||||
const declarations = getProperty(nameToDeclarations, name);
|
||||
const declarations = nameToDeclarations[name];
|
||||
if (declarations) {
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// last portion of the (possibly) dotted name they're searching for.
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace ts.NavigationBar {
|
||||
|
||||
/** Merge declarations of the same kind. */
|
||||
function mergeChildren(children: NavigationBarNode[]): void {
|
||||
const nameToItems: Map<NavigationBarNode | NavigationBarNode[]> = {};
|
||||
const nameToItems = createMap<NavigationBarNode | NavigationBarNode[]>();
|
||||
filterMutate(children, child => {
|
||||
const decl = <Declaration>child.node;
|
||||
const name = decl.name && nodeText(decl.name);
|
||||
@@ -243,7 +243,7 @@ namespace ts.NavigationBar {
|
||||
return true;
|
||||
}
|
||||
|
||||
const itemsWithSameName = getProperty(nameToItems, name);
|
||||
const itemsWithSameName = nameToItems[name];
|
||||
if (!itemsWithSameName) {
|
||||
nameToItems[name] = child;
|
||||
return true;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ts {
|
||||
// we see the name of a module that is used everywhere, or the name of an overload). As
|
||||
// such, we cache the information we compute about the candidate for the life of this
|
||||
// pattern matcher so we don't have to compute it multiple times.
|
||||
const stringToWordSpans: Map<TextSpan[]> = {};
|
||||
const stringToWordSpans = createMap<TextSpan[]>();
|
||||
|
||||
pattern = pattern.trim();
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWordSpans(word: string): TextSpan[] {
|
||||
if (!hasProperty(stringToWordSpans, word)) {
|
||||
if (!(word in stringToWordSpans)) {
|
||||
stringToWordSpans[word] = breakIntoWordSpans(word);
|
||||
}
|
||||
|
||||
|
||||
+65
-30
@@ -304,6 +304,10 @@ namespace ts {
|
||||
processNode(jsDocComment);
|
||||
}
|
||||
}
|
||||
// For syntactic classifications, all trivia are classcified together, including jsdoc comments.
|
||||
// For that to work, the jsdoc comments should still be the leading trivia of the first child.
|
||||
// Restoring the scanner position ensures that.
|
||||
pos = this.pos;
|
||||
forEachChild(this, processNode, processNodes);
|
||||
if (pos < this.end) {
|
||||
this.addSyntheticNodes(children, pos, this.end);
|
||||
@@ -980,7 +984,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
private computeNamedDeclarations(): Map<Declaration[]> {
|
||||
const result: Map<Declaration[]> = {};
|
||||
const result = createMap<Declaration[]>();
|
||||
|
||||
forEachChild(this, visit);
|
||||
|
||||
@@ -995,7 +999,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDeclarations(name: string) {
|
||||
return getProperty(result, name) || (result[name] = []);
|
||||
return result[name] || (result[name] = []);
|
||||
}
|
||||
|
||||
function getDeclarationName(declaration: Declaration) {
|
||||
@@ -2030,7 +2034,7 @@ namespace ts {
|
||||
fileName?: string;
|
||||
reportDiagnostics?: boolean;
|
||||
moduleName?: string;
|
||||
renamedDependencies?: Map<string>;
|
||||
renamedDependencies?: MapLike<string>;
|
||||
}
|
||||
|
||||
export interface TranspileOutput {
|
||||
@@ -2047,7 +2051,7 @@ namespace ts {
|
||||
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
|
||||
// Lazily create this value to fix module loading errors.
|
||||
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
|
||||
typeof o.type === "object" && !forEachValue(<Map<any>>o.type, v => typeof v !== "number"));
|
||||
typeof o.type === "object" && !forEachProperty(o.type, v => typeof v !== "number"));
|
||||
|
||||
options = clone(options);
|
||||
|
||||
@@ -2063,7 +2067,7 @@ namespace ts {
|
||||
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
|
||||
}
|
||||
else {
|
||||
if (!forEachValue(opt.type, v => v === value)) {
|
||||
if (!forEachProperty(opt.type, v => v === value)) {
|
||||
// Supplied value isn't a valid enum value.
|
||||
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
|
||||
}
|
||||
@@ -2122,7 +2126,9 @@ namespace ts {
|
||||
sourceFile.moduleName = transpileOptions.moduleName;
|
||||
}
|
||||
|
||||
sourceFile.renamedDependencies = transpileOptions.renamedDependencies;
|
||||
if (transpileOptions.renamedDependencies) {
|
||||
sourceFile.renamedDependencies = createMap(transpileOptions.renamedDependencies);
|
||||
}
|
||||
|
||||
const newLine = getNewLineCharacter(options);
|
||||
|
||||
@@ -2248,7 +2254,7 @@ namespace ts {
|
||||
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
|
||||
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
|
||||
// for those settings.
|
||||
const buckets: Map<FileMap<DocumentRegistryEntry>> = {};
|
||||
const buckets = createMap<FileMap<DocumentRegistryEntry>>();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
@@ -2256,7 +2262,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
|
||||
let bucket = lookUp(buckets, key);
|
||||
let bucket = buckets[key];
|
||||
if (!bucket && createIfMissing) {
|
||||
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
|
||||
}
|
||||
@@ -2265,7 +2271,7 @@ namespace ts {
|
||||
|
||||
function reportStats() {
|
||||
const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => {
|
||||
const entries = lookUp(buckets, name);
|
||||
const entries = buckets[name];
|
||||
const sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
entries.forEachValue((key, entry) => {
|
||||
sourceFiles.push({
|
||||
@@ -3104,7 +3110,7 @@ namespace ts {
|
||||
oldSettings.allowJs !== newSettings.allowJs ||
|
||||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit ||
|
||||
oldSettings.baseUrl !== newSettings.baseUrl ||
|
||||
!mapIsEqualTo(oldSettings.paths, newSettings.paths));
|
||||
!equalOwnProperties(oldSettings.paths, newSettings.paths));
|
||||
|
||||
// Now create a new compiler
|
||||
const compilerHost: CompilerHost = {
|
||||
@@ -3119,7 +3125,6 @@ namespace ts {
|
||||
getCurrentDirectory: () => currentDirectory,
|
||||
fileExists: (fileName): boolean => {
|
||||
// stub missing host functionality
|
||||
Debug.assert(!host.resolveModuleNames || !host.resolveTypeReferenceDirectives);
|
||||
return hostCache.getOrCreateEntry(fileName) !== undefined;
|
||||
},
|
||||
readFile: (fileName): string => {
|
||||
@@ -3793,7 +3798,11 @@ namespace ts {
|
||||
// other than those within the declared type.
|
||||
isNewIdentifierLocation = true;
|
||||
|
||||
// If the object literal is being assigned to something of type 'null | { hello: string }',
|
||||
// it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible.
|
||||
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
|
||||
typeForObject = typeForObject && typeForObject.getNonNullableType();
|
||||
|
||||
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
||||
}
|
||||
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
@@ -3805,7 +3814,7 @@ namespace ts {
|
||||
// We don't want to complete using the type acquired by the shape
|
||||
// of the binding pattern; we are only interested in types acquired
|
||||
// through type declaration or inference.
|
||||
// Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed -
|
||||
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
|
||||
// type of parameter will flow in from the contextual type of the function
|
||||
let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type);
|
||||
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
|
||||
@@ -4107,7 +4116,7 @@ namespace ts {
|
||||
* do not occur at the current position and have not otherwise been typed.
|
||||
*/
|
||||
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] {
|
||||
const existingImportsOrExports: Map<boolean> = {};
|
||||
const existingImportsOrExports = createMap<boolean>();
|
||||
|
||||
for (const element of namedImportsOrExports) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
@@ -4119,11 +4128,11 @@ namespace ts {
|
||||
existingImportsOrExports[name.text] = true;
|
||||
}
|
||||
|
||||
if (isEmpty(existingImportsOrExports)) {
|
||||
if (!someProperties(existingImportsOrExports)) {
|
||||
return filter(exportsOfModule, e => e.name !== "default");
|
||||
}
|
||||
|
||||
return filter(exportsOfModule, e => e.name !== "default" && !lookUp(existingImportsOrExports, e.name));
|
||||
return filter(exportsOfModule, e => e.name !== "default" && !existingImportsOrExports[e.name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4137,7 +4146,7 @@ namespace ts {
|
||||
return contextualMemberSymbols;
|
||||
}
|
||||
|
||||
const existingMemberNames: Map<boolean> = {};
|
||||
const existingMemberNames = createMap<boolean>();
|
||||
for (const m of existingMembers) {
|
||||
// Ignore omitted expressions for missing members
|
||||
if (m.kind !== SyntaxKind.PropertyAssignment &&
|
||||
@@ -4170,7 +4179,7 @@ namespace ts {
|
||||
existingMemberNames[existingName] = true;
|
||||
}
|
||||
|
||||
return filter(contextualMemberSymbols, m => !lookUp(existingMemberNames, m.name));
|
||||
return filter(contextualMemberSymbols, m => !existingMemberNames[m.name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4180,7 +4189,7 @@ namespace ts {
|
||||
* do not occur at the current position and have not otherwise been typed.
|
||||
*/
|
||||
function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>): Symbol[] {
|
||||
const seenNames: Map<boolean> = {};
|
||||
const seenNames = createMap<boolean>();
|
||||
for (const attr of attributes) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
if (attr.getStart() <= position && position <= attr.getEnd()) {
|
||||
@@ -4192,7 +4201,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return filter(symbols, a => !lookUp(seenNames, a.name));
|
||||
return filter(symbols, a => !seenNames[a.name]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4252,7 +4261,7 @@ namespace ts {
|
||||
addRange(entries, keywordCompletions);
|
||||
}
|
||||
|
||||
return { isMemberCompletion, isNewIdentifierLocation, entries };
|
||||
return { isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation || isSourceFileJavaScript(sourceFile), entries };
|
||||
|
||||
function getJavaScriptCompletionEntries(sourceFile: SourceFile, position: number, uniqueNames: Map<string>): CompletionEntry[] {
|
||||
const entries: CompletionEntry[] = [];
|
||||
@@ -4322,13 +4331,13 @@ namespace ts {
|
||||
|
||||
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
|
||||
const start = timestamp();
|
||||
const uniqueNames: Map<string> = {};
|
||||
const uniqueNames = createMap<string>();
|
||||
if (symbols) {
|
||||
for (const symbol of symbols) {
|
||||
const entry = createCompletionEntry(symbol, location, performCharacterChecks);
|
||||
if (entry) {
|
||||
const id = escapeIdentifier(entry.name);
|
||||
if (!lookUp(uniqueNames, id)) {
|
||||
if (!uniqueNames[id]) {
|
||||
entries.push(entry);
|
||||
uniqueNames[id] = id;
|
||||
}
|
||||
@@ -4917,6 +4926,28 @@ namespace ts {
|
||||
|
||||
if (!documentation) {
|
||||
documentation = symbol.getDocumentationComment();
|
||||
if (documentation.length === 0 && symbol.flags & SymbolFlags.Property) {
|
||||
// For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo`
|
||||
// there documentation comments might be attached to the right hand side symbol of their declarations.
|
||||
// The pattern of such special property access is that the parent symbol is the symbol of the file.
|
||||
if (symbol.parent && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rhsSymbol = program.getTypeChecker().getSymbolAtLocation((<BinaryExpression>declaration.parent).right);
|
||||
if (!rhsSymbol) {
|
||||
continue;
|
||||
}
|
||||
|
||||
documentation = rhsSymbol.getDocumentationComment();
|
||||
if (documentation.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { displayParts, documentation, symbolKind };
|
||||
@@ -5156,7 +5187,7 @@ namespace ts {
|
||||
// Type reference directives
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const referenceFile = lookUp(program.getResolvedTypeReferenceDirectives(), typeReferenceDirective.fileName);
|
||||
const referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName];
|
||||
if (referenceFile && referenceFile.resolvedFileName) {
|
||||
return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
|
||||
}
|
||||
@@ -5323,12 +5354,12 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const fileNameToDocumentHighlights: Map<DocumentHighlights> = {};
|
||||
const fileNameToDocumentHighlights = createMap<DocumentHighlights>();
|
||||
const result: DocumentHighlights[] = [];
|
||||
for (const referencedSymbol of referencedSymbols) {
|
||||
for (const referenceEntry of referencedSymbol.references) {
|
||||
const fileName = referenceEntry.fileName;
|
||||
let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName);
|
||||
let documentHighlights = fileNameToDocumentHighlights[fileName];
|
||||
if (!documentHighlights) {
|
||||
documentHighlights = { fileName, highlightSpans: [] };
|
||||
|
||||
@@ -6073,7 +6104,7 @@ namespace ts {
|
||||
|
||||
const nameTable = getNameTable(sourceFile);
|
||||
|
||||
if (lookUp(nameTable, internedName) !== undefined) {
|
||||
if (nameTable[internedName] !== undefined) {
|
||||
result = result || [];
|
||||
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
|
||||
}
|
||||
@@ -6718,7 +6749,7 @@ namespace ts {
|
||||
|
||||
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {});
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6750,7 +6781,7 @@ namespace ts {
|
||||
// the function will add any found symbol of the property-name, then its sub-routine will call
|
||||
// getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already
|
||||
// visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol.
|
||||
if (hasProperty(previousIterationSymbolsCache, symbol.name)) {
|
||||
if (symbol.name in previousIterationSymbolsCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6839,7 +6870,7 @@ namespace ts {
|
||||
// see if any is in the list
|
||||
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
const result: Symbol[] = [];
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ {});
|
||||
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap<Symbol>());
|
||||
return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
|
||||
}
|
||||
|
||||
@@ -7574,6 +7605,10 @@ namespace ts {
|
||||
* False will mean that node is not classified and traverse routine should recurse into node contents.
|
||||
*/
|
||||
function tryClassifyNode(node: Node): boolean {
|
||||
if (isJSDocTag(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nodeIsMissing(node)) {
|
||||
return true;
|
||||
}
|
||||
@@ -8323,7 +8358,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function initializeNameTable(sourceFile: SourceFile): void {
|
||||
const nameTable: Map<number> = {};
|
||||
const nameTable = createMap<number>();
|
||||
|
||||
walk(sourceFile);
|
||||
sourceFile.nameTable = nameTable;
|
||||
|
||||
@@ -311,9 +311,9 @@ namespace ts {
|
||||
// 'in' does not have this effect.
|
||||
if ("getModuleResolutionsForFile" in this.shimHost) {
|
||||
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
|
||||
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
return map(moduleNames, name => {
|
||||
const result = lookUp(resolutionsInFile, name);
|
||||
const result = getProperty(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result } : undefined;
|
||||
});
|
||||
};
|
||||
@@ -323,8 +323,8 @@ namespace ts {
|
||||
}
|
||||
if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) {
|
||||
this.resolveTypeReferenceDirectives = (typeDirectiveNames: string[], containingFile: string) => {
|
||||
const typeDirectivesForFile = <Map<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
|
||||
return map(typeDirectiveNames, name => lookUp(typeDirectivesForFile, name));
|
||||
const typeDirectivesForFile = <MapLike<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
|
||||
return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1203,6 +1203,6 @@ namespace TypeScript.Services {
|
||||
// TODO: it should be moved into a namespace though.
|
||||
|
||||
/* @internal */
|
||||
const toolsVersion = "1.9";
|
||||
const toolsVersion = "2.1";
|
||||
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace ts.SignatureHelp {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
const nameToDeclarations = sourceFile.getNamedDeclarations();
|
||||
const declarations = getProperty(nameToDeclarations, name.text);
|
||||
const declarations = nameToDeclarations[name.text];
|
||||
|
||||
if (declarations) {
|
||||
for (const declaration of declarations) {
|
||||
|
||||
@@ -925,4 +925,24 @@ namespace ts {
|
||||
}
|
||||
return ensureScriptKind(fileName, scriptKind);
|
||||
}
|
||||
|
||||
export function parseAndReEmitConfigJSONFile(content: string) {
|
||||
const options: TranspileOptions = {
|
||||
fileName: "config.js",
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES6
|
||||
},
|
||||
reportDiagnostics: true
|
||||
};
|
||||
const { outputText, diagnostics } = ts.transpileModule("(" + content + ")", options);
|
||||
// Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1
|
||||
// also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these
|
||||
// as well
|
||||
const trimmedOutput = outputText.trim();
|
||||
const configJsonObject = JSON.parse(trimmedOutput.substring(1, trimmedOutput.length - 2));
|
||||
for (const diagnostic of diagnostics) {
|
||||
diagnostic.start = diagnostic.start - 1;
|
||||
}
|
||||
return { configJsonObject, diagnostics };
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ declare var path: any;
|
||||
import * as ts from "typescript";
|
||||
|
||||
function watch(rootFileNames: string[], options: ts.CompilerOptions) {
|
||||
const files: ts.Map<{ version: number }> = {};
|
||||
const files: ts.MapLike<{ version: number }> = {};
|
||||
|
||||
// initialize the list of files
|
||||
rootFileNames.forEach(fileName => {
|
||||
|
||||
+2
-9
@@ -1,12 +1,5 @@
|
||||
{
|
||||
"kind": "JSDocTypeReference",
|
||||
"kind": "NullKeyword",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 1,
|
||||
"end": 5,
|
||||
"originalKeywordKind": "NullKeyword",
|
||||
"text": "null"
|
||||
}
|
||||
"end": 5
|
||||
}
|
||||
+2
-9
@@ -1,12 +1,5 @@
|
||||
{
|
||||
"kind": "JSDocTypeReference",
|
||||
"kind": "UndefinedKeyword",
|
||||
"pos": 1,
|
||||
"end": 10,
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 1,
|
||||
"end": 10,
|
||||
"originalKeywordKind": "UndefinedKeyword",
|
||||
"text": "undefined"
|
||||
}
|
||||
"end": 10
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts(1,16): error TS7005: Variable '"jquery"' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts (1 errors) ====
|
||||
declare module "jquery";
|
||||
~~~~~~~~
|
||||
!!! error TS7005: Variable '"jquery"' implicitly has an 'any' type.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
//// [ambientShorthand_isImplicitAny.ts]
|
||||
declare module "jquery";
|
||||
|
||||
|
||||
//// [ambientShorthand_isImplicitAny.js]
|
||||
@@ -1,6 +1,7 @@
|
||||
tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts(9,7): error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtyping.ts (1 errors) ====
|
||||
@@ -17,6 +18,7 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSubtypi
|
||||
!!! error TS2415: Class 'Derived<U>' incorrectly extends base class 'Base<string>'.
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: String;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSuperty
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'U' is not assignable to type 'string'.
|
||||
Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSupertype.ts (1 errors) ====
|
||||
@@ -19,5 +20,6 @@ tests/cases/conformance/types/typeRelationships/apparentType/apparentTypeSuperty
|
||||
!!! error TS2415: Types of property 'x' are incompatible.
|
||||
!!! error TS2415: Type 'U' is not assignable to type 'string'.
|
||||
!!! error TS2415: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2415: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x: U;
|
||||
}
|
||||
@@ -39,8 +39,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'.
|
||||
Property 'length' is missing in type '{ 0: string; 1: number; }'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(29,5): error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
@@ -136,8 +135,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error
|
||||
var n1: [number, string] = x;
|
||||
~~
|
||||
!!! error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
var n2: [number, string] = y;
|
||||
~~
|
||||
!!! error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(10,5): error TS2322: Type 'undefined[]' is not assignable to type '[any, any, any]'.
|
||||
Property '0' is missing in type 'undefined[]'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,5): error TS2322: Type '[string, number, boolean]' is not assignable to type '[boolean, string, number]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'boolean'.
|
||||
Type 'string' is not assignable to type 'boolean'.
|
||||
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'.
|
||||
Types of property 'pop' are incompatible.
|
||||
Type '() => string | number | boolean' is not assignable to type '() => number'.
|
||||
@@ -18,6 +17,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
Types of parameters 'items' and 'items' are incompatible.
|
||||
Type 'Number' is not assignable to type 'string | number'.
|
||||
Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts (6 errors) ====
|
||||
@@ -37,8 +37,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
var a1: [boolean, string, number] = ["string", 1, true]; // Error
|
||||
~~
|
||||
!!! error TS2322: Type '[string, number, boolean]' is not assignable to type '[boolean, string, number]'.
|
||||
!!! error TS2322: Types of property '0' are incompatible.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
|
||||
// The resulting type an array literal expression is determined as follows:
|
||||
// - If the array literal contains no spread elements and is an array assignment pattern in a destructuring assignment (section 4.17.1),
|
||||
@@ -81,4 +80,5 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
|
||||
!!! error TS2322: Types of parameters 'items' and 'items' are incompatible.
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'string | number'.
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
Property 'b' is missing in type 'A'.
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts (2 errors) ====
|
||||
class A { a }
|
||||
class B extends A { b }
|
||||
class C<T> extends Array<T> { c }
|
||||
declare var ara: A[];
|
||||
declare var arb: B[];
|
||||
declare var cra: C<A>;
|
||||
declare var crb: C<B>;
|
||||
declare var rra: ReadonlyArray<A>;
|
||||
declare var rrb: ReadonlyArray<B>;
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
~~~
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
!!! error TS2322: Property 'b' is missing in type 'A'.
|
||||
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
~~~
|
||||
!!! error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//// [arrayOfSubtypeIsAssignableToReadonlyArray.ts]
|
||||
class A { a }
|
||||
class B extends A { b }
|
||||
class C<T> extends Array<T> { c }
|
||||
declare var ara: A[];
|
||||
declare var arb: B[];
|
||||
declare var cra: C<A>;
|
||||
declare var crb: C<B>;
|
||||
declare var rra: ReadonlyArray<A>;
|
||||
declare var rrb: ReadonlyArray<B>;
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
|
||||
|
||||
//// [arrayOfSubtypeIsAssignableToReadonlyArray.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = (function (_super) {
|
||||
__extends(B, _super);
|
||||
function B() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return B;
|
||||
}(A));
|
||||
var C = (function (_super) {
|
||||
__extends(C, _super);
|
||||
function C() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return C;
|
||||
}(Array));
|
||||
rra = ara;
|
||||
rrb = arb; // OK, Array<B> is assignable to ReadonlyArray<A>
|
||||
rra = arb;
|
||||
rrb = ara; // error: 'A' is not assignable to 'B'
|
||||
rra = cra;
|
||||
rra = crb; // OK, C<B> is assignable to ReadonlyArray<A>
|
||||
rrb = crb;
|
||||
rrb = cra; // error: 'A' is not assignable to 'B'
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts(3,1): error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface.ts(3
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
a = x;
|
||||
@@ -3,6 +3,7 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(
|
||||
Type '() => Object' is not assignable to type '() => boolean'.
|
||||
Type 'Object' is not assignable to type 'boolean'.
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(19,1): error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(20,1): error TS2322: Type 'NotBoolean' is not assignable to type 'boolean'.
|
||||
|
||||
|
||||
@@ -33,6 +34,7 @@ tests/cases/conformance/types/primitives/boolean/assignFromBooleanInterface2.ts(
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'Boolean' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: 'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotBoolean' is not assignable to type 'boolean'.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts(3,1): error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/number/assignFromNumberInterface.ts(3,1
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
a = x;
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(24,1): error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(25,1): error TS2322: Type 'NotNumber' is not assignable to type 'number'.
|
||||
|
||||
|
||||
@@ -29,6 +30,7 @@ tests/cases/conformance/types/primitives/number/assignFromNumberInterface2.ts(25
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'Number' is not assignable to type 'number'.
|
||||
!!! error TS2322: 'number' is a primitive, but 'Number' is a wrapper object. Prefer using 'number' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotNumber' is not assignable to type 'number'.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts(3,1): error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/types/primitives/string/assignFromStringInterface.ts(3,1
|
||||
x = a;
|
||||
~
|
||||
!!! error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2322: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
a = x;
|
||||
@@ -1,4 +1,5 @@
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(47,1): error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(48,1): error TS2322: Type 'NotString' is not assignable to type 'string'.
|
||||
|
||||
|
||||
@@ -52,6 +53,7 @@ tests/cases/conformance/types/primitives/string/assignFromStringInterface2.ts(48
|
||||
x = a; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'String' is not assignable to type 'string'.
|
||||
!!! error TS2322: 'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
|
||||
x = b; // expected error
|
||||
~
|
||||
!!! error TS2322: Type 'NotString' is not assignable to type 'string'.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//// [await_unaryExpression_es6.ts]
|
||||
|
||||
async function bar() {
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
+await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
-await 42; // OK
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
~await 42; // OK
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
!(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
+(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
-(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
~(yield 42); // OK
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : Symbol(bar, Decl(await_unaryExpression_es6.ts, 0, 0))
|
||||
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6.ts, 3, 1))
|
||||
|
||||
+await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6.ts, 7, 1))
|
||||
|
||||
-await 42; // OK
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : Symbol(bar4, Decl(await_unaryExpression_es6.ts, 11, 1))
|
||||
|
||||
~await 42; // OK
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : () => Promise<void>
|
||||
|
||||
!await 42; // OK
|
||||
>!await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
+await 42; // OK
|
||||
>+await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
-await 42; // OK
|
||||
>-await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : () => Promise<void>
|
||||
|
||||
~await 42; // OK
|
||||
>~await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//// [await_unaryExpression_es6_1.ts]
|
||||
|
||||
async function bar() {
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
void await 42;
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
+await 42;
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_1.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
!(yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42); // OK
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
void (yield 42);
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
+(yield 42);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_1.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : Symbol(bar, Decl(await_unaryExpression_es6_1.ts, 0, 0))
|
||||
|
||||
!await 42; // OK
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6_1.ts, 3, 1))
|
||||
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : Symbol(bar2, Decl(await_unaryExpression_es6_1.ts, 7, 1))
|
||||
|
||||
delete await 42; // OK
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6_1.ts, 11, 1))
|
||||
|
||||
void await 42;
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : Symbol(bar4, Decl(await_unaryExpression_es6_1.ts, 15, 1))
|
||||
|
||||
+await 42;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_1.ts ===
|
||||
|
||||
async function bar() {
|
||||
>bar : () => Promise<void>
|
||||
|
||||
!await 42; // OK
|
||||
>!await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
delete await 42; // OK
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : () => Promise<void>
|
||||
|
||||
delete await 42; // OK
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
void await 42;
|
||||
>void await 42 : undefined
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
>bar4 : () => Promise<void>
|
||||
|
||||
+await 42;
|
||||
>+await 42 : number
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//// [await_unaryExpression_es6_2.ts]
|
||||
|
||||
async function bar1() {
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
void await 42;
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_2.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42);
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
delete (yield 42);
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
void (yield 42);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_2.ts ===
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : Symbol(bar1, Decl(await_unaryExpression_es6_2.ts, 0, 0))
|
||||
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : Symbol(bar2, Decl(await_unaryExpression_es6_2.ts, 3, 1))
|
||||
|
||||
delete await 42;
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : Symbol(bar3, Decl(await_unaryExpression_es6_2.ts, 7, 1))
|
||||
|
||||
void await 42;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
=== tests/cases/conformance/async/es6/await_unaryExpression_es6_2.ts ===
|
||||
|
||||
async function bar1() {
|
||||
>bar1 : () => Promise<void>
|
||||
|
||||
delete await 42;
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
>bar2 : () => Promise<void>
|
||||
|
||||
delete await 42;
|
||||
>delete await 42 : boolean
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
>bar3 : () => Promise<void>
|
||||
|
||||
void await 42;
|
||||
>void await 42 : undefined
|
||||
>await 42 : number
|
||||
>42 : number
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts(3,7): error TS1109: Expression expected.
|
||||
tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts(7,7): error TS1109: Expression expected.
|
||||
|
||||
|
||||
==== tests/cases/conformance/async/es6/await_unaryExpression_es6_3.ts (2 errors) ====
|
||||
|
||||
async function bar1() {
|
||||
++await 42; // Error
|
||||
~~~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
--await 42; // Error
|
||||
~~~~~
|
||||
!!! error TS1109: Expression expected.
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
var x = 42;
|
||||
await x++; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
var x = 42;
|
||||
await x--; // OK but shouldn't need parenthesis
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//// [await_unaryExpression_es6_3.ts]
|
||||
|
||||
async function bar1() {
|
||||
++await 42; // Error
|
||||
}
|
||||
|
||||
async function bar2() {
|
||||
--await 42; // Error
|
||||
}
|
||||
|
||||
async function bar3() {
|
||||
var x = 42;
|
||||
await x++; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
async function bar4() {
|
||||
var x = 42;
|
||||
await x--; // OK but shouldn't need parenthesis
|
||||
}
|
||||
|
||||
//// [await_unaryExpression_es6_3.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function bar1() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
++;
|
||||
yield 42; // Error
|
||||
});
|
||||
}
|
||||
function bar2() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
--;
|
||||
yield 42; // Error
|
||||
});
|
||||
}
|
||||
function bar3() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var x = 42;
|
||||
yield x++; // OK but shouldn't need parenthesis
|
||||
});
|
||||
}
|
||||
function bar4() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var x = 42;
|
||||
yield x--; // OK but shouldn't need parenthesis
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//// [castOfAwait.ts]
|
||||
async function f() {
|
||||
<number> await 0;
|
||||
typeof await 0;
|
||||
void await 0;
|
||||
await void <string> typeof <number> void await 0;
|
||||
await await 0;
|
||||
}
|
||||
|
||||
|
||||
//// [castOfAwait.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield 0;
|
||||
typeof (yield 0);
|
||||
void (yield 0);
|
||||
yield void typeof void (yield 0);
|
||||
yield yield 0;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/castOfAwait.ts ===
|
||||
async function f() {
|
||||
>f : Symbol(f, Decl(castOfAwait.ts, 0, 0))
|
||||
|
||||
<number> await 0;
|
||||
typeof await 0;
|
||||
void await 0;
|
||||
await void <string> typeof <number> void await 0;
|
||||
await await 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
=== tests/cases/compiler/castOfAwait.ts ===
|
||||
async function f() {
|
||||
>f : () => Promise<void>
|
||||
|
||||
<number> await 0;
|
||||
><number> await 0 : number
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
typeof await 0;
|
||||
>typeof await 0 : string
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
void await 0;
|
||||
>void await 0 : undefined
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
await void <string> typeof <number> void await 0;
|
||||
>await void <string> typeof <number> void await 0 : any
|
||||
>void <string> typeof <number> void await 0 : undefined
|
||||
><string> typeof <number> void await 0 : string
|
||||
>typeof <number> void await 0 : string
|
||||
><number> void await 0 : number
|
||||
>void await 0 : undefined
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
|
||||
await await 0;
|
||||
>await await 0 : number
|
||||
>await 0 : number
|
||||
>0 : number
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user