mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into readonlyTypes
# Conflicts: # src/compiler/checker.ts # src/compiler/types.ts # src/lib/es5.d.ts # tests/baselines/reference/arrayConcat2.types # tests/baselines/reference/arrayConcatMap.types # tests/baselines/reference/arrayOfSubtypeIsAssignableToReadonlyArray.errors.txt # tests/baselines/reference/concatError.types # tests/baselines/reference/concatTuples.types # tests/baselines/reference/emitSkipsThisWithRestParameter.types # tests/baselines/reference/iteratorSpreadInArray7.types # tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types
This commit is contained in:
+2
-1
@@ -16,4 +16,5 @@ Jakefile.js
|
||||
.gitattributes
|
||||
.settings/
|
||||
.travis.yml
|
||||
.vscode/
|
||||
.vscode/
|
||||
test.config
|
||||
@@ -16,6 +16,7 @@ matrix:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- release-2.5
|
||||
|
||||
install:
|
||||
- npm uninstall typescript --no-save
|
||||
|
||||
Vendored
+7
@@ -18,6 +18,13 @@
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"taskName": "tests",
|
||||
"showOutput": "silent",
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+75
-41
@@ -28,7 +28,6 @@ import minimist = require("minimist");
|
||||
import browserify = require("browserify");
|
||||
import through2 = require("through2");
|
||||
import merge2 = require("merge2");
|
||||
import intoStream = require("into-stream");
|
||||
import * as os from "os";
|
||||
import fold = require("travis-fold");
|
||||
const gulp = helpMaker(originalGulp);
|
||||
@@ -294,7 +293,7 @@ gulp.task("configure-nightly", "Runs scripts/configureNightly.ts to prepare a bu
|
||||
exec(host, [configureNightlyJs, packageJson, versionFile], done, done);
|
||||
});
|
||||
gulp.task("publish-nightly", "Runs `npm publish --tag next` to create a new nightly build on npm", ["LKG"], () => {
|
||||
return runSequence("clean", "useDebugMode", "runtests", (done) => {
|
||||
return runSequence("clean", "useDebugMode", "runtests-parallel", (done) => {
|
||||
exec("npm", ["publish", "--tag", "next"], done, done);
|
||||
});
|
||||
});
|
||||
@@ -464,10 +463,11 @@ gulp.task(serverFile, /*help*/ false, [servicesFile, typingsInstallerJs, cancell
|
||||
.pipe(gulp.dest("src/server"));
|
||||
});
|
||||
|
||||
const typesMapJson = path.join(builtLocalDirectory, "typesMap.json");
|
||||
const tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
const tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
|
||||
gulp.task(tsserverLibraryFile, /*help*/ false, [servicesFile], (done) => {
|
||||
gulp.task(tsserverLibraryFile, /*help*/ false, [servicesFile, typesMapJson], (done) => {
|
||||
const serverLibraryProject = tsc.createProject("src/server/tsconfig.library.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src()
|
||||
.pipe(sourcemaps.init())
|
||||
@@ -486,6 +486,15 @@ gulp.task(tsserverLibraryFile, /*help*/ false, [servicesFile], (done) => {
|
||||
]);
|
||||
});
|
||||
|
||||
gulp.task(typesMapJson, /*help*/ false, [], () => {
|
||||
return gulp.src("src/server/typesMap.json")
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
JSON.parse(contents);
|
||||
return contents;
|
||||
}))
|
||||
.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, tsserverLibraryFile]);
|
||||
gulp.task("tsc", "Builds only the compiler", [builtLocalCompiler]);
|
||||
@@ -737,50 +746,75 @@ gulp.task(nodeServerOutFile, /*help*/ false, [servicesFile], () => {
|
||||
|
||||
import convertMap = require("convert-source-map");
|
||||
import sorcery = require("sorcery");
|
||||
declare module "convert-source-map" {
|
||||
export function fromSource(source: string, largeSource?: boolean): SourceMapConverter;
|
||||
}
|
||||
import Vinyl = require("vinyl");
|
||||
|
||||
gulp.task("browserify", "Runs browserify on run.js to produce a file suitable for running tests in the browser", [servicesFile, run], (done) => {
|
||||
const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({ outFile: "../../built/local/bundle.js" }, /*useBuiltCompiler*/ true));
|
||||
return testProject.src()
|
||||
.pipe(newer("built/local/bundle.js"))
|
||||
const bundlePath = path.resolve("built/local/bundle.js");
|
||||
|
||||
gulp.task("browserify", "Runs browserify on run.js to produce a file suitable for running tests in the browser", [servicesFile], (done) => {
|
||||
const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({ outFile: bundlePath, inlineSourceMap: true }, /*useBuiltCompiler*/ true));
|
||||
let originalMap: any;
|
||||
let prebundledContent: string;
|
||||
browserify(testProject.src()
|
||||
.pipe(newer(bundlePath))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(testProject())
|
||||
.pipe(through2.obj((file, enc, next) => {
|
||||
const originalMap = file.sourceMap;
|
||||
const prebundledContent = file.contents.toString();
|
||||
if (originalMap) {
|
||||
throw new Error("Should only recieve one file!");
|
||||
}
|
||||
console.log(`Saving sourcemaps for ${file.path}`);
|
||||
originalMap = file.sourceMap;
|
||||
prebundledContent = file.contents.toString();
|
||||
// Make paths absolute to help sorcery deal with all the terrible paths being thrown around
|
||||
originalMap.sources = originalMap.sources.map(s => path.resolve(path.join("src/harness", s)));
|
||||
// intoStream (below) makes browserify think the input file is named this, so this is what it puts in the sourcemap
|
||||
// browserify names input files this when they are streamed in, so this is what it puts in the sourcemap
|
||||
originalMap.file = "built/local/_stream_0.js";
|
||||
|
||||
browserify(intoStream(file.contents), { debug: true })
|
||||
.bundle((err, res) => {
|
||||
// assumes file.contents is a Buffer
|
||||
const maps = JSON.parse(convertMap.fromSource(res.toString(), /*largeSource*/ true).toJSON());
|
||||
delete maps.sourceRoot;
|
||||
maps.sources = maps.sources.map(s => path.resolve(s === "_stream_0.js" ? "built/local/_stream_0.js" : s));
|
||||
// Strip browserify's inline comments away (could probably just let sorcery do this, but then we couldn't fix the paths)
|
||||
file.contents = new Buffer(convertMap.removeComments(res.toString()));
|
||||
const chain = sorcery.loadSync("built/local/bundle.js", {
|
||||
content: {
|
||||
"built/local/_stream_0.js": prebundledContent,
|
||||
"built/local/bundle.js": file.contents.toString()
|
||||
},
|
||||
sourcemaps: {
|
||||
"built/local/_stream_0.js": originalMap,
|
||||
"built/local/bundle.js": maps,
|
||||
"node_modules/source-map-support/source-map-support.js": undefined,
|
||||
}
|
||||
});
|
||||
const finalMap = chain.apply();
|
||||
file.sourceMap = finalMap;
|
||||
next(/*err*/ undefined, file);
|
||||
});
|
||||
next(/*err*/ undefined, file.contents);
|
||||
}))
|
||||
.pipe(sourcemaps.write(".", { includeContent: false }))
|
||||
.pipe(gulp.dest("src/harness"));
|
||||
.on("error", err => {
|
||||
return done(err);
|
||||
}), { debug: true, basedir: __dirname }) // Attach error handler to inner stream
|
||||
.bundle((err, contents) => {
|
||||
if (err) {
|
||||
if (err.message.match(/Cannot find module '.*_stream_0.js'/)) {
|
||||
return done(); // Browserify errors when we pass in no files when `newer` filters the input, we should count that as a success, though
|
||||
}
|
||||
return done(err);
|
||||
}
|
||||
const stringContent = contents.toString();
|
||||
const file = new Vinyl({ contents, path: bundlePath });
|
||||
console.log(`Fixing sourcemaps for ${file.path}`);
|
||||
// assumes contents is a Buffer, since that's what browserify yields
|
||||
const maps = convertMap.fromSource(stringContent, /*largeSource*/ true).toObject();
|
||||
delete maps.sourceRoot;
|
||||
maps.sources = maps.sources.map(s => path.resolve(s === "_stream_0.js" ? "built/local/_stream_0.js" : s));
|
||||
// Strip browserify's inline comments away (could probably just let sorcery do this, but then we couldn't fix the paths)
|
||||
file.contents = new Buffer(convertMap.removeComments(stringContent));
|
||||
const chain = sorcery.loadSync(bundlePath, {
|
||||
content: {
|
||||
"built/local/_stream_0.js": prebundledContent,
|
||||
[bundlePath]: stringContent
|
||||
},
|
||||
sourcemaps: {
|
||||
"built/local/_stream_0.js": originalMap,
|
||||
[bundlePath]: maps,
|
||||
"node_modules/source-map-support/source-map-support.js": undefined,
|
||||
}
|
||||
});
|
||||
const finalMap = chain.apply();
|
||||
file.sourceMap = finalMap;
|
||||
|
||||
const stream = through2.obj((file, enc, callback) => {
|
||||
return callback(/*err*/ undefined, file);
|
||||
});
|
||||
stream.pipe(sourcemaps.write(".", { includeContent: false }))
|
||||
.pipe(gulp.dest("."))
|
||||
.on("end", done)
|
||||
.on("error", done);
|
||||
stream.write(file);
|
||||
stream.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -944,7 +978,7 @@ const instrumenterPath = path.join(harnessDirectory, "instrumenter.ts");
|
||||
const instrumenterJsPath = path.join(builtLocalDirectory, "instrumenter.js");
|
||||
gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
outFile: instrumenterJsPath,
|
||||
module: "commonjs",
|
||||
target: "es5",
|
||||
lib: [
|
||||
"es6",
|
||||
@@ -956,8 +990,8 @@ gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => {
|
||||
.pipe(newer(instrumenterJsPath))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(tsc(settings))
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(sourcemaps.write(builtLocalDirectory))
|
||||
.pipe(gulp.dest(builtLocalDirectory));
|
||||
});
|
||||
|
||||
gulp.task("tsc-instrumented", "Builds an instrumented tsc.js", ["local", loggedIOJsPath, instrumenterJsPath, servicesFile], (done) => {
|
||||
|
||||
+31
-31
@@ -88,6 +88,8 @@ var watchGuardSources = filesFromConfig(path.join(serverDirectory, "watchGuard/t
|
||||
var serverSources = filesFromConfig(path.join(serverDirectory, "tsconfig.json"))
|
||||
var languageServiceLibrarySources = filesFromConfig(path.join(serverDirectory, "tsconfig.library.json"));
|
||||
|
||||
var typesMapOutputPath = path.join(builtLocalDirectory, 'typesMap.json');
|
||||
|
||||
var harnessCoreSources = [
|
||||
"harness.ts",
|
||||
"virtualFileSystem.ts",
|
||||
@@ -133,12 +135,14 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"projectErrors.ts",
|
||||
"matchFiles.ts",
|
||||
"initializeTSConfig.ts",
|
||||
"extractMethods.ts",
|
||||
"printer.ts",
|
||||
"textChanges.ts",
|
||||
"telemetry.ts",
|
||||
"transform.ts",
|
||||
"customTransforms.ts",
|
||||
"programMissingFiles.ts",
|
||||
"symbolWalker.ts",
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
@@ -422,6 +426,7 @@ var buildProtocolTs = path.join(scriptsDirectory, "buildProtocol.ts");
|
||||
var buildProtocolJs = path.join(scriptsDirectory, "buildProtocol.js");
|
||||
var buildProtocolDts = path.join(builtLocalDirectory, "protocol.d.ts");
|
||||
var typescriptServicesDts = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
var typesMapJson = path.join(builtLocalDirectory, "typesMap.json");
|
||||
|
||||
file(buildProtocolTs);
|
||||
|
||||
@@ -505,7 +510,7 @@ task("configure-nightly", [configureNightlyJs], function () {
|
||||
}, { async: true });
|
||||
|
||||
desc("Configure, build, test, and publish the nightly release.");
|
||||
task("publish-nightly", ["configure-nightly", "LKG", "clean", "setDebugMode", "runtests"], function () {
|
||||
task("publish-nightly", ["configure-nightly", "LKG", "clean", "setDebugMode", "runtests-parallel"], function () {
|
||||
var cmd = "npm publish --tag next";
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
@@ -533,7 +538,6 @@ var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var servicesFileInBrowserTest = path.join(builtLocalDirectory, "typescriptServicesInBrowserTest.js");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
@@ -572,22 +576,6 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
|
||||
compileFile(
|
||||
servicesFileInBrowserTest,
|
||||
servicesSources,
|
||||
[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
|
||||
file(typescriptServicesDts, [servicesFile]);
|
||||
|
||||
var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js");
|
||||
@@ -603,6 +591,16 @@ var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true, lib: "es6" });
|
||||
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
file(typesMapOutputPath, function() {
|
||||
var content = fs.readFileSync(path.join(serverDirectory, 'typesMap.json'));
|
||||
// Validate that it's valid JSON
|
||||
try {
|
||||
JSON.parse(content);
|
||||
} catch (e) {
|
||||
console.log("Parse error in typesMap.json: " + e);
|
||||
}
|
||||
fs.writeFileSync(typesMapOutputPath, content);
|
||||
});
|
||||
compileFile(
|
||||
tsserverLibraryFile,
|
||||
languageServiceLibrarySources,
|
||||
@@ -625,7 +623,7 @@ compileFile(
|
||||
|
||||
// Local target to build the language service server library
|
||||
desc("Builds language service server library");
|
||||
task("lssl", [tsserverLibraryFile, tsserverLibraryDefinitionFile]);
|
||||
task("lssl", [tsserverLibraryFile, tsserverLibraryDefinitionFile, typesMapOutputPath]);
|
||||
|
||||
desc("Emit the start of the build fold");
|
||||
task("build-fold-start", [], function () {
|
||||
@@ -654,7 +652,6 @@ task("release", function () {
|
||||
// Set the default task to "local"
|
||||
task("default", ["local"]);
|
||||
|
||||
|
||||
// Cleans the built directory
|
||||
desc("Cleans the compiler output, declare files, and tests");
|
||||
task("clean", function () {
|
||||
@@ -725,7 +722,7 @@ compileFile(
|
||||
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler:*/ true,
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6" });
|
||||
/*opts*/ { types: ["node", "mocha", "chai"], lib: "es6" });
|
||||
|
||||
var internalTests = "internal/";
|
||||
|
||||
@@ -840,7 +837,8 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
testTimeout = 800000;
|
||||
}
|
||||
|
||||
var colors = process.env.colors || process.env.color || true;
|
||||
var colorsFlag = process.env.color || process.env.colors;
|
||||
var colors = colorsFlag !== "false" && colorsFlag !== "0";
|
||||
var reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
var bail = process.env.bail || process.env.b;
|
||||
var lintFlag = process.env.lint !== 'false';
|
||||
@@ -960,13 +958,14 @@ var nodeServerInFile = "tests/webTestServer.ts";
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true, lib: "es6" });
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", run, builtLocalDirectory, nodeServerOutFile], function() {
|
||||
var cmd = 'browserify built/local/run.js -t ./scripts/browserify-optional -d -o built/local/bundle.js';
|
||||
task("browserify", [], function() {
|
||||
// Shell out to `gulp`, since we do the work to handle sourcemaps correctly w/o inline maps there
|
||||
var cmd = 'gulp browserify --silent';
|
||||
exec(cmd);
|
||||
}, { 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", ["browserify", nodeServerOutFile], function () {
|
||||
cleanTestDirs();
|
||||
host = "node";
|
||||
browser = process.env.browser || process.env.b || (os.platform() === "linux" ? "chrome" : "IE");
|
||||
@@ -1100,7 +1099,7 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function () {
|
||||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true, { lib: "es6", types: ["node"] });
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true, { lib: "es6", types: ["node"], noOutFile: true, outDir: builtLocalDirectory });
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function () {
|
||||
@@ -1121,14 +1120,15 @@ task("update-sublime", ["local", serverFile], function () {
|
||||
|
||||
var tslintRuleDir = "scripts/tslint";
|
||||
var tslintRules = [
|
||||
"nextLineRule",
|
||||
"booleanTriviaRule",
|
||||
"typeOperatorSpacingRule",
|
||||
"noInOperatorRule",
|
||||
"debugAssertRule",
|
||||
"nextLineRule",
|
||||
"noBomRule",
|
||||
"noIncrementDecrementRule",
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"noInOperatorRule",
|
||||
"noTypeAssertionWhitespaceRule",
|
||||
"noBomRule"
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"typeOperatorSpacingRule",
|
||||
];
|
||||
var tslintRulesFiles = tslintRules.map(function (p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
```ts
|
||||
// A *self-contained* demonstration of the problem follows...
|
||||
|
||||
// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.
|
||||
```
|
||||
|
||||
**Expected behavior:**
|
||||
|
||||
Vendored
+4352
-4809
File diff suppressed because it is too large
Load Diff
Vendored
+4200
-4452
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
@@ -21,8 +21,8 @@ and limitations under the License.
|
||||
/// <reference path="lib.es2015.core.d.ts" />
|
||||
/// <reference path="lib.es2015.collection.d.ts" />
|
||||
/// <reference path="lib.es2015.generator.d.ts" />
|
||||
/// <reference path="lib.es2015.iterable.d.ts" />
|
||||
/// <reference path="lib.es2015.promise.d.ts" />
|
||||
/// <reference path="lib.es2015.iterable.d.ts" />
|
||||
/// <reference path="lib.es2015.proxy.d.ts" />
|
||||
/// <reference path="lib.es2015.reflect.d.ts" />
|
||||
/// <reference path="lib.es2015.symbol.d.ts" />
|
||||
|
||||
Vendored
+1
-1
@@ -130,7 +130,7 @@ interface Map<K, V> {
|
||||
readonly [Symbol.toStringTag]: "Map";
|
||||
}
|
||||
|
||||
interface WeakMap<K extends object, V>{
|
||||
interface WeakMap<K extends object, V> {
|
||||
readonly [Symbol.toStringTag]: "WeakMap";
|
||||
}
|
||||
|
||||
|
||||
Vendored
+4201
-4453
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
@@ -22,4 +22,4 @@ and limitations under the License.
|
||||
/// <reference path="lib.es2017.object.d.ts" />
|
||||
/// <reference path="lib.es2017.sharedmemory.d.ts" />
|
||||
/// <reference path="lib.es2017.string.d.ts" />
|
||||
/// <reference path="lib.es2017.intl.d.ts" />
|
||||
/// <reference path="lib.es2017.intl.d.ts" />
|
||||
|
||||
Vendored
+4202
-4453
File diff suppressed because it is too large
Load Diff
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
|
||||
type DateTimeFormatPartTypes = "day" | "dayPeriod" | "era" | "hour" | "literal" | "minute" | "month" | "second" | "timeZoneName" | "weekday" | "year";
|
||||
|
||||
interface DateTimeFormatPart {
|
||||
type: DateTimeFormatPartTypes;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DateTimeFormat {
|
||||
formatToParts(date?: Date | number): DateTimeFormatPart[];
|
||||
}
|
||||
Vendored
+152
-357
File diff suppressed because it is too large
Load Diff
Vendored
+4353
-4810
File diff suppressed because it is too large
Load Diff
Vendored
+4201
-4453
File diff suppressed because it is too large
Load Diff
Vendored
+145
-134
@@ -20,7 +20,7 @@ and limitations under the License.
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
/// IE Worker APIs
|
||||
/// Worker APIs
|
||||
/////////////////////////////
|
||||
|
||||
interface Algorithm {
|
||||
@@ -28,16 +28,16 @@ interface Algorithm {
|
||||
}
|
||||
|
||||
interface CacheQueryOptions {
|
||||
ignoreSearch?: boolean;
|
||||
ignoreMethod?: boolean;
|
||||
ignoreVary?: boolean;
|
||||
cacheName?: string;
|
||||
ignoreMethod?: boolean;
|
||||
ignoreSearch?: boolean;
|
||||
ignoreVary?: boolean;
|
||||
}
|
||||
|
||||
interface CloseEventInit extends EventInit {
|
||||
wasClean?: boolean;
|
||||
code?: number;
|
||||
reason?: string;
|
||||
wasClean?: boolean;
|
||||
}
|
||||
|
||||
interface EventInit {
|
||||
@@ -69,16 +69,16 @@ interface MessageEventInit extends EventInit {
|
||||
channel?: string;
|
||||
data?: any;
|
||||
origin?: string;
|
||||
source?: any;
|
||||
ports?: MessagePort[];
|
||||
source?: any;
|
||||
}
|
||||
|
||||
interface NotificationOptions {
|
||||
dir?: NotificationDirection;
|
||||
lang?: string;
|
||||
body?: string;
|
||||
tag?: string;
|
||||
dir?: NotificationDirection;
|
||||
icon?: string;
|
||||
lang?: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
interface ObjectURLOptions {
|
||||
@@ -86,29 +86,29 @@ interface ObjectURLOptions {
|
||||
}
|
||||
|
||||
interface PushSubscriptionOptionsInit {
|
||||
userVisibleOnly?: boolean;
|
||||
applicationServerKey?: any;
|
||||
userVisibleOnly?: boolean;
|
||||
}
|
||||
|
||||
interface RequestInit {
|
||||
method?: string;
|
||||
headers?: any;
|
||||
body?: any;
|
||||
referrer?: string;
|
||||
referrerPolicy?: ReferrerPolicy;
|
||||
mode?: RequestMode;
|
||||
credentials?: RequestCredentials;
|
||||
cache?: RequestCache;
|
||||
redirect?: RequestRedirect;
|
||||
credentials?: RequestCredentials;
|
||||
headers?: any;
|
||||
integrity?: string;
|
||||
keepalive?: boolean;
|
||||
method?: string;
|
||||
mode?: RequestMode;
|
||||
redirect?: RequestRedirect;
|
||||
referrer?: string;
|
||||
referrerPolicy?: ReferrerPolicy;
|
||||
window?: any;
|
||||
}
|
||||
|
||||
interface ResponseInit {
|
||||
headers?: any;
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
headers?: any;
|
||||
}
|
||||
|
||||
interface ClientQueryOptions {
|
||||
@@ -176,7 +176,7 @@ interface AudioBuffer {
|
||||
declare var AudioBuffer: {
|
||||
prototype: AudioBuffer;
|
||||
new(): AudioBuffer;
|
||||
}
|
||||
};
|
||||
|
||||
interface Blob {
|
||||
readonly size: number;
|
||||
@@ -189,7 +189,7 @@ interface Blob {
|
||||
declare var Blob: {
|
||||
prototype: Blob;
|
||||
new (blobParts?: any[], options?: BlobPropertyBag): Blob;
|
||||
}
|
||||
};
|
||||
|
||||
interface Cache {
|
||||
add(request: RequestInfo): Promise<void>;
|
||||
@@ -204,7 +204,7 @@ interface Cache {
|
||||
declare var Cache: {
|
||||
prototype: Cache;
|
||||
new(): Cache;
|
||||
}
|
||||
};
|
||||
|
||||
interface CacheStorage {
|
||||
delete(cacheName: string): Promise<boolean>;
|
||||
@@ -217,7 +217,7 @@ interface CacheStorage {
|
||||
declare var CacheStorage: {
|
||||
prototype: CacheStorage;
|
||||
new(): CacheStorage;
|
||||
}
|
||||
};
|
||||
|
||||
interface CloseEvent extends Event {
|
||||
readonly code: number;
|
||||
@@ -229,7 +229,7 @@ interface CloseEvent extends Event {
|
||||
declare var CloseEvent: {
|
||||
prototype: CloseEvent;
|
||||
new(typeArg: string, eventInitDict?: CloseEventInit): CloseEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface Console {
|
||||
assert(test?: boolean, message?: string, ...optionalParams: any[]): void;
|
||||
@@ -240,8 +240,8 @@ interface Console {
|
||||
dirxml(value: any): void;
|
||||
error(message?: any, ...optionalParams: any[]): void;
|
||||
exception(message?: string, ...optionalParams: any[]): void;
|
||||
group(groupTitle?: string): void;
|
||||
groupCollapsed(groupTitle?: string): void;
|
||||
group(groupTitle?: string, ...optionalParams: any[]): void;
|
||||
groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void;
|
||||
groupEnd(): void;
|
||||
info(message?: any, ...optionalParams: any[]): void;
|
||||
log(message?: any, ...optionalParams: any[]): void;
|
||||
@@ -259,7 +259,7 @@ interface Console {
|
||||
declare var Console: {
|
||||
prototype: Console;
|
||||
new(): Console;
|
||||
}
|
||||
};
|
||||
|
||||
interface Coordinates {
|
||||
readonly accuracy: number;
|
||||
@@ -274,7 +274,7 @@ interface Coordinates {
|
||||
declare var Coordinates: {
|
||||
prototype: Coordinates;
|
||||
new(): Coordinates;
|
||||
}
|
||||
};
|
||||
|
||||
interface CryptoKey {
|
||||
readonly algorithm: KeyAlgorithm;
|
||||
@@ -286,7 +286,7 @@ interface CryptoKey {
|
||||
declare var CryptoKey: {
|
||||
prototype: CryptoKey;
|
||||
new(): CryptoKey;
|
||||
}
|
||||
};
|
||||
|
||||
interface DOMError {
|
||||
readonly name: string;
|
||||
@@ -296,7 +296,7 @@ interface DOMError {
|
||||
declare var DOMError: {
|
||||
prototype: DOMError;
|
||||
new(): DOMError;
|
||||
}
|
||||
};
|
||||
|
||||
interface DOMException {
|
||||
readonly code: number;
|
||||
@@ -316,10 +316,10 @@ interface DOMException {
|
||||
readonly INVALID_STATE_ERR: number;
|
||||
readonly NAMESPACE_ERR: number;
|
||||
readonly NETWORK_ERR: number;
|
||||
readonly NOT_FOUND_ERR: number;
|
||||
readonly NOT_SUPPORTED_ERR: number;
|
||||
readonly NO_DATA_ALLOWED_ERR: number;
|
||||
readonly NO_MODIFICATION_ALLOWED_ERR: number;
|
||||
readonly NOT_FOUND_ERR: number;
|
||||
readonly NOT_SUPPORTED_ERR: number;
|
||||
readonly PARSE_ERR: number;
|
||||
readonly QUOTA_EXCEEDED_ERR: number;
|
||||
readonly SECURITY_ERR: number;
|
||||
@@ -348,10 +348,10 @@ declare var DOMException: {
|
||||
readonly INVALID_STATE_ERR: number;
|
||||
readonly NAMESPACE_ERR: number;
|
||||
readonly NETWORK_ERR: number;
|
||||
readonly NOT_FOUND_ERR: number;
|
||||
readonly NOT_SUPPORTED_ERR: number;
|
||||
readonly NO_DATA_ALLOWED_ERR: number;
|
||||
readonly NO_MODIFICATION_ALLOWED_ERR: number;
|
||||
readonly NOT_FOUND_ERR: number;
|
||||
readonly NOT_SUPPORTED_ERR: number;
|
||||
readonly PARSE_ERR: number;
|
||||
readonly QUOTA_EXCEEDED_ERR: number;
|
||||
readonly SECURITY_ERR: number;
|
||||
@@ -362,7 +362,7 @@ declare var DOMException: {
|
||||
readonly URL_MISMATCH_ERR: number;
|
||||
readonly VALIDATION_ERR: number;
|
||||
readonly WRONG_DOCUMENT_ERR: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface DOMStringList {
|
||||
readonly length: number;
|
||||
@@ -374,7 +374,7 @@ interface DOMStringList {
|
||||
declare var DOMStringList: {
|
||||
prototype: DOMStringList;
|
||||
new(): DOMStringList;
|
||||
}
|
||||
};
|
||||
|
||||
interface ErrorEvent extends Event {
|
||||
readonly colno: number;
|
||||
@@ -388,12 +388,12 @@ interface ErrorEvent extends Event {
|
||||
declare var ErrorEvent: {
|
||||
prototype: ErrorEvent;
|
||||
new(type: string, errorEventInitDict?: ErrorEventInit): ErrorEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface Event {
|
||||
readonly bubbles: boolean;
|
||||
cancelBubble: boolean;
|
||||
readonly cancelable: boolean;
|
||||
cancelBubble: boolean;
|
||||
readonly currentTarget: EventTarget;
|
||||
readonly defaultPrevented: boolean;
|
||||
readonly eventPhase: number;
|
||||
@@ -420,7 +420,7 @@ declare var Event: {
|
||||
readonly AT_TARGET: number;
|
||||
readonly BUBBLING_PHASE: number;
|
||||
readonly CAPTURING_PHASE: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface EventTarget {
|
||||
addEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
@@ -431,7 +431,7 @@ interface EventTarget {
|
||||
declare var EventTarget: {
|
||||
prototype: EventTarget;
|
||||
new(): EventTarget;
|
||||
}
|
||||
};
|
||||
|
||||
interface File extends Blob {
|
||||
readonly lastModifiedDate: any;
|
||||
@@ -442,7 +442,7 @@ interface File extends Blob {
|
||||
declare var File: {
|
||||
prototype: File;
|
||||
new (parts: (ArrayBuffer | ArrayBufferView | Blob | string)[], filename: string, properties?: FilePropertyBag): File;
|
||||
}
|
||||
};
|
||||
|
||||
interface FileList {
|
||||
readonly length: number;
|
||||
@@ -453,7 +453,7 @@ interface FileList {
|
||||
declare var FileList: {
|
||||
prototype: FileList;
|
||||
new(): FileList;
|
||||
}
|
||||
};
|
||||
|
||||
interface FileReader extends EventTarget, MSBaseReader {
|
||||
readonly error: DOMError;
|
||||
@@ -468,8 +468,17 @@ interface FileReader extends EventTarget, MSBaseReader {
|
||||
declare var FileReader: {
|
||||
prototype: FileReader;
|
||||
new(): FileReader;
|
||||
};
|
||||
|
||||
interface FormData {
|
||||
append(name: string, value: string | Blob, fileName?: string): void;
|
||||
}
|
||||
|
||||
declare var FormData: {
|
||||
prototype: FormData;
|
||||
new(): FormData;
|
||||
};
|
||||
|
||||
interface Headers {
|
||||
append(name: string, value: string): void;
|
||||
delete(name: string): void;
|
||||
@@ -482,7 +491,7 @@ interface Headers {
|
||||
declare var Headers: {
|
||||
prototype: Headers;
|
||||
new(init?: any): Headers;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBCursor {
|
||||
readonly direction: IDBCursorDirection;
|
||||
@@ -506,7 +515,7 @@ declare var IDBCursor: {
|
||||
readonly NEXT_NO_DUPLICATE: string;
|
||||
readonly PREV: string;
|
||||
readonly PREV_NO_DUPLICATE: string;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBCursorWithValue extends IDBCursor {
|
||||
readonly value: any;
|
||||
@@ -515,7 +524,7 @@ interface IDBCursorWithValue extends IDBCursor {
|
||||
declare var IDBCursorWithValue: {
|
||||
prototype: IDBCursorWithValue;
|
||||
new(): IDBCursorWithValue;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBDatabaseEventMap {
|
||||
"abort": Event;
|
||||
@@ -532,7 +541,7 @@ interface IDBDatabase extends EventTarget {
|
||||
close(): void;
|
||||
createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore;
|
||||
deleteObjectStore(name: string): void;
|
||||
transaction(storeNames: string | string[], mode?: string): IDBTransaction;
|
||||
transaction(storeNames: string | string[], mode?: IDBTransactionMode): IDBTransaction;
|
||||
addEventListener(type: "versionchange", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener<K extends keyof IDBDatabaseEventMap>(type: K, listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
@@ -541,7 +550,7 @@ interface IDBDatabase extends EventTarget {
|
||||
declare var IDBDatabase: {
|
||||
prototype: IDBDatabase;
|
||||
new(): IDBDatabase;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBFactory {
|
||||
cmp(first: any, second: any): number;
|
||||
@@ -552,7 +561,7 @@ interface IDBFactory {
|
||||
declare var IDBFactory: {
|
||||
prototype: IDBFactory;
|
||||
new(): IDBFactory;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBIndex {
|
||||
keyPath: string | string[];
|
||||
@@ -563,14 +572,14 @@ interface IDBIndex {
|
||||
count(key?: IDBKeyRange | IDBValidKey): IDBRequest;
|
||||
get(key: IDBKeyRange | IDBValidKey): IDBRequest;
|
||||
getKey(key: IDBKeyRange | IDBValidKey): IDBRequest;
|
||||
openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest;
|
||||
openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest;
|
||||
openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;
|
||||
openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;
|
||||
}
|
||||
|
||||
declare var IDBIndex: {
|
||||
prototype: IDBIndex;
|
||||
new(): IDBIndex;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBKeyRange {
|
||||
readonly lower: any;
|
||||
@@ -586,7 +595,7 @@ declare var IDBKeyRange: {
|
||||
lowerBound(lower: any, open?: boolean): IDBKeyRange;
|
||||
only(value: any): IDBKeyRange;
|
||||
upperBound(upper: any, open?: boolean): IDBKeyRange;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBObjectStore {
|
||||
readonly indexNames: DOMStringList;
|
||||
@@ -602,14 +611,14 @@ interface IDBObjectStore {
|
||||
deleteIndex(indexName: string): void;
|
||||
get(key: any): IDBRequest;
|
||||
index(name: string): IDBIndex;
|
||||
openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest;
|
||||
openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;
|
||||
put(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest;
|
||||
}
|
||||
|
||||
declare var IDBObjectStore: {
|
||||
prototype: IDBObjectStore;
|
||||
new(): IDBObjectStore;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBOpenDBRequestEventMap extends IDBRequestEventMap {
|
||||
"blocked": Event;
|
||||
@@ -626,7 +635,7 @@ interface IDBOpenDBRequest extends IDBRequest {
|
||||
declare var IDBOpenDBRequest: {
|
||||
prototype: IDBOpenDBRequest;
|
||||
new(): IDBOpenDBRequest;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBRequestEventMap {
|
||||
"error": Event;
|
||||
@@ -634,7 +643,7 @@ interface IDBRequestEventMap {
|
||||
}
|
||||
|
||||
interface IDBRequest extends EventTarget {
|
||||
readonly error: DOMError;
|
||||
readonly error: DOMException;
|
||||
onerror: (this: IDBRequest, ev: Event) => any;
|
||||
onsuccess: (this: IDBRequest, ev: Event) => any;
|
||||
readonly readyState: IDBRequestReadyState;
|
||||
@@ -648,7 +657,7 @@ interface IDBRequest extends EventTarget {
|
||||
declare var IDBRequest: {
|
||||
prototype: IDBRequest;
|
||||
new(): IDBRequest;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBTransactionEventMap {
|
||||
"abort": Event;
|
||||
@@ -658,7 +667,7 @@ interface IDBTransactionEventMap {
|
||||
|
||||
interface IDBTransaction extends EventTarget {
|
||||
readonly db: IDBDatabase;
|
||||
readonly error: DOMError;
|
||||
readonly error: DOMException;
|
||||
readonly mode: IDBTransactionMode;
|
||||
onabort: (this: IDBTransaction, ev: Event) => any;
|
||||
oncomplete: (this: IDBTransaction, ev: Event) => any;
|
||||
@@ -678,7 +687,7 @@ declare var IDBTransaction: {
|
||||
readonly READ_ONLY: string;
|
||||
readonly READ_WRITE: string;
|
||||
readonly VERSION_CHANGE: string;
|
||||
}
|
||||
};
|
||||
|
||||
interface IDBVersionChangeEvent extends Event {
|
||||
readonly newVersion: number | null;
|
||||
@@ -688,7 +697,7 @@ interface IDBVersionChangeEvent extends Event {
|
||||
declare var IDBVersionChangeEvent: {
|
||||
prototype: IDBVersionChangeEvent;
|
||||
new(): IDBVersionChangeEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface ImageData {
|
||||
data: Uint8ClampedArray;
|
||||
@@ -700,7 +709,7 @@ declare var ImageData: {
|
||||
prototype: ImageData;
|
||||
new(width: number, height: number): ImageData;
|
||||
new(array: Uint8ClampedArray, width: number, height: number): ImageData;
|
||||
}
|
||||
};
|
||||
|
||||
interface MessageChannel {
|
||||
readonly port1: MessagePort;
|
||||
@@ -710,7 +719,7 @@ interface MessageChannel {
|
||||
declare var MessageChannel: {
|
||||
prototype: MessageChannel;
|
||||
new(): MessageChannel;
|
||||
}
|
||||
};
|
||||
|
||||
interface MessageEvent extends Event {
|
||||
readonly data: any;
|
||||
@@ -723,7 +732,7 @@ interface MessageEvent extends Event {
|
||||
declare var MessageEvent: {
|
||||
prototype: MessageEvent;
|
||||
new(type: string, eventInitDict?: MessageEventInit): MessageEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface MessagePortEventMap {
|
||||
"message": MessageEvent;
|
||||
@@ -741,7 +750,7 @@ interface MessagePort extends EventTarget {
|
||||
declare var MessagePort: {
|
||||
prototype: MessagePort;
|
||||
new(): MessagePort;
|
||||
}
|
||||
};
|
||||
|
||||
interface NotificationEventMap {
|
||||
"click": Event;
|
||||
@@ -771,7 +780,7 @@ declare var Notification: {
|
||||
prototype: Notification;
|
||||
new(title: string, options?: NotificationOptions): Notification;
|
||||
requestPermission(callback?: NotificationPermissionCallback): Promise<NotificationPermission>;
|
||||
}
|
||||
};
|
||||
|
||||
interface Performance {
|
||||
readonly navigation: PerformanceNavigation;
|
||||
@@ -794,7 +803,7 @@ interface Performance {
|
||||
declare var Performance: {
|
||||
prototype: Performance;
|
||||
new(): Performance;
|
||||
}
|
||||
};
|
||||
|
||||
interface PerformanceNavigation {
|
||||
readonly redirectCount: number;
|
||||
@@ -813,18 +822,18 @@ declare var PerformanceNavigation: {
|
||||
readonly TYPE_NAVIGATE: number;
|
||||
readonly TYPE_RELOAD: number;
|
||||
readonly TYPE_RESERVED: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface PerformanceTiming {
|
||||
readonly connectEnd: number;
|
||||
readonly connectStart: number;
|
||||
readonly domainLookupEnd: number;
|
||||
readonly domainLookupStart: number;
|
||||
readonly domComplete: number;
|
||||
readonly domContentLoadedEventEnd: number;
|
||||
readonly domContentLoadedEventStart: number;
|
||||
readonly domInteractive: number;
|
||||
readonly domLoading: number;
|
||||
readonly domainLookupEnd: number;
|
||||
readonly domainLookupStart: number;
|
||||
readonly fetchStart: number;
|
||||
readonly loadEventEnd: number;
|
||||
readonly loadEventStart: number;
|
||||
@@ -844,7 +853,7 @@ interface PerformanceTiming {
|
||||
declare var PerformanceTiming: {
|
||||
prototype: PerformanceTiming;
|
||||
new(): PerformanceTiming;
|
||||
}
|
||||
};
|
||||
|
||||
interface Position {
|
||||
readonly coords: Coordinates;
|
||||
@@ -854,7 +863,7 @@ interface Position {
|
||||
declare var Position: {
|
||||
prototype: Position;
|
||||
new(): Position;
|
||||
}
|
||||
};
|
||||
|
||||
interface PositionError {
|
||||
readonly code: number;
|
||||
@@ -871,7 +880,7 @@ declare var PositionError: {
|
||||
readonly PERMISSION_DENIED: number;
|
||||
readonly POSITION_UNAVAILABLE: number;
|
||||
readonly TIMEOUT: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface ProgressEvent extends Event {
|
||||
readonly lengthComputable: boolean;
|
||||
@@ -883,7 +892,7 @@ interface ProgressEvent extends Event {
|
||||
declare var ProgressEvent: {
|
||||
prototype: ProgressEvent;
|
||||
new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface PushManager {
|
||||
getSubscription(): Promise<PushSubscription>;
|
||||
@@ -894,7 +903,7 @@ interface PushManager {
|
||||
declare var PushManager: {
|
||||
prototype: PushManager;
|
||||
new(): PushManager;
|
||||
}
|
||||
};
|
||||
|
||||
interface PushSubscription {
|
||||
readonly endpoint: USVString;
|
||||
@@ -907,7 +916,7 @@ interface PushSubscription {
|
||||
declare var PushSubscription: {
|
||||
prototype: PushSubscription;
|
||||
new(): PushSubscription;
|
||||
}
|
||||
};
|
||||
|
||||
interface PushSubscriptionOptions {
|
||||
readonly applicationServerKey: ArrayBuffer | null;
|
||||
@@ -917,7 +926,7 @@ interface PushSubscriptionOptions {
|
||||
declare var PushSubscriptionOptions: {
|
||||
prototype: PushSubscriptionOptions;
|
||||
new(): PushSubscriptionOptions;
|
||||
}
|
||||
};
|
||||
|
||||
interface ReadableStream {
|
||||
readonly locked: boolean;
|
||||
@@ -928,7 +937,7 @@ interface ReadableStream {
|
||||
declare var ReadableStream: {
|
||||
prototype: ReadableStream;
|
||||
new(): ReadableStream;
|
||||
}
|
||||
};
|
||||
|
||||
interface ReadableStreamReader {
|
||||
cancel(): Promise<void>;
|
||||
@@ -939,7 +948,7 @@ interface ReadableStreamReader {
|
||||
declare var ReadableStreamReader: {
|
||||
prototype: ReadableStreamReader;
|
||||
new(): ReadableStreamReader;
|
||||
}
|
||||
};
|
||||
|
||||
interface Request extends Object, Body {
|
||||
readonly cache: RequestCache;
|
||||
@@ -961,7 +970,7 @@ interface Request extends Object, Body {
|
||||
declare var Request: {
|
||||
prototype: Request;
|
||||
new(input: Request | string, init?: RequestInit): Request;
|
||||
}
|
||||
};
|
||||
|
||||
interface Response extends Object, Body {
|
||||
readonly body: ReadableStream | null;
|
||||
@@ -977,7 +986,9 @@ interface Response extends Object, Body {
|
||||
declare var Response: {
|
||||
prototype: Response;
|
||||
new(body?: any, init?: ResponseInit): Response;
|
||||
}
|
||||
error: () => Response;
|
||||
redirect: (url: string, status?: number) => Response;
|
||||
};
|
||||
|
||||
interface ServiceWorkerEventMap extends AbstractWorkerEventMap {
|
||||
"statechange": Event;
|
||||
@@ -995,7 +1006,7 @@ interface ServiceWorker extends EventTarget, AbstractWorker {
|
||||
declare var ServiceWorker: {
|
||||
prototype: ServiceWorker;
|
||||
new(): ServiceWorker;
|
||||
}
|
||||
};
|
||||
|
||||
interface ServiceWorkerRegistrationEventMap {
|
||||
"updatefound": Event;
|
||||
@@ -1020,7 +1031,7 @@ interface ServiceWorkerRegistration extends EventTarget {
|
||||
declare var ServiceWorkerRegistration: {
|
||||
prototype: ServiceWorkerRegistration;
|
||||
new(): ServiceWorkerRegistration;
|
||||
}
|
||||
};
|
||||
|
||||
interface SyncManager {
|
||||
getTags(): any;
|
||||
@@ -1030,7 +1041,7 @@ interface SyncManager {
|
||||
declare var SyncManager: {
|
||||
prototype: SyncManager;
|
||||
new(): SyncManager;
|
||||
}
|
||||
};
|
||||
|
||||
interface URL {
|
||||
hash: string;
|
||||
@@ -1053,7 +1064,7 @@ declare var URL: {
|
||||
new(url: string, base?: string): URL;
|
||||
createObjectURL(object: any, options?: ObjectURLOptions): string;
|
||||
revokeObjectURL(url: string): void;
|
||||
}
|
||||
};
|
||||
|
||||
interface WebSocketEventMap {
|
||||
"close": CloseEvent;
|
||||
@@ -1090,7 +1101,7 @@ declare var WebSocket: {
|
||||
readonly CLOSING: number;
|
||||
readonly CONNECTING: number;
|
||||
readonly OPEN: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface WorkerEventMap extends AbstractWorkerEventMap {
|
||||
"message": MessageEvent;
|
||||
@@ -1107,7 +1118,7 @@ interface Worker extends EventTarget, AbstractWorker {
|
||||
declare var Worker: {
|
||||
prototype: Worker;
|
||||
new(stringUrl: string): Worker;
|
||||
}
|
||||
};
|
||||
|
||||
interface XMLHttpRequestEventMap extends XMLHttpRequestEventTargetEventMap {
|
||||
"readystatechange": Event;
|
||||
@@ -1153,7 +1164,7 @@ declare var XMLHttpRequest: {
|
||||
readonly LOADING: number;
|
||||
readonly OPENED: number;
|
||||
readonly UNSENT: number;
|
||||
}
|
||||
};
|
||||
|
||||
interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {
|
||||
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;
|
||||
@@ -1163,7 +1174,7 @@ interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {
|
||||
declare var XMLHttpRequestUpload: {
|
||||
prototype: XMLHttpRequestUpload;
|
||||
new(): XMLHttpRequestUpload;
|
||||
}
|
||||
};
|
||||
|
||||
interface AbstractWorkerEventMap {
|
||||
"error": ErrorEvent;
|
||||
@@ -1278,7 +1289,7 @@ interface Client {
|
||||
declare var Client: {
|
||||
prototype: Client;
|
||||
new(): Client;
|
||||
}
|
||||
};
|
||||
|
||||
interface Clients {
|
||||
claim(): Promise<void>;
|
||||
@@ -1290,7 +1301,7 @@ interface Clients {
|
||||
declare var Clients: {
|
||||
prototype: Clients;
|
||||
new(): Clients;
|
||||
}
|
||||
};
|
||||
|
||||
interface DedicatedWorkerGlobalScopeEventMap extends WorkerGlobalScopeEventMap {
|
||||
"message": MessageEvent;
|
||||
@@ -1307,7 +1318,7 @@ interface DedicatedWorkerGlobalScope extends WorkerGlobalScope {
|
||||
declare var DedicatedWorkerGlobalScope: {
|
||||
prototype: DedicatedWorkerGlobalScope;
|
||||
new(): DedicatedWorkerGlobalScope;
|
||||
}
|
||||
};
|
||||
|
||||
interface ExtendableEvent extends Event {
|
||||
waitUntil(f: Promise<any>): void;
|
||||
@@ -1316,7 +1327,7 @@ interface ExtendableEvent extends Event {
|
||||
declare var ExtendableEvent: {
|
||||
prototype: ExtendableEvent;
|
||||
new(type: string, eventInitDict?: ExtendableEventInit): ExtendableEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface ExtendableMessageEvent extends ExtendableEvent {
|
||||
readonly data: any;
|
||||
@@ -1329,7 +1340,7 @@ interface ExtendableMessageEvent extends ExtendableEvent {
|
||||
declare var ExtendableMessageEvent: {
|
||||
prototype: ExtendableMessageEvent;
|
||||
new(type: string, eventInitDict?: ExtendableMessageEventInit): ExtendableMessageEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface FetchEvent extends ExtendableEvent {
|
||||
readonly clientId: string | null;
|
||||
@@ -1341,7 +1352,7 @@ interface FetchEvent extends ExtendableEvent {
|
||||
declare var FetchEvent: {
|
||||
prototype: FetchEvent;
|
||||
new(type: string, eventInitDict: FetchEventInit): FetchEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface FileReaderSync {
|
||||
readAsArrayBuffer(blob: Blob): any;
|
||||
@@ -1353,7 +1364,7 @@ interface FileReaderSync {
|
||||
declare var FileReaderSync: {
|
||||
prototype: FileReaderSync;
|
||||
new(): FileReaderSync;
|
||||
}
|
||||
};
|
||||
|
||||
interface NotificationEvent extends ExtendableEvent {
|
||||
readonly action: string;
|
||||
@@ -1363,7 +1374,7 @@ interface NotificationEvent extends ExtendableEvent {
|
||||
declare var NotificationEvent: {
|
||||
prototype: NotificationEvent;
|
||||
new(type: string, eventInitDict: NotificationEventInit): NotificationEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface PushEvent extends ExtendableEvent {
|
||||
readonly data: PushMessageData | null;
|
||||
@@ -1372,7 +1383,7 @@ interface PushEvent extends ExtendableEvent {
|
||||
declare var PushEvent: {
|
||||
prototype: PushEvent;
|
||||
new(type: string, eventInitDict?: PushEventInit): PushEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface PushMessageData {
|
||||
arrayBuffer(): ArrayBuffer;
|
||||
@@ -1384,7 +1395,7 @@ interface PushMessageData {
|
||||
declare var PushMessageData: {
|
||||
prototype: PushMessageData;
|
||||
new(): PushMessageData;
|
||||
}
|
||||
};
|
||||
|
||||
interface ServiceWorkerGlobalScopeEventMap extends WorkerGlobalScopeEventMap {
|
||||
"activate": ExtendableEvent;
|
||||
@@ -1418,7 +1429,7 @@ interface ServiceWorkerGlobalScope extends WorkerGlobalScope {
|
||||
declare var ServiceWorkerGlobalScope: {
|
||||
prototype: ServiceWorkerGlobalScope;
|
||||
new(): ServiceWorkerGlobalScope;
|
||||
}
|
||||
};
|
||||
|
||||
interface SyncEvent extends ExtendableEvent {
|
||||
readonly lastChance: boolean;
|
||||
@@ -1428,7 +1439,7 @@ interface SyncEvent extends ExtendableEvent {
|
||||
declare var SyncEvent: {
|
||||
prototype: SyncEvent;
|
||||
new(type: string, init: SyncEventInit): SyncEvent;
|
||||
}
|
||||
};
|
||||
|
||||
interface WindowClient extends Client {
|
||||
readonly focused: boolean;
|
||||
@@ -1440,7 +1451,7 @@ interface WindowClient extends Client {
|
||||
declare var WindowClient: {
|
||||
prototype: WindowClient;
|
||||
new(): WindowClient;
|
||||
}
|
||||
};
|
||||
|
||||
interface WorkerGlobalScopeEventMap {
|
||||
"error": ErrorEvent;
|
||||
@@ -1463,7 +1474,7 @@ interface WorkerGlobalScope extends EventTarget, WorkerUtils, WindowConsole, Glo
|
||||
declare var WorkerGlobalScope: {
|
||||
prototype: WorkerGlobalScope;
|
||||
new(): WorkerGlobalScope;
|
||||
}
|
||||
};
|
||||
|
||||
interface WorkerLocation {
|
||||
readonly hash: string;
|
||||
@@ -1481,7 +1492,7 @@ interface WorkerLocation {
|
||||
declare var WorkerLocation: {
|
||||
prototype: WorkerLocation;
|
||||
new(): WorkerLocation;
|
||||
}
|
||||
};
|
||||
|
||||
interface WorkerNavigator extends Object, NavigatorID, NavigatorOnLine, NavigatorBeacon, NavigatorConcurrentHardware {
|
||||
readonly hardwareConcurrency: number;
|
||||
@@ -1490,7 +1501,7 @@ interface WorkerNavigator extends Object, NavigatorID, NavigatorOnLine, Navigato
|
||||
declare var WorkerNavigator: {
|
||||
prototype: WorkerNavigator;
|
||||
new(): WorkerNavigator;
|
||||
}
|
||||
};
|
||||
|
||||
interface WorkerUtils extends Object, WindowBase64 {
|
||||
readonly indexedDB: IDBFactory;
|
||||
@@ -1533,38 +1544,38 @@ interface ImageBitmap {
|
||||
|
||||
interface URLSearchParams {
|
||||
/**
|
||||
* Appends a specified key/value pair as a new search parameter.
|
||||
*/
|
||||
* Appends a specified key/value pair as a new search parameter.
|
||||
*/
|
||||
append(name: string, value: string): void;
|
||||
/**
|
||||
* Deletes the given search parameter, and its associated value, from the list of all search parameters.
|
||||
*/
|
||||
* Deletes the given search parameter, and its associated value, from the list of all search parameters.
|
||||
*/
|
||||
delete(name: string): void;
|
||||
/**
|
||||
* Returns the first value associated to the given search parameter.
|
||||
*/
|
||||
* Returns the first value associated to the given search parameter.
|
||||
*/
|
||||
get(name: string): string | null;
|
||||
/**
|
||||
* Returns all the values association with a given search parameter.
|
||||
*/
|
||||
* Returns all the values association with a given search parameter.
|
||||
*/
|
||||
getAll(name: string): string[];
|
||||
/**
|
||||
* Returns a Boolean indicating if such a search parameter exists.
|
||||
*/
|
||||
* Returns a Boolean indicating if such a search parameter exists.
|
||||
*/
|
||||
has(name: string): boolean;
|
||||
/**
|
||||
* Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
|
||||
*/
|
||||
* Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
|
||||
*/
|
||||
set(name: string, value: string): void;
|
||||
}
|
||||
|
||||
declare var URLSearchParams: {
|
||||
prototype: URLSearchParams;
|
||||
/**
|
||||
* Constructor returning a URLSearchParams object.
|
||||
*/
|
||||
* Constructor returning a URLSearchParams object.
|
||||
*/
|
||||
new (init?: string | URLSearchParams): URLSearchParams;
|
||||
}
|
||||
};
|
||||
|
||||
interface BlobPropertyBag {
|
||||
type?: string;
|
||||
@@ -1771,8 +1782,23 @@ interface AddEventListenerOptions extends EventListenerOptions {
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface DecodeErrorCallback {
|
||||
(error: DOMException): void;
|
||||
}
|
||||
interface DecodeSuccessCallback {
|
||||
(decodedData: AudioBuffer): void;
|
||||
}
|
||||
interface ErrorEventHandler {
|
||||
(message: string, filename?: string, lineno?: number, colno?: number, error?:Error): void;
|
||||
(message: string, filename?: string, lineno?: number, colno?: number, error?: Error): void;
|
||||
}
|
||||
interface ForEachCallback {
|
||||
(keyId: any, status: MediaKeyStatus): void;
|
||||
}
|
||||
interface FunctionStringCallback {
|
||||
(data: string): void;
|
||||
}
|
||||
interface NotificationPermissionCallback {
|
||||
(permission: NotificationPermission): void;
|
||||
}
|
||||
interface PositionCallback {
|
||||
(position: Position): void;
|
||||
@@ -1780,21 +1806,6 @@ interface PositionCallback {
|
||||
interface PositionErrorCallback {
|
||||
(error: PositionError): void;
|
||||
}
|
||||
interface DecodeSuccessCallback {
|
||||
(decodedData: AudioBuffer): void;
|
||||
}
|
||||
interface DecodeErrorCallback {
|
||||
(error: DOMException): void;
|
||||
}
|
||||
interface FunctionStringCallback {
|
||||
(data: string): void;
|
||||
}
|
||||
interface ForEachCallback {
|
||||
(keyId: any, status: MediaKeyStatus): void;
|
||||
}
|
||||
interface NotificationPermissionCallback {
|
||||
(permission: NotificationPermission): void;
|
||||
}
|
||||
declare var onmessage: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any;
|
||||
declare function close(): void;
|
||||
declare function postMessage(message: any, transfer?: any[]): void;
|
||||
|
||||
Vendored
+180
-95
@@ -2,51 +2,53 @@
|
||||
* Declaration module describing the TypeScript Server protocol
|
||||
*/
|
||||
declare namespace ts.server.protocol {
|
||||
namespace CommandTypes {
|
||||
type Brace = "brace";
|
||||
type BraceCompletion = "braceCompletion";
|
||||
type Change = "change";
|
||||
type Close = "close";
|
||||
type Completions = "completions";
|
||||
type CompletionDetails = "completionEntryDetails";
|
||||
type CompileOnSaveAffectedFileList = "compileOnSaveAffectedFileList";
|
||||
type CompileOnSaveEmitFile = "compileOnSaveEmitFile";
|
||||
type Configure = "configure";
|
||||
type Definition = "definition";
|
||||
type Implementation = "implementation";
|
||||
type Exit = "exit";
|
||||
type Format = "format";
|
||||
type Formatonkey = "formatonkey";
|
||||
type Geterr = "geterr";
|
||||
type GeterrForProject = "geterrForProject";
|
||||
type SemanticDiagnosticsSync = "semanticDiagnosticsSync";
|
||||
type SyntacticDiagnosticsSync = "syntacticDiagnosticsSync";
|
||||
type NavBar = "navbar";
|
||||
type Navto = "navto";
|
||||
type NavTree = "navtree";
|
||||
type NavTreeFull = "navtree-full";
|
||||
type Occurrences = "occurrences";
|
||||
type DocumentHighlights = "documentHighlights";
|
||||
type Open = "open";
|
||||
type Quickinfo = "quickinfo";
|
||||
type References = "references";
|
||||
type Reload = "reload";
|
||||
type Rename = "rename";
|
||||
type Saveto = "saveto";
|
||||
type SignatureHelp = "signatureHelp";
|
||||
type TypeDefinition = "typeDefinition";
|
||||
type ProjectInfo = "projectInfo";
|
||||
type ReloadProjects = "reloadProjects";
|
||||
type Unknown = "unknown";
|
||||
type OpenExternalProject = "openExternalProject";
|
||||
type OpenExternalProjects = "openExternalProjects";
|
||||
type CloseExternalProject = "closeExternalProject";
|
||||
type TodoComments = "todoComments";
|
||||
type Indentation = "indentation";
|
||||
type DocCommentTemplate = "docCommentTemplate";
|
||||
type CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects";
|
||||
type GetCodeFixes = "getCodeFixes";
|
||||
type GetSupportedCodeFixes = "getSupportedCodeFixes";
|
||||
const enum CommandTypes {
|
||||
Brace = "brace",
|
||||
BraceCompletion = "braceCompletion",
|
||||
Change = "change",
|
||||
Close = "close",
|
||||
Completions = "completions",
|
||||
CompletionDetails = "completionEntryDetails",
|
||||
CompileOnSaveAffectedFileList = "compileOnSaveAffectedFileList",
|
||||
CompileOnSaveEmitFile = "compileOnSaveEmitFile",
|
||||
Configure = "configure",
|
||||
Definition = "definition",
|
||||
Implementation = "implementation",
|
||||
Exit = "exit",
|
||||
Format = "format",
|
||||
Formatonkey = "formatonkey",
|
||||
Geterr = "geterr",
|
||||
GeterrForProject = "geterrForProject",
|
||||
SemanticDiagnosticsSync = "semanticDiagnosticsSync",
|
||||
SyntacticDiagnosticsSync = "syntacticDiagnosticsSync",
|
||||
NavBar = "navbar",
|
||||
Navto = "navto",
|
||||
NavTree = "navtree",
|
||||
NavTreeFull = "navtree-full",
|
||||
Occurrences = "occurrences",
|
||||
DocumentHighlights = "documentHighlights",
|
||||
Open = "open",
|
||||
Quickinfo = "quickinfo",
|
||||
References = "references",
|
||||
Reload = "reload",
|
||||
Rename = "rename",
|
||||
Saveto = "saveto",
|
||||
SignatureHelp = "signatureHelp",
|
||||
TypeDefinition = "typeDefinition",
|
||||
ProjectInfo = "projectInfo",
|
||||
ReloadProjects = "reloadProjects",
|
||||
Unknown = "unknown",
|
||||
OpenExternalProject = "openExternalProject",
|
||||
OpenExternalProjects = "openExternalProjects",
|
||||
CloseExternalProject = "closeExternalProject",
|
||||
TodoComments = "todoComments",
|
||||
Indentation = "indentation",
|
||||
DocCommentTemplate = "docCommentTemplate",
|
||||
CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects",
|
||||
GetCodeFixes = "getCodeFixes",
|
||||
GetSupportedCodeFixes = "getSupportedCodeFixes",
|
||||
GetApplicableRefactors = "getApplicableRefactors",
|
||||
GetEditsForRefactor = "getEditsForRefactor",
|
||||
}
|
||||
/**
|
||||
* A TypeScript Server message
|
||||
@@ -287,6 +289,85 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
offset: number;
|
||||
}
|
||||
type FileLocationOrRangeRequestArgs = FileLocationRequestArgs | FileRangeRequestArgs;
|
||||
/**
|
||||
* Request refactorings at a given position or selection area.
|
||||
*/
|
||||
interface GetApplicableRefactorsRequest extends Request {
|
||||
command: CommandTypes.GetApplicableRefactors;
|
||||
arguments: GetApplicableRefactorsRequestArgs;
|
||||
}
|
||||
type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs;
|
||||
/**
|
||||
* Response is a list of available refactorings.
|
||||
* Each refactoring exposes one or more "Actions"; a user selects one action to invoke a refactoring
|
||||
*/
|
||||
interface GetApplicableRefactorsResponse extends Response {
|
||||
body?: ApplicableRefactorInfo[];
|
||||
}
|
||||
/**
|
||||
* A set of one or more available refactoring actions, grouped under a parent refactoring.
|
||||
*/
|
||||
interface ApplicableRefactorInfo {
|
||||
/**
|
||||
* The programmatic name of the refactoring
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A description of this refactoring category to show to the user.
|
||||
* If the refactoring gets inlined (see below), this text will not be visible.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* Inlineable refactorings can have their actions hoisted out to the top level
|
||||
* of a context menu. Non-inlineanable refactorings should always be shown inside
|
||||
* their parent grouping.
|
||||
*
|
||||
* If not specified, this value is assumed to be 'true'
|
||||
*/
|
||||
inlineable?: boolean;
|
||||
actions: RefactorActionInfo[];
|
||||
}
|
||||
/**
|
||||
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
|
||||
* offer several actions, each corresponding to a surround class or closure to extract into.
|
||||
*/
|
||||
type RefactorActionInfo = {
|
||||
/**
|
||||
* The programmatic name of the refactoring action
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A description of this refactoring action to show to the user.
|
||||
* If the parent refactoring is inlined away, this will be the only text shown,
|
||||
* so this description should make sense by itself if the parent is inlineable=true
|
||||
*/
|
||||
description: string;
|
||||
};
|
||||
interface GetEditsForRefactorRequest extends Request {
|
||||
command: CommandTypes.GetEditsForRefactor;
|
||||
arguments: GetEditsForRefactorRequestArgs;
|
||||
}
|
||||
/**
|
||||
* Request the edits that a particular refactoring action produces.
|
||||
* Callers must specify the name of the refactor and the name of the action.
|
||||
*/
|
||||
type GetEditsForRefactorRequestArgs = FileLocationOrRangeRequestArgs & {
|
||||
refactor: string;
|
||||
action: string;
|
||||
};
|
||||
interface GetEditsForRefactorResponse extends Response {
|
||||
body?: RefactorEditInfo;
|
||||
}
|
||||
type RefactorEditInfo = {
|
||||
edits: FileCodeEdits[];
|
||||
/**
|
||||
* An optional location where the editor should start a rename operation once
|
||||
* the refactoring edits have been applied
|
||||
*/
|
||||
renameLocation?: Location;
|
||||
renameFilename?: string;
|
||||
};
|
||||
/**
|
||||
* Request for the available codefixes at a specific position.
|
||||
*/
|
||||
@@ -294,10 +375,7 @@ declare namespace ts.server.protocol {
|
||||
command: CommandTypes.GetCodeFixes;
|
||||
arguments: CodeFixRequestArgs;
|
||||
}
|
||||
/**
|
||||
* Instances of this interface specify errorcodes on a specific location in a sourcefile.
|
||||
*/
|
||||
interface CodeFixRequestArgs extends FileRequestArgs {
|
||||
interface FileRangeRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* The line number for the request (1-based).
|
||||
*/
|
||||
@@ -314,6 +392,11 @@ declare namespace ts.server.protocol {
|
||||
* The character offset (on the line) for the request (1-based).
|
||||
*/
|
||||
endOffset: number;
|
||||
}
|
||||
/**
|
||||
* Instances of this interface specify errorcodes on a specific location in a sourcefile.
|
||||
*/
|
||||
interface CodeFixRequestArgs extends FileRangeRequestArgs {
|
||||
/**
|
||||
* Errorcodes we want to get the fixes for.
|
||||
*/
|
||||
@@ -394,7 +477,7 @@ declare namespace ts.server.protocol {
|
||||
command: CommandTypes.Implementation;
|
||||
}
|
||||
/**
|
||||
* Location in source code expressed as (one-based) line and character offset.
|
||||
* Location in source code expressed as (one-based) line and (one-based) column offset.
|
||||
*/
|
||||
interface Location {
|
||||
line: number;
|
||||
@@ -488,10 +571,9 @@ declare namespace ts.server.protocol {
|
||||
}
|
||||
/**
|
||||
* Span augmented with extra information that denotes the kind of the highlighting to be used for span.
|
||||
* Kind is taken from HighlightSpanKind type.
|
||||
*/
|
||||
interface HighlightSpan extends TextSpan {
|
||||
kind: string;
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
/**
|
||||
* Represents a set of highligh spans for a give name
|
||||
@@ -609,7 +691,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The items's kind (such as 'className' or 'parameterName' or plain 'text').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
@@ -957,7 +1039,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName' or plain 'text').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
@@ -1143,7 +1225,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
@@ -1170,7 +1252,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
@@ -1417,6 +1499,12 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
source?: string;
|
||||
}
|
||||
interface DiagnosticWithFileName extends Diagnostic {
|
||||
/**
|
||||
* Name of the file the diagnostic is in
|
||||
*/
|
||||
fileName: string;
|
||||
}
|
||||
interface DiagnosticEventBody {
|
||||
/**
|
||||
* The file for which diagnostic information is reported.
|
||||
@@ -1446,7 +1534,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* An arry of diagnostic information items for the found config file.
|
||||
*/
|
||||
diagnostics: Diagnostic[];
|
||||
diagnostics: DiagnosticWithFileName[];
|
||||
}
|
||||
/**
|
||||
* Event message for "configFileDiag" event type.
|
||||
@@ -1563,7 +1651,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* exact, substring, or prefix.
|
||||
*/
|
||||
@@ -1596,7 +1684,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* Kind of symbol's container symbol (if any).
|
||||
*/
|
||||
containerKind?: string;
|
||||
containerKind?: ScriptElementKind;
|
||||
}
|
||||
/**
|
||||
* Navto response message. Body is an array of navto items. Each
|
||||
@@ -1660,7 +1748,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* The symbol's kind (such as 'className' or 'parameterName').
|
||||
*/
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
/**
|
||||
* Optional modifiers for the kind (such as 'public').
|
||||
*/
|
||||
@@ -1681,7 +1769,7 @@ declare namespace ts.server.protocol {
|
||||
/** protocol.NavigationTree is identical to ts.NavigationTree, except using protocol.TextSpan instead of ts.TextSpan */
|
||||
interface NavigationTree {
|
||||
text: string;
|
||||
kind: string;
|
||||
kind: ScriptElementKind;
|
||||
kindModifiers: string;
|
||||
spans: TextSpan[];
|
||||
childItems?: NavigationTree[];
|
||||
@@ -1756,12 +1844,11 @@ declare namespace ts.server.protocol {
|
||||
interface NavTreeResponse extends Response {
|
||||
body?: NavigationTree;
|
||||
}
|
||||
namespace IndentStyle {
|
||||
type None = "None";
|
||||
type Block = "Block";
|
||||
type Smart = "Smart";
|
||||
const enum IndentStyle {
|
||||
None = "None",
|
||||
Block = "Block",
|
||||
Smart = "Smart",
|
||||
}
|
||||
type IndentStyle = IndentStyle.None | IndentStyle.Block | IndentStyle.Smart;
|
||||
interface EditorSettings {
|
||||
baseIndentSize?: number;
|
||||
indentSize?: number;
|
||||
@@ -1782,6 +1869,7 @@ declare namespace ts.server.protocol {
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
|
||||
insertSpaceAfterTypeAssertion?: boolean;
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
placeOpenBraceOnNewLineForFunctions?: boolean;
|
||||
placeOpenBraceOnNewLineForControlBlocks?: boolean;
|
||||
@@ -1854,40 +1942,35 @@ declare namespace ts.server.protocol {
|
||||
typeRoots?: string[];
|
||||
[option: string]: CompilerOptionsValue | undefined;
|
||||
}
|
||||
namespace JsxEmit {
|
||||
type None = "None";
|
||||
type Preserve = "Preserve";
|
||||
type ReactNative = "ReactNative";
|
||||
type React = "React";
|
||||
const enum JsxEmit {
|
||||
None = "None",
|
||||
Preserve = "Preserve",
|
||||
ReactNative = "ReactNative",
|
||||
React = "React",
|
||||
}
|
||||
type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React | JsxEmit.ReactNative;
|
||||
namespace ModuleKind {
|
||||
type None = "None";
|
||||
type CommonJS = "CommonJS";
|
||||
type AMD = "AMD";
|
||||
type UMD = "UMD";
|
||||
type System = "System";
|
||||
type ES6 = "ES6";
|
||||
type ES2015 = "ES2015";
|
||||
const enum ModuleKind {
|
||||
None = "None",
|
||||
CommonJS = "CommonJS",
|
||||
AMD = "AMD",
|
||||
UMD = "UMD",
|
||||
System = "System",
|
||||
ES6 = "ES6",
|
||||
ES2015 = "ES2015",
|
||||
}
|
||||
type ModuleKind = ModuleKind.None | ModuleKind.CommonJS | ModuleKind.AMD | ModuleKind.UMD | ModuleKind.System | ModuleKind.ES6 | ModuleKind.ES2015;
|
||||
namespace ModuleResolutionKind {
|
||||
type Classic = "Classic";
|
||||
type Node = "Node";
|
||||
const enum ModuleResolutionKind {
|
||||
Classic = "Classic",
|
||||
Node = "Node",
|
||||
}
|
||||
type ModuleResolutionKind = ModuleResolutionKind.Classic | ModuleResolutionKind.Node;
|
||||
namespace NewLineKind {
|
||||
type Crlf = "Crlf";
|
||||
type Lf = "Lf";
|
||||
const enum NewLineKind {
|
||||
Crlf = "Crlf",
|
||||
Lf = "Lf",
|
||||
}
|
||||
type NewLineKind = NewLineKind.Crlf | NewLineKind.Lf;
|
||||
namespace ScriptTarget {
|
||||
type ES3 = "ES3";
|
||||
type ES5 = "ES5";
|
||||
type ES6 = "ES6";
|
||||
type ES2015 = "ES2015";
|
||||
const enum ScriptTarget {
|
||||
ES3 = "ES3",
|
||||
ES5 = "ES5",
|
||||
ES6 = "ES6",
|
||||
ES2015 = "ES2015",
|
||||
}
|
||||
type ScriptTarget = ScriptTarget.ES3 | ScriptTarget.ES5 | ScriptTarget.ES6 | ScriptTarget.ES2015;
|
||||
}
|
||||
declare namespace ts.server.protocol {
|
||||
|
||||
@@ -1943,6 +2026,8 @@ declare namespace ts.server.protocol {
|
||||
}
|
||||
declare namespace ts {
|
||||
// these types are empty stubs for types from services and should not be used directly
|
||||
export type HighlightSpanKind = never;
|
||||
export type ScriptElementKind = never;
|
||||
export type ScriptKind = never;
|
||||
export type IndentStyle = never;
|
||||
export type JsxEmit = never;
|
||||
|
||||
+33323
-31037
File diff suppressed because it is too large
Load Diff
+36816
-32905
File diff suppressed because it is too large
Load Diff
Vendored
+973
-762
File diff suppressed because it is too large
Load Diff
+39450
-35580
File diff suppressed because it is too large
Load Diff
Vendored
+866
-464
File diff suppressed because it is too large
Load Diff
+42750
-38443
File diff suppressed because it is too large
Load Diff
Vendored
+866
-464
File diff suppressed because it is too large
Load Diff
+42750
-38443
File diff suppressed because it is too large
Load Diff
+11844
-1496
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
"use strict";
|
||||
if (process.argv.length < 3) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,6 +17,6 @@ nodeVersions.each { nodeVer ->
|
||||
}
|
||||
|
||||
Utilities.standardJobSetup(newJob, project, true, "*/${branch}")
|
||||
Utilities.setMachineAffinity(newJob, 'Ubuntu', '20161020')
|
||||
Utilities.setMachineAffinity(newJob, 'Ubuntu14.04', '20161020')
|
||||
Utilities.addGithubPRTriggerForBranch(newJob, branch, "TypeScript Test Run ${newJobName}")
|
||||
}
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@
|
||||
"name": "typescript",
|
||||
"author": "Microsoft Corp.",
|
||||
"homepage": "http://typescriptlang.org/",
|
||||
"version": "2.5.0",
|
||||
"version": "2.6.0",
|
||||
"license": "Apache-2.0",
|
||||
"description": "TypeScript is a language for application scale JavaScript development",
|
||||
"keywords": [
|
||||
@@ -60,7 +60,6 @@
|
||||
"gulp-newer": "latest",
|
||||
"gulp-sourcemaps": "latest",
|
||||
"gulp-typescript": "latest",
|
||||
"into-stream": "latest",
|
||||
"istanbul": "latest",
|
||||
"jake": "latest",
|
||||
"merge2": "latest",
|
||||
@@ -91,9 +90,11 @@
|
||||
"setup-hooks": "node scripts/link-hooks.js"
|
||||
},
|
||||
"browser": {
|
||||
"buffer": false,
|
||||
"fs": false,
|
||||
"os": false,
|
||||
"path": false
|
||||
},
|
||||
"dependencies": {
|
||||
"browser-resolve": "^1.11.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,15 @@ function endsWith(s: string, suffix: string) {
|
||||
return s.lastIndexOf(suffix, s.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
function isStringEnum(declaration: ts.EnumDeclaration) {
|
||||
return declaration.members.length && declaration.members.every(m => m.initializer && m.initializer.kind === ts.SyntaxKind.StringLiteral);
|
||||
}
|
||||
|
||||
class DeclarationsWalker {
|
||||
private visitedTypes: ts.Type[] = [];
|
||||
private text = "";
|
||||
private removedTypes: ts.Type[] = [];
|
||||
|
||||
|
||||
private constructor(private typeChecker: ts.TypeChecker, private protocolFile: ts.SourceFile) {
|
||||
}
|
||||
|
||||
@@ -19,7 +23,7 @@ class DeclarationsWalker {
|
||||
let text = "declare namespace ts.server.protocol {\n";
|
||||
var walker = new DeclarationsWalker(typeChecker, protocolFile);
|
||||
walker.visitTypeNodes(protocolFile);
|
||||
text = walker.text
|
||||
text = walker.text
|
||||
? `declare namespace ts.server.protocol {\n${walker.text}}`
|
||||
: "";
|
||||
if (walker.removedTypes) {
|
||||
@@ -52,7 +56,7 @@ class DeclarationsWalker {
|
||||
if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") {
|
||||
return;
|
||||
}
|
||||
if (decl.kind === ts.SyntaxKind.EnumDeclaration) {
|
||||
if (decl.kind === ts.SyntaxKind.EnumDeclaration && !isStringEnum(decl as ts.EnumDeclaration)) {
|
||||
this.removedTypes.push(type);
|
||||
return;
|
||||
}
|
||||
@@ -91,7 +95,7 @@ class DeclarationsWalker {
|
||||
for (const type of heritageClauses[0].types) {
|
||||
this.processTypeOfNode(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +114,7 @@ class DeclarationsWalker {
|
||||
this.processType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptServicesDts: string) {
|
||||
|
||||
+34
-24
@@ -19,47 +19,57 @@ function main(): void {
|
||||
|
||||
// Acquire the version from the package.json file and modify it appropriately.
|
||||
const packageJsonFilePath = ts.normalizePath(sys.args[0]);
|
||||
const packageJsonContents = sys.readFile(packageJsonFilePath);
|
||||
const packageJsonValue: PackageJson = JSON.parse(packageJsonContents);
|
||||
const packageJsonValue: PackageJson = JSON.parse(sys.readFile(packageJsonFilePath));
|
||||
|
||||
const nightlyVersion = getNightlyVersionString(packageJsonValue.version);
|
||||
|
||||
// Modify the package.json structure
|
||||
packageJsonValue.version = nightlyVersion;
|
||||
const { majorMinor, patch } = parsePackageJsonVersion(packageJsonValue.version);
|
||||
const nightlyPatch = getNightlyPatch(patch);
|
||||
|
||||
// Acquire and modify the source file that exposes the version string.
|
||||
const tsFilePath = ts.normalizePath(sys.args[1]);
|
||||
const tsFileContents = sys.readFile(tsFilePath);
|
||||
const versionAssignmentRegExp = /export\s+const\s+version\s+=\s+".*";/;
|
||||
const modifiedTsFileContents = tsFileContents.replace(versionAssignmentRegExp, `export const version = "${nightlyVersion}";`);
|
||||
const tsFileContents = ts.sys.readFile(tsFilePath);
|
||||
const modifiedTsFileContents = updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, nightlyPatch);
|
||||
|
||||
// Ensure we are actually changing something - the user probably wants to know that the update failed.
|
||||
if (tsFileContents === modifiedTsFileContents) {
|
||||
let err = `\n '${tsFilePath}' was not updated while configuring for a nightly publish.\n `;
|
||||
|
||||
if (tsFileContents.match(versionAssignmentRegExp)) {
|
||||
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
|
||||
}
|
||||
else {
|
||||
err += `The file seems to no longer have a string matching '${versionAssignmentRegExp}'.`;
|
||||
}
|
||||
|
||||
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
|
||||
throw err + "\n";
|
||||
}
|
||||
|
||||
// Finally write the changes to disk.
|
||||
// Modify the package.json structure
|
||||
packageJsonValue.version = `${majorMinor}.${nightlyPatch}`;
|
||||
sys.writeFile(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4))
|
||||
sys.writeFile(tsFilePath, modifiedTsFileContents);
|
||||
}
|
||||
|
||||
function getNightlyVersionString(versionString: string): string {
|
||||
// If the version string already contains "-nightly",
|
||||
// then get the base string and update based on that.
|
||||
const dashNightlyPos = versionString.indexOf("-dev");
|
||||
if (dashNightlyPos >= 0) {
|
||||
versionString = versionString.slice(0, dashNightlyPos);
|
||||
function updateTsFile(tsFilePath: string, tsFileContents: string, majorMinor: string, patch: string, nightlyPatch: string): string {
|
||||
const majorMinorRgx = /export const versionMajorMinor = "(\d+\.\d+)"/;
|
||||
const majorMinorMatch = majorMinorRgx.exec(tsFileContents);
|
||||
ts.Debug.assert(majorMinorMatch !== null, "", () => `The file seems to no longer have a string matching '${majorMinorRgx}'.`);
|
||||
const parsedMajorMinor = majorMinorMatch[1];
|
||||
ts.Debug.assert(parsedMajorMinor === majorMinor, "versionMajorMinor does not match.", () => `${tsFilePath}: '${parsedMajorMinor}'; package.json: '${majorMinor}'`);
|
||||
|
||||
const versionRgx = /export const version = `\$\{versionMajorMinor\}\.(\d)`;/;
|
||||
const patchMatch = versionRgx.exec(tsFileContents);
|
||||
ts.Debug.assert(patchMatch !== null, "The file seems to no longer have a string matching", () => versionRgx.toString());
|
||||
const parsedPatch = patchMatch[1];
|
||||
if (parsedPatch !== patch) {
|
||||
throw new Error(`patch does not match. ${tsFilePath}: '${parsedPatch}; package.json: '${patch}'`);
|
||||
}
|
||||
|
||||
return tsFileContents.replace(versionRgx, `export const version = \`\${versionMajorMinor}.${nightlyPatch}\`;`);
|
||||
}
|
||||
|
||||
function parsePackageJsonVersion(versionString: string): { majorMinor: string, patch: string } {
|
||||
const versionRgx = /(\d+\.\d+)\.(\d+)($|\-)/;
|
||||
const match = versionString.match(versionRgx);
|
||||
ts.Debug.assert(match !== null, "package.json 'version' should match", () => versionRgx.toString());
|
||||
return { majorMinor: match[1], patch: match[2] };
|
||||
}
|
||||
|
||||
/** e.g. 0-dev.20170707 */
|
||||
function getNightlyPatch(plainPatch: string): string {
|
||||
// We're going to append a representation of the current time at the end of the current version.
|
||||
// String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
|
||||
// but we'd prefer to just remove separators and limit ourselves to YYYYMMDD.
|
||||
@@ -67,7 +77,7 @@ function getNightlyVersionString(versionString: string): string {
|
||||
const now = new Date();
|
||||
const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 8);
|
||||
|
||||
return `${versionString}-dev.${timeStr}`;
|
||||
return `${plainPatch}-dev.${timeStr}`;
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -6,9 +6,7 @@ interface DiagnosticDetails {
|
||||
isEarly?: boolean;
|
||||
}
|
||||
|
||||
interface InputDiagnosticMessageTable {
|
||||
[msg: string]: DiagnosticDetails;
|
||||
}
|
||||
type InputDiagnosticMessageTable = ts.Map<DiagnosticDetails>;
|
||||
|
||||
function main(): void {
|
||||
var sys = ts.sys;
|
||||
@@ -28,101 +26,66 @@ function main(): void {
|
||||
var inputFilePath = sys.args[0].replace(/\\/g, "/");
|
||||
var inputStr = sys.readFile(inputFilePath);
|
||||
|
||||
var diagnosticMessages: InputDiagnosticMessageTable = JSON.parse(inputStr);
|
||||
var diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr);
|
||||
// Check that there are no duplicates.
|
||||
const seenNames = ts.createMap<true>();
|
||||
for (const name of Object.keys(diagnosticMessagesJson)) {
|
||||
if (seenNames.has(name))
|
||||
throw new Error(`Name ${name} appears twice`);
|
||||
seenNames.set(name, true);
|
||||
}
|
||||
|
||||
var names = Utilities.getObjectKeys(diagnosticMessages);
|
||||
var nameMap = buildUniqueNameMap(names);
|
||||
const diagnosticMessages: InputDiagnosticMessageTable = ts.createMapFromTemplate(diagnosticMessagesJson);
|
||||
|
||||
var infoFileOutput = buildInfoFileOutput(diagnosticMessages, nameMap);
|
||||
checkForUniqueCodes(names, diagnosticMessages);
|
||||
var infoFileOutput = buildInfoFileOutput(diagnosticMessages);
|
||||
checkForUniqueCodes(diagnosticMessages);
|
||||
writeFile("diagnosticInformationMap.generated.ts", infoFileOutput);
|
||||
|
||||
var messageOutput = buildDiagnosticMessageOutput(diagnosticMessages, nameMap);
|
||||
var messageOutput = buildDiagnosticMessageOutput(diagnosticMessages);
|
||||
writeFile("diagnosticMessages.generated.json", messageOutput);
|
||||
}
|
||||
|
||||
function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosticMessageTable) {
|
||||
const originalMessageForCode: string[] = [];
|
||||
let numConflicts = 0;
|
||||
|
||||
for (const currentMessage of messages) {
|
||||
const code = diagnosticTable[currentMessage].code;
|
||||
|
||||
if (code in originalMessageForCode) {
|
||||
const originalMessage = originalMessageForCode[code];
|
||||
ts.sys.write("\x1b[91m"); // High intensity red.
|
||||
ts.sys.write("Error");
|
||||
ts.sys.write("\x1b[0m"); // Reset formatting.
|
||||
ts.sys.write(`: Diagnostic code '${code}' conflicts between "${originalMessage}" and "${currentMessage}".`);
|
||||
ts.sys.write(ts.sys.newLine + ts.sys.newLine);
|
||||
|
||||
numConflicts++;
|
||||
}
|
||||
else {
|
||||
originalMessageForCode[code] = currentMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (numConflicts > 0) {
|
||||
throw new Error(`Found ${numConflicts} conflict(s) in diagnostic codes.`);
|
||||
}
|
||||
function checkForUniqueCodes(diagnosticTable: InputDiagnosticMessageTable) {
|
||||
const allCodes: { [key: number]: true | undefined } = [];
|
||||
diagnosticTable.forEach(({ code }) => {
|
||||
if (allCodes[code])
|
||||
throw new Error(`Diagnostic code ${code} appears more than once.`);
|
||||
allCodes[code] = true;
|
||||
});
|
||||
}
|
||||
|
||||
function buildUniqueNameMap(names: string[]): ts.Map<string> {
|
||||
var nameMap = ts.createMap<string>();
|
||||
|
||||
var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined);
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
nameMap.set(names[i], uniqueNames[i]);
|
||||
}
|
||||
|
||||
return nameMap;
|
||||
}
|
||||
|
||||
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, nameMap: ts.Map<string>): string {
|
||||
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable): string {
|
||||
var result =
|
||||
'// <auto-generated />\r\n' +
|
||||
'/// <reference path="types.ts" />\r\n' +
|
||||
'/* @internal */\r\n' +
|
||||
'namespace ts {\r\n' +
|
||||
" function diag(code: number, category: DiagnosticCategory, key: string, message: string): DiagnosticMessage {\r\n" +
|
||||
" return { code, category, key, message };\r\n" +
|
||||
" }\r\n" +
|
||||
' export const Diagnostics = {\r\n';
|
||||
var names = Utilities.getObjectKeys(messageTable);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var diagnosticDetails = messageTable[name];
|
||||
var propName = convertPropertyName(nameMap.get(name));
|
||||
|
||||
result +=
|
||||
' ' + propName +
|
||||
': { code: ' + diagnosticDetails.code +
|
||||
', category: DiagnosticCategory.' + diagnosticDetails.category +
|
||||
', key: "' + createKey(propName, diagnosticDetails.code) + '"' +
|
||||
', message: "' + name.replace(/[\"]/g, '\\"') + '"' +
|
||||
' },\r\n';
|
||||
}
|
||||
messageTable.forEach(({ code, category }, name) => {
|
||||
const propName = convertPropertyName(name);
|
||||
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}),\r\n`;
|
||||
});
|
||||
|
||||
result += ' };\r\n}';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable, nameMap: ts.Map<string>): string {
|
||||
var result =
|
||||
'{';
|
||||
var names = Utilities.getObjectKeys(messageTable);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var diagnosticDetails = messageTable[name];
|
||||
var propName = convertPropertyName(nameMap.get(name));
|
||||
function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable): string {
|
||||
let result = '{';
|
||||
messageTable.forEach(({ code }, name) => {
|
||||
const propName = convertPropertyName(name);
|
||||
result += `\r\n "${createKey(propName, code)}" : "${name.replace(/[\"]/g, '\\"')}",`;
|
||||
});
|
||||
|
||||
result += '\r\n "' + createKey(propName, diagnosticDetails.code) + '"' + ' : "' + name.replace(/[\"]/g, '\\"') + '"';
|
||||
if (i !== names.length - 1) {
|
||||
result += ',';
|
||||
}
|
||||
}
|
||||
// Shave trailing comma, then add newline and ending brace
|
||||
result = result.slice(0, result.length - 1) + '\r\n}';
|
||||
|
||||
result += '\r\n}';
|
||||
// Assert that we generated valid JSON
|
||||
JSON.parse(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -139,7 +102,6 @@ function convertPropertyName(origName: string): string {
|
||||
return /\w/.test(char) ? char : "_";
|
||||
}).join("");
|
||||
|
||||
|
||||
// get rid of all multi-underscores
|
||||
result = result.replace(/_+/g, "_");
|
||||
|
||||
@@ -152,93 +114,4 @@ function convertPropertyName(origName: string): string {
|
||||
return result;
|
||||
}
|
||||
|
||||
module NameGenerator {
|
||||
export function ensureUniqueness(names: string[], isCaseSensitive: boolean, isFixed?: boolean[]): string[]{
|
||||
if (!isFixed) {
|
||||
isFixed = names.map(() => false)
|
||||
}
|
||||
|
||||
var names = names.slice();
|
||||
ensureUniquenessInPlace(names, isCaseSensitive, isFixed);
|
||||
return names;
|
||||
}
|
||||
|
||||
function ensureUniquenessInPlace(names: string[], isCaseSensitive: boolean, isFixed: boolean[]): void {
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var collisionIndices = Utilities.collectMatchingIndices(name, names, isCaseSensitive);
|
||||
|
||||
// We will always have one "collision" because getCollisionIndices returns the index of name itself as well;
|
||||
// so if we only have one collision, then there are no issues.
|
||||
if (collisionIndices.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
handleCollisions(name, names, isFixed, collisionIndices, isCaseSensitive);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCollisions(name: string, proposedNames: string[], isFixed: boolean[], collisionIndices: number[], isCaseSensitive: boolean): void {
|
||||
var suffix = 1;
|
||||
|
||||
for (var i = 0; i < collisionIndices.length; i++) {
|
||||
var collisionIndex = collisionIndices[i];
|
||||
|
||||
if (isFixed[collisionIndex]) {
|
||||
// can't do anything about this name.
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var newName = name + suffix;
|
||||
suffix++;
|
||||
|
||||
// Check if we've synthesized a unique name, and if so
|
||||
// replace the conflicting name with the new one.
|
||||
if (!proposedNames.some(name => Utilities.stringEquals(name, newName, isCaseSensitive))) {
|
||||
proposedNames[collisionIndex] = newName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Utilities {
|
||||
/// Return a list of all indices where a string occurs.
|
||||
export function collectMatchingIndices(name: string, proposedNames: string[], isCaseSensitive: boolean): number[] {
|
||||
var matchingIndices: number[] = [];
|
||||
|
||||
for (var i = 0; i < proposedNames.length; i++) {
|
||||
if (stringEquals(name, proposedNames[i], isCaseSensitive)) {
|
||||
matchingIndices.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return matchingIndices;
|
||||
}
|
||||
|
||||
export function stringEquals(s1: string, s2: string, caseSensitive: boolean): boolean {
|
||||
if (caseSensitive) {
|
||||
s1 = s1.toLowerCase();
|
||||
s2 = s2.toLowerCase();
|
||||
}
|
||||
|
||||
return s1 == s2;
|
||||
}
|
||||
|
||||
// Like Object.keys
|
||||
export function getObjectKeys(obj: any): string[] {
|
||||
var result: string[] = [];
|
||||
|
||||
for (var name in obj) {
|
||||
if (obj.hasOwnProperty(name)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -34,6 +34,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
switch (methodName) {
|
||||
case "apply":
|
||||
case "assert":
|
||||
case "assertEqual":
|
||||
case "call":
|
||||
case "equal":
|
||||
case "fail":
|
||||
@@ -69,7 +70,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
|
||||
const ranges = ts.getTrailingCommentRanges(sourceFile.text, arg.pos) || ts.getLeadingCommentRanges(sourceFile.text, arg.pos);
|
||||
if (ranges === undefined || ranges.length !== 1 || ranges[0].kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
ctx.addFailureAtNode(arg, "Tag boolean argument with parameter name");
|
||||
ctx.addFailureAtNode(arg, "Tag argument with parameter name");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithFunction(sourceFile, ctx => walk(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, function recur(node) {
|
||||
if (ts.isCallExpression(node)) {
|
||||
checkCall(node);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
});
|
||||
|
||||
function checkCall(node: ts.CallExpression) {
|
||||
if (!isDebugAssert(node.expression) || node.arguments.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = node.arguments[1];
|
||||
if (!ts.isStringLiteral(message)) {
|
||||
ctx.addFailureAtNode(message, "Second argument to 'Debug.assert' should be a string literal.");
|
||||
}
|
||||
|
||||
if (node.arguments.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message2 = node.arguments[2];
|
||||
if (!ts.isStringLiteral(message2) && !ts.isArrowFunction(message2)) {
|
||||
ctx.addFailureAtNode(message, "Third argument to 'Debug.assert' should be a string literal or arrow function.");
|
||||
}
|
||||
}
|
||||
|
||||
function isDebugAssert(expr: ts.Node): boolean {
|
||||
return ts.isPropertyAccessExpression(expr) && isName(expr.expression, "Debug") && isName(expr.name, "assert");
|
||||
}
|
||||
|
||||
function isName(expr: ts.Node, text: string): boolean {
|
||||
return ts.isIdentifier(expr) && expr.text === text;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
function check(types: ts.TypeNode[]): void {
|
||||
function check(types: ReadonlyArray<ts.TypeNode>): void {
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
|
||||
Vendored
-8
@@ -13,13 +13,5 @@ declare module "gulp-insert" {
|
||||
export function transform(cb: (contents: string, file: {path: string, relative: string}) => string): NodeJS.ReadWriteStream; // file is a vinyl file
|
||||
}
|
||||
|
||||
declare module "into-stream" {
|
||||
function IntoStream(content: string | Buffer | (string | Buffer)[]): NodeJS.ReadableStream;
|
||||
namespace IntoStream {
|
||||
export function obj(content: any): NodeJS.ReadableStream
|
||||
}
|
||||
export = IntoStream;
|
||||
}
|
||||
|
||||
declare module "sorcery";
|
||||
declare module "travis-fold";
|
||||
|
||||
+73
-96
@@ -242,7 +242,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
|
||||
return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores((<PropertyAccessExpression>nameExpression).name.text));
|
||||
return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores((<PropertyAccessExpression>nameExpression).name.escapedText));
|
||||
}
|
||||
return getEscapedTextOfIdentifierOrLiteral(<Identifier | LiteralExpression>name);
|
||||
}
|
||||
@@ -287,8 +287,8 @@ namespace ts {
|
||||
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
|
||||
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
|
||||
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
|
||||
if (nameIdentifier.kind === SyntaxKind.Identifier) {
|
||||
nameFromParentNode = (<Identifier>nameIdentifier).text;
|
||||
if (isIdentifier(nameIdentifier)) {
|
||||
nameFromParentNode = nameIdentifier.escapedText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ namespace ts {
|
||||
* @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.)
|
||||
* @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations.
|
||||
*/
|
||||
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
|
||||
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol {
|
||||
Debug.assert(!hasDynamicName(node));
|
||||
|
||||
const isDefaultExport = hasModifier(node, ModifierFlags.Default);
|
||||
@@ -345,15 +345,20 @@ namespace ts {
|
||||
// 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 = symbolTable.get(name);
|
||||
if (!symbol) {
|
||||
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
|
||||
}
|
||||
|
||||
if (name && (includes & SymbolFlags.Classifiable)) {
|
||||
if (includes & SymbolFlags.Classifiable) {
|
||||
classifiableNames.set(name, true);
|
||||
}
|
||||
|
||||
if (symbol.flags & excludes) {
|
||||
if (!symbol) {
|
||||
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
|
||||
if (isReplaceableByMethod) symbol.isReplaceableByMethod = true;
|
||||
}
|
||||
else if (isReplaceableByMethod && !symbol.isReplaceableByMethod) {
|
||||
// A symbol already exists, so don't add this as a declaration.
|
||||
return symbol;
|
||||
}
|
||||
else if (symbol.flags & excludes) {
|
||||
if (symbol.isReplaceableByMethod) {
|
||||
// Javascript constructor-declared symbols can be discarded in favor of
|
||||
// prototype symbols like methods.
|
||||
@@ -416,9 +421,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
|
||||
// ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
|
||||
// on it. There are 2 main reasons:
|
||||
// Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue flag,
|
||||
// and an associated export symbol with all the correct flags set on it. There are 2 main reasons:
|
||||
//
|
||||
// 1. We treat locals and exports of the same name as mutually exclusive within a container.
|
||||
// That means the binder will issue a Duplicate Identifier error if you mix locals and exports
|
||||
@@ -438,10 +442,7 @@ namespace ts {
|
||||
(node as JSDocTypedefTag).name.kind === SyntaxKind.Identifier &&
|
||||
((node as JSDocTypedefTag).name as Identifier).isInJSDocNamespace;
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) {
|
||||
const exportKind =
|
||||
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
|
||||
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
|
||||
(symbolFlags & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
|
||||
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0;
|
||||
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
|
||||
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
node.localSymbol = local;
|
||||
@@ -805,11 +806,7 @@ namespace ts {
|
||||
return antecedent;
|
||||
}
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowCondition>{
|
||||
flags,
|
||||
expression,
|
||||
antecedent
|
||||
};
|
||||
return { flags, expression, antecedent };
|
||||
}
|
||||
|
||||
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
|
||||
@@ -817,31 +814,18 @@ namespace ts {
|
||||
return antecedent;
|
||||
}
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowSwitchClause>{
|
||||
flags: FlowFlags.SwitchClause,
|
||||
switchStatement,
|
||||
clauseStart,
|
||||
clauseEnd,
|
||||
antecedent
|
||||
};
|
||||
return { flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent };
|
||||
}
|
||||
|
||||
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowAssignment>{
|
||||
flags: FlowFlags.Assignment,
|
||||
antecedent,
|
||||
node
|
||||
};
|
||||
return { flags: FlowFlags.Assignment, antecedent, node };
|
||||
}
|
||||
|
||||
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return <FlowArrayMutation>{
|
||||
flags: FlowFlags.ArrayMutation,
|
||||
antecedent,
|
||||
node
|
||||
};
|
||||
const res: FlowArrayMutation = { flags: FlowFlags.ArrayMutation, antecedent, node };
|
||||
return res;
|
||||
}
|
||||
|
||||
function finishFlowLabel(flow: FlowLabel): FlowNode {
|
||||
@@ -1030,7 +1014,7 @@ namespace ts {
|
||||
function bindBreakOrContinueStatement(node: BreakOrContinueStatement): void {
|
||||
bind(node.label);
|
||||
if (node.label) {
|
||||
const activeLabel = findActiveLabel(node.label.text);
|
||||
const activeLabel = findActiveLabel(node.label.escapedText);
|
||||
if (activeLabel) {
|
||||
activeLabel.referenced = true;
|
||||
bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget);
|
||||
@@ -1191,7 +1175,7 @@ namespace ts {
|
||||
const postStatementLabel = createBranchLabel();
|
||||
bind(node.label);
|
||||
addAntecedent(preStatementLabel, currentFlow);
|
||||
const activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel);
|
||||
const activeLabel = pushActiveLabel(node.label.escapedText, postStatementLabel, preStatementLabel);
|
||||
bind(node.statement);
|
||||
popActiveLabel();
|
||||
if (!activeLabel.referenced && !options.allowUnusedLabels) {
|
||||
@@ -1331,7 +1315,7 @@ namespace ts {
|
||||
function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) {
|
||||
const name = !isOmittedExpression(node) ? node.name : undefined;
|
||||
if (isBindingPattern(name)) {
|
||||
for (const child of <ArrayBindingElement[]>name.elements) {
|
||||
for (const child of name.elements) {
|
||||
bindInitializedVariableFlow(child);
|
||||
}
|
||||
}
|
||||
@@ -1399,14 +1383,12 @@ namespace ts {
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return ContainerFlags.IsContainer;
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsInterface;
|
||||
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.MappedType:
|
||||
@@ -1426,9 +1408,10 @@ namespace ts {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike;
|
||||
|
||||
@@ -1504,10 +1487,9 @@ namespace ts {
|
||||
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
// Interface/Object-types always have their children added to the 'members' of
|
||||
// their container. They are only accessible through an instance of their
|
||||
@@ -1650,7 +1632,7 @@ namespace ts {
|
||||
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
|
||||
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
|
||||
typeLiteralSymbol.members = createSymbolTable();
|
||||
typeLiteralSymbol.members.set(symbol.name, symbol);
|
||||
typeLiteralSymbol.members.set(symbol.escapedName, symbol);
|
||||
}
|
||||
|
||||
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
|
||||
@@ -1681,9 +1663,9 @@ namespace ts {
|
||||
? ElementKind.Property
|
||||
: ElementKind.Accessor;
|
||||
|
||||
const existingKind = seen.get(identifier.text);
|
||||
const existingKind = seen.get(identifier.escapedText);
|
||||
if (!existingKind) {
|
||||
seen.set(identifier.text, currentKind);
|
||||
seen.set(identifier.escapedText, currentKind);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1793,8 +1775,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isEvalOrArgumentsIdentifier(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.Identifier &&
|
||||
((<Identifier>node).text === "eval" || (<Identifier>node).text === "arguments");
|
||||
return isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments");
|
||||
}
|
||||
|
||||
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) {
|
||||
@@ -1805,7 +1786,7 @@ namespace ts {
|
||||
// otherwise report generic error message.
|
||||
const span = getErrorSpanForNode(file, name);
|
||||
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length,
|
||||
getStrictModeEvalOrArgumentsMessage(contextNode), unescapeLeadingUnderscores(identifier.text)));
|
||||
getStrictModeEvalOrArgumentsMessage(contextNode), unescapeLeadingUnderscores(identifier.escapedText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2067,8 +2048,10 @@ namespace ts {
|
||||
case SyntaxKind.Parameter:
|
||||
return bindParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return bindVariableDeclarationOrBindingElement(<VariableDeclaration>node);
|
||||
case SyntaxKind.BindingElement:
|
||||
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
|
||||
node.flowNode = currentFlow;
|
||||
return bindVariableDeclarationOrBindingElement(<BindingElement>node);
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
return bindPropertyWorker(node as PropertyDeclaration | PropertySignature);
|
||||
@@ -2099,11 +2082,13 @@ namespace ts {
|
||||
case SyntaxKind.SetAccessor:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.MappedType:
|
||||
return bindAnonymousTypeWorker(node as TypeLiteralNode | MappedTypeNode);
|
||||
return bindAnonymousTypeWorker(node as TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return bindObjectLiteralExpression(<ObjectLiteralExpression>node);
|
||||
case SyntaxKind.FunctionExpression:
|
||||
@@ -2161,18 +2146,17 @@ namespace ts {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);
|
||||
|
||||
case SyntaxKind.JSDocRecordMember:
|
||||
return bindPropertyWorker(node as JSDocRecordMember);
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
if (node.parent.kind !== SyntaxKind.JSDocTypeLiteral) {
|
||||
break;
|
||||
}
|
||||
// falls through
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return declareSymbolAndAddToSymbolTable(node as JSDocPropertyTag,
|
||||
(node as JSDocPropertyTag).isBracketed || ((node as JSDocPropertyTag).typeExpression && (node as JSDocPropertyTag).typeExpression.type.kind === SyntaxKind.JSDocOptionalType) ?
|
||||
SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property,
|
||||
SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return bindAnonymousTypeWorker(node as JSDocTypeLiteral | JSDocRecordType);
|
||||
const propTag = node as JSDocPropertyLikeTag;
|
||||
const flags = propTag.isBracketed || propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ?
|
||||
SymbolFlags.Property | SymbolFlags.Optional :
|
||||
SymbolFlags.Property;
|
||||
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag: {
|
||||
const { fullName } = node as JSDocTypedefTag;
|
||||
if (!fullName || fullName.kind === SyntaxKind.Identifier) {
|
||||
@@ -2187,7 +2171,7 @@ namespace ts {
|
||||
return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
|
||||
function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) {
|
||||
function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral) {
|
||||
return bindAnonymousDeclaration(<Declaration>node, SymbolFlags.TypeLiteral, InternalSymbolName.Type);
|
||||
}
|
||||
|
||||
@@ -2288,7 +2272,7 @@ namespace ts {
|
||||
// When we create a property via 'exports.foo = bar', the 'exports.foo' property access
|
||||
// expression is the declaration
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None);
|
||||
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function isExportsOrModuleExportsOrAlias(node: Node): boolean {
|
||||
@@ -2298,14 +2282,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
const symbol = lookupSymbolForName((<Identifier>node).text);
|
||||
if (symbol && symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const declaration = symbol.valueDeclaration as VariableDeclaration;
|
||||
if (declaration.initializer) {
|
||||
return isExportsOrModuleExportsOrAliasOrAssignment(declaration.initializer);
|
||||
}
|
||||
}
|
||||
if (isIdentifier(node)) {
|
||||
const symbol = lookupSymbolForName(node.escapedText);
|
||||
return symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) &&
|
||||
symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(symbol.valueDeclaration.initializer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2329,7 +2309,7 @@ namespace ts {
|
||||
|
||||
// 'module.exports = expr' assignment
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None);
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
@@ -2352,11 +2332,8 @@ namespace ts {
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const containingClass = container.parent;
|
||||
const symbol = declareSymbol(hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// symbols declared through 'this' property assignements can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
const symbolTable = hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members;
|
||||
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2375,7 +2352,7 @@ namespace ts {
|
||||
constructorFunction.parent = classPrototype;
|
||||
classPrototype.parent = leftSideOfAssignment;
|
||||
|
||||
bindPropertyAssignment(constructorFunction.text, leftSideOfAssignment, /*isPrototypeProperty*/ true);
|
||||
bindPropertyAssignment(constructorFunction.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ true);
|
||||
}
|
||||
|
||||
function bindStaticPropertyAssignment(node: BinaryExpression) {
|
||||
@@ -2397,7 +2374,7 @@ namespace ts {
|
||||
bindExportsPropertyAssignment(node);
|
||||
}
|
||||
else {
|
||||
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2438,11 +2415,11 @@ namespace ts {
|
||||
bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
|
||||
}
|
||||
else {
|
||||
const bindingName = node.name ? node.name.text : InternalSymbolName.Class;
|
||||
const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Class;
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
|
||||
// Add name of class expression into the map for semantic classifier
|
||||
if (node.name) {
|
||||
classifiableNames.set(node.name.text, true);
|
||||
classifiableNames.set(node.name.escapedText, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2458,14 +2435,14 @@ 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" as __String);
|
||||
const symbolExport = symbol.exports.get(prototypeSymbol.name);
|
||||
const symbolExport = symbol.exports.get(prototypeSymbol.escapedName);
|
||||
if (symbolExport) {
|
||||
if (node.name) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(prototypeSymbol.name)));
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(prototypeSymbol.escapedName)));
|
||||
}
|
||||
symbol.exports.set(prototypeSymbol.name, prototypeSymbol);
|
||||
symbol.exports.set(prototypeSymbol.escapedName, prototypeSymbol);
|
||||
prototypeSymbol.parent = symbol;
|
||||
}
|
||||
|
||||
@@ -2551,7 +2528,7 @@ namespace ts {
|
||||
node.flowNode = currentFlow;
|
||||
}
|
||||
checkStrictModeFunctionName(node);
|
||||
const bindingName = node.name ? node.name.text : InternalSymbolName.Function;
|
||||
const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Function;
|
||||
return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName);
|
||||
}
|
||||
|
||||
@@ -2790,7 +2767,6 @@ namespace ts {
|
||||
|
||||
function computeParameter(node: ParameterDeclaration, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
const modifierFlags = getModifierFlags(node);
|
||||
const name = node.name;
|
||||
const initializer = node.initializer;
|
||||
const dotDotDotToken = node.dotDotDotToken;
|
||||
@@ -2805,7 +2781,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// If a parameter has an accessibility modifier, then it is TypeScript syntax.
|
||||
if (modifierFlags & ModifierFlags.ParameterPropertyModifier) {
|
||||
if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
|
||||
}
|
||||
|
||||
@@ -2850,9 +2826,8 @@ namespace ts {
|
||||
|
||||
function computeClassDeclaration(node: ClassDeclaration, subtreeFlags: TransformFlags) {
|
||||
let transformFlags: TransformFlags;
|
||||
const modifierFlags = getModifierFlags(node);
|
||||
|
||||
if (modifierFlags & ModifierFlags.Ambient) {
|
||||
if (hasModifier(node, ModifierFlags.Ambient)) {
|
||||
// An ambient declaration is TypeScript syntax.
|
||||
transformFlags = TransformFlags.AssertTypeScript;
|
||||
}
|
||||
@@ -2927,7 +2902,10 @@ namespace ts {
|
||||
function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
|
||||
if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) {
|
||||
if (!node.variableDeclaration) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
else if (isBindingPattern(node.variableDeclaration.name)) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
@@ -3193,11 +3171,10 @@ namespace ts {
|
||||
|
||||
function computeVariableStatement(node: VariableStatement, subtreeFlags: TransformFlags) {
|
||||
let transformFlags: TransformFlags;
|
||||
const modifierFlags = getModifierFlags(node);
|
||||
const declarationListTransformFlags = node.declarationList.transformFlags;
|
||||
|
||||
// An ambient declaration is TypeScript syntax.
|
||||
if (modifierFlags & ModifierFlags.Ambient) {
|
||||
if (hasModifier(node, ModifierFlags.Ambient)) {
|
||||
transformFlags = TransformFlags.AssertTypeScript;
|
||||
}
|
||||
else {
|
||||
|
||||
+1197
-816
File diff suppressed because it is too large
Load Diff
+109
-116
@@ -105,7 +105,7 @@ namespace ts {
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_none_commonjs_amd_system_umd_es2015_or_ESNext,
|
||||
},
|
||||
{
|
||||
name: "lib",
|
||||
@@ -340,7 +340,6 @@ namespace ts {
|
||||
isTSConfigOnly: true,
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl
|
||||
|
||||
},
|
||||
{
|
||||
// this option can only be specified in tsconfig.json
|
||||
@@ -384,6 +383,12 @@ namespace ts {
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking
|
||||
},
|
||||
{
|
||||
name: "preserveSymlinks",
|
||||
type: "boolean",
|
||||
category: Diagnostics.Module_Resolution_Options,
|
||||
description: Diagnostics.Do_not_resolve_the_real_path_of_symlinks,
|
||||
},
|
||||
|
||||
// Source Maps
|
||||
{
|
||||
@@ -728,12 +733,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Push<Diagnostic>) {
|
||||
return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "", errors: Diagnostic[]): (string | number)[] | undefined {
|
||||
export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "", errors: Push<Diagnostic>): (string | number)[] | undefined {
|
||||
value = trimString(value);
|
||||
if (startsWith(value, "-")) {
|
||||
return undefined;
|
||||
@@ -752,7 +757,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
|
||||
export function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine {
|
||||
const options: CompilerOptions = {};
|
||||
const fileNames: string[] = [];
|
||||
const errors: Diagnostic[] = [];
|
||||
@@ -764,7 +769,7 @@ namespace ts {
|
||||
errors
|
||||
};
|
||||
|
||||
function parseStrings(args: string[]) {
|
||||
function parseStrings(args: ReadonlyArray<string>) {
|
||||
let i = 0;
|
||||
while (i < args.length) {
|
||||
const s = args[i];
|
||||
@@ -878,15 +883,9 @@ namespace ts {
|
||||
* Read tsconfig.json file
|
||||
* @param fileName The path to the config file
|
||||
*/
|
||||
export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } {
|
||||
let text = "";
|
||||
try {
|
||||
text = readFile(fileName);
|
||||
}
|
||||
catch (e) {
|
||||
return { config: {}, error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
|
||||
}
|
||||
return parseConfigFileTextToJson(fileName, text);
|
||||
export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic } {
|
||||
const textOrDiagnostic = tryReadFile(fileName, readFile);
|
||||
return typeof textOrDiagnostic === "string" ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -906,18 +905,23 @@ namespace ts {
|
||||
* Read tsconfig.json file
|
||||
* @param fileName The path to the config file
|
||||
*/
|
||||
export function readJsonConfigFile(fileName: string, readFile: (path: string) => string): JsonSourceFile {
|
||||
let text = "";
|
||||
export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): JsonSourceFile {
|
||||
const textOrDiagnostic = tryReadFile(fileName, readFile);
|
||||
return typeof textOrDiagnostic === "string" ? parseJsonText(fileName, textOrDiagnostic) : <JsonSourceFile>{ parseDiagnostics: [textOrDiagnostic] };
|
||||
}
|
||||
|
||||
function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
text = readFile(fileName);
|
||||
}
|
||||
catch (e) {
|
||||
return <JsonSourceFile>{ parseDiagnostics: [createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message)] };
|
||||
return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message);
|
||||
}
|
||||
return parseJsonText(fileName, text);
|
||||
return text === undefined ? createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, fileName) : text;
|
||||
}
|
||||
|
||||
function commandLineOptionsToMap(options: CommandLineOption[]) {
|
||||
function commandLineOptionsToMap(options: ReadonlyArray<CommandLineOption>) {
|
||||
return arrayToMap(options, option => option.name);
|
||||
}
|
||||
|
||||
@@ -1008,7 +1012,7 @@ namespace ts {
|
||||
/**
|
||||
* Convert the json syntax tree into the json value
|
||||
*/
|
||||
export function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any {
|
||||
export function convertToObject(sourceFile: JsonSourceFile, errors: Push<Diagnostic>): any {
|
||||
return convertToObjectWorker(sourceFile, errors, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined);
|
||||
}
|
||||
|
||||
@@ -1017,7 +1021,7 @@ namespace ts {
|
||||
*/
|
||||
function convertToObjectWorker(
|
||||
sourceFile: JsonSourceFile,
|
||||
errors: Diagnostic[],
|
||||
errors: Push<Diagnostic>,
|
||||
knownRootOptions: Map<CommandLineOption> | undefined,
|
||||
jsonConversionNotifier: JsonConversionNotifier | undefined): any {
|
||||
if (!sourceFile.jsonObject) {
|
||||
@@ -1086,11 +1090,7 @@ namespace ts {
|
||||
elements: NodeArray<Expression>,
|
||||
elementOption: CommandLineOption | undefined
|
||||
): any[] {
|
||||
const result: any[] = [];
|
||||
for (const element of elements) {
|
||||
result.push(convertPropertyValueToJson(element, elementOption));
|
||||
}
|
||||
return result;
|
||||
return elements.map(element => convertPropertyValueToJson(element, elementOption));
|
||||
}
|
||||
|
||||
function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption): any {
|
||||
@@ -1116,7 +1116,7 @@ namespace ts {
|
||||
if (option && typeof option.type !== "string") {
|
||||
const customOption = <CommandLineOptionOfCustomType>option;
|
||||
// Validate custom option type
|
||||
if (!customOption.type.has(text)) {
|
||||
if (!customOption.type.has(text.toLowerCase())) {
|
||||
errors.push(
|
||||
createDiagnosticForInvalidCustomType(
|
||||
customOption,
|
||||
@@ -1203,17 +1203,9 @@ namespace ts {
|
||||
* @param fileNames array of filenames to be generated into tsconfig.json
|
||||
*/
|
||||
/* @internal */
|
||||
export function generateTSConfig(options: CompilerOptions, fileNames: string[], newLine: string): string {
|
||||
export function generateTSConfig(options: CompilerOptions, fileNames: ReadonlyArray<string>, newLine: string): string {
|
||||
const compilerOptions = extend(options, defaultInitCompilerOptions);
|
||||
const configurations: { compilerOptions: MapLike<CompilerOptionsValue>; files?: string[] } = {
|
||||
compilerOptions: serializeCompilerOptions(compilerOptions)
|
||||
};
|
||||
if (fileNames && fileNames.length) {
|
||||
// only set the files property if we have at least one file
|
||||
configurations.files = fileNames;
|
||||
}
|
||||
|
||||
|
||||
const compilerOptionsMap = serializeCompilerOptions(compilerOptions);
|
||||
return writeConfigurations();
|
||||
|
||||
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
|
||||
@@ -1238,8 +1230,8 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function serializeCompilerOptions(options: CompilerOptions): MapLike<CompilerOptionsValue> {
|
||||
const result: ts.MapLike<CompilerOptionsValue> = {};
|
||||
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
|
||||
const result = createMap<CompilerOptionsValue>();
|
||||
const optionsNameMap = getOptionNameMap().optionNameMap;
|
||||
|
||||
for (const name in options) {
|
||||
@@ -1256,19 +1248,15 @@ namespace ts {
|
||||
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;
|
||||
result.set(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;
|
||||
result.set(name, (value as ReadonlyArray<string | number>).map(element => getNameOfCompilerOptionValue(element, customTypeMap)));
|
||||
}
|
||||
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);
|
||||
result.set(name, getNameOfCompilerOptionValue(value, customTypeMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1300,33 +1288,30 @@ namespace ts {
|
||||
|
||||
function writeConfigurations() {
|
||||
// Filter applicable options to place in the file
|
||||
const categorizedOptions = reduceLeft(
|
||||
filter(optionDeclarations, o => o.category !== Diagnostics.Command_line_Options && o.category !== Diagnostics.Advanced_Options),
|
||||
(memo, value) => {
|
||||
if (value.category) {
|
||||
const name = getLocaleSpecificMessage(value.category);
|
||||
(memo[name] || (memo[name] = [])).push(value);
|
||||
}
|
||||
return memo;
|
||||
}, <MapLike<CommandLineOption[]>>{});
|
||||
const categorizedOptions = createMultiMap<CommandLineOption>();
|
||||
for (const option of optionDeclarations) {
|
||||
const { category } = option;
|
||||
if (category !== undefined && category !== Diagnostics.Command_line_Options && category !== Diagnostics.Advanced_Options) {
|
||||
categorizedOptions.add(getLocaleSpecificMessage(category), option);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize all options and thier descriptions
|
||||
// Serialize all options and their descriptions
|
||||
let marginLength = 0;
|
||||
let seenKnownKeys = 0;
|
||||
const nameColumn: string[] = [];
|
||||
const descriptionColumn: string[] = [];
|
||||
const knownKeysCount = getOwnKeys(configurations.compilerOptions).length;
|
||||
for (const category in categorizedOptions) {
|
||||
categorizedOptions.forEach((options, category) => {
|
||||
if (nameColumn.length !== 0) {
|
||||
nameColumn.push("");
|
||||
descriptionColumn.push("");
|
||||
}
|
||||
nameColumn.push(`/* ${category} */`);
|
||||
descriptionColumn.push("");
|
||||
for (const option of categorizedOptions[category]) {
|
||||
for (const option of options) {
|
||||
let optionName;
|
||||
if (hasProperty(configurations.compilerOptions, option.name)) {
|
||||
optionName = `"${option.name}": ${JSON.stringify(configurations.compilerOptions[option.name])}${(seenKnownKeys += 1) === knownKeysCount ? "" : ","}`;
|
||||
if (compilerOptionsMap.has(option.name)) {
|
||||
optionName = `"${option.name}": ${JSON.stringify(compilerOptionsMap.get(option.name))}${(seenKnownKeys += 1) === compilerOptionsMap.size ? "" : ","}`;
|
||||
}
|
||||
else {
|
||||
optionName = `// "${option.name}": ${JSON.stringify(getDefaultValueForOption(option))},`;
|
||||
@@ -1335,7 +1320,7 @@ namespace ts {
|
||||
descriptionColumn.push(`/* ${option.description && getLocaleSpecificMessage(option.description) || option.name} */`);
|
||||
marginLength = Math.max(optionName.length, marginLength);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Write the output
|
||||
const tab = makePadding(2);
|
||||
@@ -1348,11 +1333,11 @@ namespace ts {
|
||||
const description = descriptionColumn[i];
|
||||
result.push(optionName && `${tab}${tab}${optionName}${ description && (makePadding(marginLength - optionName.length + 2) + description)}`);
|
||||
}
|
||||
if (configurations.files && configurations.files.length) {
|
||||
if (fileNames.length) {
|
||||
result.push(`${tab}},`);
|
||||
result.push(`${tab}"files": [`);
|
||||
for (let i = 0; i < configurations.files.length; i++) {
|
||||
result.push(`${tab}${tab}${JSON.stringify(configurations.files[i])}${i === configurations.files.length - 1 ? "" : ","}`);
|
||||
for (let i = 0; i < fileNames.length; i++) {
|
||||
result.push(`${tab}${tab}${JSON.stringify(fileNames[i])}${i === fileNames.length - 1 ? "" : ","}`);
|
||||
}
|
||||
result.push(`${tab}]`);
|
||||
}
|
||||
@@ -1372,7 +1357,7 @@ namespace ts {
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: JsFileExtensionInfo[]): ParsedCommandLine {
|
||||
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray<JsFileExtensionInfo>): ParsedCommandLine {
|
||||
return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions);
|
||||
}
|
||||
|
||||
@@ -1383,7 +1368,7 @@ namespace ts {
|
||||
* @param basePath A root directory to resolve relative path entries in the config
|
||||
* file to. e.g. outDir
|
||||
*/
|
||||
export function parseJsonSourceFileConfigFileContent(sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: JsFileExtensionInfo[]): ParsedCommandLine {
|
||||
export function parseJsonSourceFileConfigFileContent(sourceFile: JsonSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray<JsFileExtensionInfo>): ParsedCommandLine {
|
||||
return parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions);
|
||||
}
|
||||
|
||||
@@ -1411,7 +1396,7 @@ namespace ts {
|
||||
existingOptions: CompilerOptions = {},
|
||||
configFileName?: string,
|
||||
resolutionStack: Path[] = [],
|
||||
extraFileExtensions: JsFileExtensionInfo[] = [],
|
||||
extraFileExtensions: ReadonlyArray<JsFileExtensionInfo> = [],
|
||||
): ParsedCommandLine {
|
||||
Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
|
||||
const errors: Diagnostic[] = [];
|
||||
@@ -1433,10 +1418,10 @@ namespace ts {
|
||||
};
|
||||
|
||||
function getFileNames(): ExpandResult {
|
||||
let fileNames: string[];
|
||||
let fileNames: ReadonlyArray<string>;
|
||||
if (hasProperty(raw, "files")) {
|
||||
if (isArray(raw["files"])) {
|
||||
fileNames = <string[]>raw["files"];
|
||||
fileNames = <ReadonlyArray<string>>raw["files"];
|
||||
if (fileNames.length === 0) {
|
||||
createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json");
|
||||
}
|
||||
@@ -1446,32 +1431,29 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
let includeSpecs: string[];
|
||||
let includeSpecs: ReadonlyArray<string>;
|
||||
if (hasProperty(raw, "include")) {
|
||||
if (isArray(raw["include"])) {
|
||||
includeSpecs = <string[]>raw["include"];
|
||||
includeSpecs = <ReadonlyArray<string>>raw["include"];
|
||||
}
|
||||
else {
|
||||
createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "include", "Array");
|
||||
}
|
||||
}
|
||||
|
||||
let excludeSpecs: string[];
|
||||
let excludeSpecs: ReadonlyArray<string>;
|
||||
if (hasProperty(raw, "exclude")) {
|
||||
if (isArray(raw["exclude"])) {
|
||||
excludeSpecs = <string[]>raw["exclude"];
|
||||
excludeSpecs = <ReadonlyArray<string>>raw["exclude"];
|
||||
}
|
||||
else {
|
||||
createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "exclude", "Array");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If no includes were specified, exclude common package folders and the outDir
|
||||
excludeSpecs = includeSpecs ? [] : ["node_modules", "bower_components", "jspm_packages"];
|
||||
|
||||
const outDir = raw["compilerOptions"] && raw["compilerOptions"]["outDir"];
|
||||
if (outDir) {
|
||||
excludeSpecs.push(outDir);
|
||||
excludeSpecs = [outDir];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1522,7 +1504,7 @@ namespace ts {
|
||||
basePath: string,
|
||||
configFileName: string,
|
||||
resolutionStack: Path[],
|
||||
errors: Diagnostic[],
|
||||
errors: Push<Diagnostic>,
|
||||
): ParsedTsconfig {
|
||||
basePath = normalizeSlashes(basePath);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
@@ -1571,7 +1553,7 @@ namespace ts {
|
||||
basePath: string,
|
||||
getCanonicalFileName: (fileName: string) => string,
|
||||
configFileName: string,
|
||||
errors: Diagnostic[]
|
||||
errors: Push<Diagnostic>
|
||||
): ParsedTsconfig {
|
||||
if (hasProperty(json, "excludes")) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
|
||||
@@ -1601,7 +1583,7 @@ namespace ts {
|
||||
basePath: string,
|
||||
getCanonicalFileName: (fileName: string) => string,
|
||||
configFileName: string,
|
||||
errors: Diagnostic[]
|
||||
errors: Push<Diagnostic>
|
||||
): ParsedTsconfig {
|
||||
const options = getDefaultCompilerOptions(configFileName);
|
||||
let typeAcquisition: TypeAcquisition, typingOptionstypeAcquisition: TypeAcquisition;
|
||||
@@ -1632,7 +1614,7 @@ namespace ts {
|
||||
);
|
||||
return;
|
||||
case "files":
|
||||
if ((<string[]>value).length === 0) {
|
||||
if ((<ReadonlyArray<string>>value).length === 0) {
|
||||
errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueNode, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
|
||||
}
|
||||
return;
|
||||
@@ -1668,7 +1650,7 @@ namespace ts {
|
||||
host: ParseConfigHost,
|
||||
basePath: string,
|
||||
getCanonicalFileName: (fileName: string) => string,
|
||||
errors: Diagnostic[],
|
||||
errors: Push<Diagnostic>,
|
||||
createDiagnostic: (message: DiagnosticMessage, arg1?: string) => Diagnostic) {
|
||||
extendedConfig = normalizeSlashes(extendedConfig);
|
||||
// If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future)
|
||||
@@ -1694,7 +1676,7 @@ namespace ts {
|
||||
basePath: string,
|
||||
getCanonicalFileName: (fileName: string) => string,
|
||||
resolutionStack: Path[],
|
||||
errors: Diagnostic[],
|
||||
errors: Push<Diagnostic>,
|
||||
): ParsedTsconfig | undefined {
|
||||
const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path));
|
||||
if (sourceFile) {
|
||||
@@ -1731,7 +1713,7 @@ namespace ts {
|
||||
return extendedConfig;
|
||||
}
|
||||
|
||||
function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean {
|
||||
function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push<Diagnostic>): boolean {
|
||||
if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1762,7 +1744,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
|
||||
basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
|
||||
basePath: string, errors: Push<Diagnostic>, configFileName?: string): CompilerOptions {
|
||||
|
||||
const options = getDefaultCompilerOptions(configFileName);
|
||||
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
|
||||
@@ -1775,7 +1757,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function convertTypeAcquisitionFromJsonWorker(jsonOptions: any,
|
||||
basePath: string, errors: Diagnostic[], configFileName?: string): TypeAcquisition {
|
||||
basePath: string, errors: Push<Diagnostic>, configFileName?: string): TypeAcquisition {
|
||||
|
||||
const options = getDefaultTypeAcquisition(configFileName);
|
||||
const typeAcquisition = convertEnableAutoDiscoveryToEnable(jsonOptions);
|
||||
@@ -1784,8 +1766,8 @@ namespace ts {
|
||||
return options;
|
||||
}
|
||||
|
||||
function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string,
|
||||
defaultOptions: CompilerOptions | TypeAcquisition, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) {
|
||||
function convertOptionsFromJson(optionDeclarations: ReadonlyArray<CommandLineOption>, jsonOptions: any, basePath: string,
|
||||
defaultOptions: CompilerOptions | TypeAcquisition, diagnosticMessage: DiagnosticMessage, errors: Push<Diagnostic>) {
|
||||
|
||||
if (!jsonOptions) {
|
||||
return;
|
||||
@@ -1804,7 +1786,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): CompilerOptionsValue {
|
||||
function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Push<Diagnostic>): CompilerOptionsValue {
|
||||
if (isCompilerOptionsValue(opt, value)) {
|
||||
const optType = opt.type;
|
||||
if (optType === "list" && isArray(value)) {
|
||||
@@ -1829,7 +1811,7 @@ namespace ts {
|
||||
return value;
|
||||
}
|
||||
else if (typeof option.type !== "string") {
|
||||
return option.type.get(value);
|
||||
return option.type.get(typeof value === "string" ? value.toLowerCase() : value);
|
||||
}
|
||||
return normalizeNonListOptionValue(option, basePath, value);
|
||||
}
|
||||
@@ -1844,7 +1826,7 @@ namespace ts {
|
||||
return value;
|
||||
}
|
||||
|
||||
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
|
||||
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Push<Diagnostic>) {
|
||||
const key = value.toLowerCase();
|
||||
const val = opt.type.get(key);
|
||||
if (val !== undefined) {
|
||||
@@ -1855,7 +1837,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] {
|
||||
function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: ReadonlyArray<any>, basePath: string, errors: Push<Diagnostic>): any[] {
|
||||
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v);
|
||||
}
|
||||
|
||||
@@ -1946,7 +1928,16 @@ namespace ts {
|
||||
* @param host The host used to resolve files and directories.
|
||||
* @param errors An array for diagnostic reporting.
|
||||
*/
|
||||
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], extraFileExtensions: JsFileExtensionInfo[], jsonSourceFile: JsonSourceFile): ExpandResult {
|
||||
function matchFileNames(
|
||||
fileNames: ReadonlyArray<string>,
|
||||
include: ReadonlyArray<string>,
|
||||
exclude: ReadonlyArray<string>,
|
||||
basePath: string,
|
||||
options: CompilerOptions,
|
||||
host: ParseConfigHost,
|
||||
errors: Push<Diagnostic>,
|
||||
extraFileExtensions: ReadonlyArray<JsFileExtensionInfo>,
|
||||
jsonSourceFile: JsonSourceFile): ExpandResult {
|
||||
basePath = normalizePath(basePath);
|
||||
|
||||
// The exclude spec list is converted into a regular expression, which allows us to quickly
|
||||
@@ -2024,31 +2015,21 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function validateSpecs(specs: string[], errors: Diagnostic[], allowTrailingRecursion: boolean, jsonSourceFile: JsonSourceFile, specKey: string) {
|
||||
const validSpecs: string[] = [];
|
||||
for (const spec of specs) {
|
||||
if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
|
||||
errors.push(createDiagnostic(Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
|
||||
function validateSpecs(specs: ReadonlyArray<string>, errors: Push<Diagnostic>, allowTrailingRecursion: boolean, jsonSourceFile: JsonSourceFile, specKey: string) {
|
||||
return specs.filter(spec => {
|
||||
const diag = specToDiagnostic(spec, allowTrailingRecursion);
|
||||
if (diag !== undefined) {
|
||||
errors.push(createDiagnostic(diag, spec));
|
||||
}
|
||||
else if (invalidMultipleRecursionPatterns.test(spec)) {
|
||||
errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, spec));
|
||||
}
|
||||
else if (invalidDotDotAfterRecursiveWildcardPattern.test(spec)) {
|
||||
errors.push(createDiagnostic(Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
|
||||
}
|
||||
else {
|
||||
validSpecs.push(spec);
|
||||
}
|
||||
}
|
||||
|
||||
return validSpecs;
|
||||
return diag === undefined;
|
||||
});
|
||||
|
||||
function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
|
||||
if (jsonSourceFile && jsonSourceFile.jsonObject) {
|
||||
for (const property of getPropertyAssignment(jsonSourceFile.jsonObject, specKey)) {
|
||||
if (isArrayLiteralExpression(property.initializer)) {
|
||||
for (const element of property.initializer.elements) {
|
||||
if (element.kind === SyntaxKind.StringLiteral && (<StringLiteral>element).text === spec) {
|
||||
if (isStringLiteral(element) && element.text === spec) {
|
||||
return createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec);
|
||||
}
|
||||
}
|
||||
@@ -2059,10 +2040,22 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function specToDiagnostic(spec: string, allowTrailingRecursion: boolean): ts.DiagnosticMessage | undefined {
|
||||
if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
|
||||
return Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0;
|
||||
}
|
||||
else if (invalidMultipleRecursionPatterns.test(spec)) {
|
||||
return Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0;
|
||||
}
|
||||
else if (invalidDotDotAfterRecursiveWildcardPattern.test(spec)) {
|
||||
return Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets directories in a set of include patterns that should be watched for changes.
|
||||
*/
|
||||
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
|
||||
function getWildcardDirectories(include: ReadonlyArray<string>, exclude: ReadonlyArray<string>, path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
|
||||
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
|
||||
// of the pattern:
|
||||
//
|
||||
@@ -2136,7 +2129,7 @@ namespace ts {
|
||||
* @param extensionPriority The priority of the extension.
|
||||
* @param context The expansion context.
|
||||
*/
|
||||
function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map<string>, wildcardFiles: Map<string>, extensions: string[], keyMapper: (value: string) => string) {
|
||||
function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map<string>, wildcardFiles: Map<string>, extensions: ReadonlyArray<string>, keyMapper: (value: string) => string) {
|
||||
const extensionPriority = getExtensionPriority(file, extensions);
|
||||
const adjustedExtensionPriority = adjustExtensionPriority(extensionPriority, extensions);
|
||||
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
|
||||
@@ -2158,7 +2151,7 @@ namespace ts {
|
||||
* @param extensionPriority The priority of the extension.
|
||||
* @param context The expansion context.
|
||||
*/
|
||||
function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: Map<string>, extensions: string[], keyMapper: (value: string) => string) {
|
||||
function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: Map<string>, extensions: ReadonlyArray<string>, keyMapper: (value: string) => string) {
|
||||
const extensionPriority = getExtensionPriority(file, extensions);
|
||||
const nextExtensionPriority = getNextLowestExtensionPriority(extensionPriority, extensions);
|
||||
for (let i = nextExtensionPriority; i < extensions.length; i++) {
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace ts {
|
||||
setWriter(writer: EmitTextWriter): void;
|
||||
emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
|
||||
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
|
||||
emitTrailingCommentsOfPosition(pos: number): void;
|
||||
emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean): void;
|
||||
emitLeadingCommentsOfPosition(pos: number): void;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ts {
|
||||
let declarationListContainerEnd = -1;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentLineMap: number[];
|
||||
let currentLineMap: ReadonlyArray<number>;
|
||||
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
|
||||
let hasWrittenComment = false;
|
||||
let disabled: boolean = printerOptions.removeComments;
|
||||
@@ -306,7 +306,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingCommentsOfPosition(pos: number) {
|
||||
function emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ namespace ts {
|
||||
performance.mark("beforeEmitTrailingCommentsOfPosition");
|
||||
}
|
||||
|
||||
forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition);
|
||||
forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : emitTrailingCommentOfPosition);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition");
|
||||
@@ -415,17 +415,7 @@ namespace ts {
|
||||
* @return true if the comment is a triple-slash comment else false
|
||||
*/
|
||||
function isTripleSlashComment(commentPos: number, commentEnd: number) {
|
||||
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
|
||||
// so that we don't end up computing comment string and doing match for all // comments
|
||||
if (currentText.charCodeAt(commentPos + 1) === CharacterCodes.slash &&
|
||||
commentPos + 2 < commentEnd &&
|
||||
currentText.charCodeAt(commentPos + 2) === CharacterCodes.slash) {
|
||||
const textSubStr = currentText.substring(commentPos, commentEnd);
|
||||
return textSubStr.match(fullTripleSlashReferencePathRegEx) ||
|
||||
textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ?
|
||||
true : false;
|
||||
}
|
||||
return false;
|
||||
return isRecognizedTripleSlashComment(currentText, commentPos, commentEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
+288
-203
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@ namespace ts {
|
||||
let enclosingDeclaration: Node;
|
||||
let resultHasExternalModuleIndicator: boolean;
|
||||
let currentText: string;
|
||||
let currentLineMap: number[];
|
||||
let currentLineMap: ReadonlyArray<number>;
|
||||
let currentIdentifiers: Map<string>;
|
||||
let isCurrentFileExternalModule: boolean;
|
||||
let reportedDeclarationError = false;
|
||||
@@ -211,7 +211,7 @@ namespace ts {
|
||||
decreaseIndent = newWriter.decreaseIndent;
|
||||
}
|
||||
|
||||
function writeAsynchronousModuleElements(nodes: Node[]) {
|
||||
function writeAsynchronousModuleElements(nodes: ReadonlyArray<Node>) {
|
||||
const oldWriter = writer;
|
||||
forEach(nodes, declaration => {
|
||||
let nodeToCheck: Node;
|
||||
@@ -349,7 +349,6 @@ namespace ts {
|
||||
errorNameNode = declaration.name;
|
||||
const format = TypeFormatFlags.UseTypeOfFunction |
|
||||
TypeFormatFlags.WriteClassExpressionAsTypeLiteral |
|
||||
TypeFormatFlags.UseTypeAliasValue |
|
||||
(shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0);
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
|
||||
errorNameNode = undefined;
|
||||
@@ -368,19 +367,19 @@ namespace ts {
|
||||
resolver.writeReturnTypeOfSignatureDeclaration(
|
||||
signature,
|
||||
enclosingDeclaration,
|
||||
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
|
||||
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
|
||||
writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function emitLines(nodes: Node[]) {
|
||||
function emitLines(nodes: ReadonlyArray<Node>) {
|
||||
for (const node of nodes) {
|
||||
emit(node);
|
||||
}
|
||||
}
|
||||
|
||||
function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
|
||||
function emitSeparatedList(nodes: ReadonlyArray<Node>, separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
|
||||
let currentWriterPos = writer.getTextPos();
|
||||
for (const node of nodes) {
|
||||
if (!canEmitFn || canEmitFn(node)) {
|
||||
@@ -393,7 +392,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[], eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
|
||||
function emitCommaList(nodes: ReadonlyArray<Node>, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
|
||||
emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn);
|
||||
}
|
||||
|
||||
@@ -633,7 +632,7 @@ namespace ts {
|
||||
resolver.writeTypeOfExpression(
|
||||
expr,
|
||||
enclosingDeclaration,
|
||||
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
|
||||
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
|
||||
writer);
|
||||
write(";");
|
||||
writeLine();
|
||||
@@ -1007,7 +1006,7 @@ namespace ts {
|
||||
return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private);
|
||||
}
|
||||
|
||||
function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
|
||||
function emitTypeParameters(typeParameters: ReadonlyArray<TypeParameterDeclaration>) {
|
||||
function emitTypeParameter(node: TypeParameterDeclaration) {
|
||||
increaseIndent();
|
||||
emitJsDocComments(node);
|
||||
@@ -1109,7 +1108,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitHeritageClause(typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
function emitHeritageClause(typeReferences: ReadonlyArray<ExpressionWithTypeArguments>, isImplementsList: boolean) {
|
||||
if (typeReferences) {
|
||||
write(isImplementsList ? " implements " : " extends ");
|
||||
emitCommaList(typeReferences, emitTypeOfTypeReference);
|
||||
@@ -1164,7 +1163,7 @@ namespace ts {
|
||||
if (baseTypeNode && !isEntityNameExpression(baseTypeNode.expression)) {
|
||||
tempVarName = baseTypeNode.expression.kind === SyntaxKind.NullKeyword ?
|
||||
"null" :
|
||||
emitTempVariableDeclaration(baseTypeNode.expression, `${node.name.text}_base`, {
|
||||
emitTempVariableDeclaration(baseTypeNode.expression, `${node.name.escapedText}_base`, {
|
||||
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
|
||||
errorNode: baseTypeNode,
|
||||
typeName: node.name
|
||||
@@ -1367,6 +1366,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function writeVariableStatement(node: VariableStatement) {
|
||||
// If binding pattern doesn't have name, then there is nothing to be emitted for declaration file i.e. const [,] = [1,2].
|
||||
if (every(node.declarationList && node.declarationList.declarations, decl => decl.name && isEmptyBindingPattern(decl.name))) {
|
||||
return;
|
||||
}
|
||||
emitJsDocComments(node);
|
||||
emitModuleElementDeclarationFlags(node);
|
||||
if (isLet(node.declarationList)) {
|
||||
|
||||
@@ -1908,6 +1908,18 @@
|
||||
"category": "Error",
|
||||
"code": 2559
|
||||
},
|
||||
"Value of type '{0}' has no properties in common with type '{1}'. Did you mean to call it?": {
|
||||
"category": "Error",
|
||||
"code": 2560
|
||||
},
|
||||
"Object literal may only specify known properties, but '{0}' does not exist in type '{1}'. Did you mean to write '{2}'?": {
|
||||
"category": "Error",
|
||||
"code": 2561
|
||||
},
|
||||
"Base class expressions cannot reference class type parameters.": {
|
||||
"category": "Error",
|
||||
"code": 2562
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -2064,7 +2076,7 @@
|
||||
"category": "Error",
|
||||
"code": 2679
|
||||
},
|
||||
"A 'this' parameter must be the first parameter.": {
|
||||
"A '{0}' parameter must be the first parameter.": {
|
||||
"category": "Error",
|
||||
"code": 2680
|
||||
},
|
||||
@@ -2192,6 +2204,10 @@
|
||||
"category": "Error",
|
||||
"code": 2712
|
||||
},
|
||||
"Cannot access '{0}.{1}' because '{0}' is a type, but not a namespace. Did you mean to retrieve the type of the property '{1}' in '{0}' with '{0}[\"{1}\"]'?": {
|
||||
"category": "Error",
|
||||
"code": 2713
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -2654,11 +2670,15 @@
|
||||
"category": "Message",
|
||||
"code": 6012
|
||||
},
|
||||
"Do not resolve the real path of symlinks.": {
|
||||
"category": "Message",
|
||||
"code": 6013
|
||||
},
|
||||
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'.": {
|
||||
"category": "Message",
|
||||
"code": 6015
|
||||
},
|
||||
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
|
||||
"Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
|
||||
"category": "Message",
|
||||
"code": 6016
|
||||
},
|
||||
@@ -3455,6 +3475,10 @@
|
||||
"category": "Error",
|
||||
"code": 8012
|
||||
},
|
||||
"'non-null assertions' can only be used in a .ts file.": {
|
||||
"category": "Error",
|
||||
"code": 8013
|
||||
},
|
||||
"'enum declarations' can only be used in a .ts file.": {
|
||||
"category": "Error",
|
||||
"code": 8015
|
||||
@@ -3463,6 +3487,22 @@
|
||||
"category": "Error",
|
||||
"code": 8016
|
||||
},
|
||||
"Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8017
|
||||
},
|
||||
"Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8018
|
||||
},
|
||||
"Report errors in .js files.": {
|
||||
"category": "Message",
|
||||
"code": 8019
|
||||
},
|
||||
"JSDoc types can only be used inside documentation comments.": {
|
||||
"category": "Error",
|
||||
"code": 8020
|
||||
},
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
@@ -3637,6 +3677,10 @@
|
||||
"category": "Message",
|
||||
"code": 90025
|
||||
},
|
||||
"Rewrite as the indexed access type '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90026
|
||||
},
|
||||
|
||||
"Convert function to an ES2015 class": {
|
||||
"category": "Message",
|
||||
@@ -3647,16 +3691,13 @@
|
||||
"code": 95002
|
||||
},
|
||||
|
||||
"Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8017
|
||||
},
|
||||
"Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8018
|
||||
},
|
||||
"Report errors in .js files.": {
|
||||
"Extract function": {
|
||||
"category": "Message",
|
||||
"code": 8019
|
||||
"code": 95003
|
||||
},
|
||||
|
||||
"Extract function into {0}": {
|
||||
"category": "Message",
|
||||
"code": 95004
|
||||
}
|
||||
}
|
||||
|
||||
+29
-11
@@ -1195,7 +1195,9 @@ namespace ts {
|
||||
if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) {
|
||||
const dotRangeStart = node.expression.end;
|
||||
const dotRangeEnd = skipTrivia(currentSourceFile.text, node.expression.end) + 1;
|
||||
const dotToken = <Node>{ kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd };
|
||||
const dotToken = createToken(SyntaxKind.DotToken);
|
||||
dotToken.pos = dotRangeStart;
|
||||
dotToken.end = dotRangeEnd;
|
||||
indentBeforeDot = needsIndentation(node, node.expression, dotToken);
|
||||
indentAfterDot = needsIndentation(node, dotToken, node.name);
|
||||
}
|
||||
@@ -1346,7 +1348,9 @@ namespace ts {
|
||||
|
||||
emitExpression(node.left);
|
||||
increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined);
|
||||
emitLeadingCommentsOfPosition(node.operatorToken.pos);
|
||||
writeTokenNode(node.operatorToken);
|
||||
emitTrailingCommentsOfPosition(node.operatorToken.end, /*prefixSpace*/ true); // Binary operators should have a space before the comment starts
|
||||
increaseIndentIf(indentAfterOperator, " ");
|
||||
emitExpression(node.right);
|
||||
decreaseIndentIf(indentBeforeOperator, indentAfterOperator);
|
||||
@@ -1570,8 +1574,20 @@ namespace ts {
|
||||
write(";");
|
||||
}
|
||||
|
||||
function emitTokenWithComment(token: SyntaxKind, pos: number, contextNode?: Node) {
|
||||
const node = contextNode && getParseTreeNode(contextNode);
|
||||
if (node && node.kind === contextNode.kind) {
|
||||
pos = skipTrivia(currentSourceFile.text, pos);
|
||||
}
|
||||
pos = writeToken(token, pos, /*contextNode*/ contextNode);
|
||||
if (node && node.kind === contextNode.kind) {
|
||||
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
function emitReturnStatement(node: ReturnStatement) {
|
||||
writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node);
|
||||
emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node);
|
||||
emitExpressionWithPrefix(" ", node.expression);
|
||||
write(";");
|
||||
}
|
||||
@@ -2131,10 +2147,12 @@ namespace ts {
|
||||
function emitCatchClause(node: CatchClause) {
|
||||
const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos);
|
||||
write(" ");
|
||||
writeToken(SyntaxKind.OpenParenToken, openParenPos);
|
||||
emit(node.variableDeclaration);
|
||||
writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos);
|
||||
write(" ");
|
||||
if (node.variableDeclaration) {
|
||||
writeToken(SyntaxKind.OpenParenToken, openParenPos);
|
||||
emit(node.variableDeclaration);
|
||||
writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end);
|
||||
write(" ");
|
||||
}
|
||||
emit(node.block);
|
||||
}
|
||||
|
||||
@@ -2228,7 +2246,7 @@ namespace ts {
|
||||
* Emits any prologue directives at the start of a Statement list, returning the
|
||||
* number of prologue directives written to the output.
|
||||
*/
|
||||
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, seenPrologueDirectives?: Map<true>): number {
|
||||
function emitPrologueDirectives(statements: ReadonlyArray<Node>, startWithNewLine?: boolean, seenPrologueDirectives?: Map<true>): number {
|
||||
for (let i = 0; i < statements.length; i++) {
|
||||
const statement = statements[i];
|
||||
if (isPrologueDirective(statement)) {
|
||||
@@ -2761,7 +2779,7 @@ namespace ts {
|
||||
return generateName(node);
|
||||
}
|
||||
else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) {
|
||||
return unescapeLeadingUnderscores(node.text);
|
||||
return unescapeLeadingUnderscores(node.escapedText);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.StringLiteral && (<StringLiteral>node).textSourceNode) {
|
||||
return getTextOfNode((<StringLiteral>node).textSourceNode, includeTrivia);
|
||||
@@ -2917,8 +2935,8 @@ namespace ts {
|
||||
*/
|
||||
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
|
||||
const expr = getExternalModuleName(node);
|
||||
const baseName = expr.kind === SyntaxKind.StringLiteral ?
|
||||
makeIdentifierFromModuleName((<LiteralExpression>expr).text) : "module";
|
||||
const baseName = isStringLiteral(expr) ?
|
||||
makeIdentifierFromModuleName(expr.text) : "module";
|
||||
return makeUniqueName(baseName);
|
||||
}
|
||||
|
||||
@@ -2981,7 +2999,7 @@ namespace ts {
|
||||
case GeneratedIdentifierKind.Loop:
|
||||
return makeTempVariableName(TempFlags._i);
|
||||
case GeneratedIdentifierKind.Unique:
|
||||
return makeUniqueName(unescapeLeadingUnderscores(name.text));
|
||||
return makeUniqueName(unescapeLeadingUnderscores(name.escapedText));
|
||||
}
|
||||
|
||||
Debug.fail("Unsupported GeneratedIdentifierKind.");
|
||||
|
||||
+394
-130
File diff suppressed because it is too large
Load Diff
@@ -19,13 +19,26 @@ namespace ts {
|
||||
push(value: T): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of trying to resolve a module.
|
||||
* At least one of `ts` and `js` should be defined, or the whole thing should be `undefined`.
|
||||
*/
|
||||
function withPackageId(packageId: PackageId | undefined, r: PathAndExtension | undefined): Resolved {
|
||||
return r && { path: r.path, extension: r.ext, packageId };
|
||||
}
|
||||
|
||||
function noPackageId(r: PathAndExtension | undefined): Resolved {
|
||||
return withPackageId(/*packageId*/ undefined, r);
|
||||
}
|
||||
|
||||
/** Result of trying to resolve a module. */
|
||||
interface Resolved {
|
||||
path: string;
|
||||
extension: Extension;
|
||||
packageId: PackageId | undefined;
|
||||
}
|
||||
|
||||
/** Result of trying to resolve a module at a file. Needs to have 'packageId' added later. */
|
||||
interface PathAndExtension {
|
||||
path: string;
|
||||
// (Use a different name than `extension` to make sure Resolved isn't assignable to PathAndExtension.)
|
||||
ext: Extension;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,24 +62,27 @@ namespace ts {
|
||||
|
||||
function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations {
|
||||
return {
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, isExternalLibraryImport },
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, isExternalLibraryImport, packageId: resolved.packageId },
|
||||
failedLookupLocations
|
||||
};
|
||||
}
|
||||
|
||||
export function moduleHasNonRelativeName(moduleName: string): boolean {
|
||||
return !(isRootedDiskPath(moduleName) || isExternalModuleNameRelative(moduleName));
|
||||
}
|
||||
|
||||
interface ModuleResolutionState {
|
||||
host: ModuleResolutionHost;
|
||||
compilerOptions: CompilerOptions;
|
||||
traceEnabled: boolean;
|
||||
}
|
||||
|
||||
interface PackageJson {
|
||||
name?: string;
|
||||
version?: string;
|
||||
typings?: string;
|
||||
types?: string;
|
||||
main?: string;
|
||||
}
|
||||
|
||||
/** Reads from "main" or "types"/"typings" depending on `extensions`. */
|
||||
function tryReadPackageJsonFields(readTypes: boolean, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string | undefined {
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState): string | undefined {
|
||||
return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main");
|
||||
|
||||
function tryReadFromField(fieldName: "typings" | "types" | "main"): string | undefined {
|
||||
@@ -93,7 +109,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } {
|
||||
function readJson(path: string, host: ModuleResolutionHost): PackageJson {
|
||||
try {
|
||||
const jsonText = host.readFile(path);
|
||||
return jsonText ? JSON.parse(jsonText) : {};
|
||||
@@ -184,7 +200,10 @@ namespace ts {
|
||||
|
||||
let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
|
||||
if (resolved) {
|
||||
resolved = realpath(resolved, host, traceEnabled);
|
||||
if (!options.preserveSymlinks) {
|
||||
resolved = realPath(resolved, host, traceEnabled);
|
||||
}
|
||||
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, primary);
|
||||
}
|
||||
@@ -266,6 +285,8 @@ namespace ts {
|
||||
for (const typeDirectivePath of host.getDirectories(root)) {
|
||||
const normalized = normalizePath(typeDirectivePath);
|
||||
const packageJsonPath = pathToPackageJson(combinePaths(root, normalized));
|
||||
// `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types.
|
||||
// See `createNotNeededPackageJSON` in the types-publisher` repo.
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null;
|
||||
if (!isNotNeededPackage) {
|
||||
@@ -318,7 +339,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getOrCreateCacheForModuleName(nonRelativeModuleName: string) {
|
||||
if (!moduleHasNonRelativeName(nonRelativeModuleName)) {
|
||||
if (isExternalModuleNameRelative(nonRelativeModuleName)) {
|
||||
return undefined;
|
||||
}
|
||||
let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName);
|
||||
@@ -535,7 +556,7 @@ namespace ts {
|
||||
function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
if (!isExternalModuleNameRelative(moduleName)) {
|
||||
return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state);
|
||||
}
|
||||
else {
|
||||
@@ -654,7 +675,7 @@ namespace ts {
|
||||
if (extension !== undefined) {
|
||||
const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
if (path !== undefined) {
|
||||
return { path, extension };
|
||||
return { path, extension, packageId: undefined };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,7 +707,7 @@ namespace ts {
|
||||
const { resolvedModule, failedLookupLocations } =
|
||||
nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
|
||||
if (!resolvedModule) {
|
||||
throw new Error(`Could not resolve JS module ${moduleName} starting at ${initialDir}. Looked in: ${failedLookupLocations.join(", ")}`);
|
||||
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`);
|
||||
}
|
||||
return resolvedModule.resolvedFileName;
|
||||
}
|
||||
@@ -711,23 +732,30 @@ namespace ts {
|
||||
return toSearchResult({ resolved, isExternalLibraryImport: false });
|
||||
}
|
||||
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
if (!isExternalModuleNameRelative(moduleName)) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]);
|
||||
}
|
||||
const resolved = loadModuleFromNodeModules(extensions, moduleName, containingDirectory, failedLookupLocations, state, cache);
|
||||
if (!resolved) return undefined;
|
||||
|
||||
let resolvedValue = resolved.value;
|
||||
if (!compilerOptions.preserveSymlinks) {
|
||||
resolvedValue = resolvedValue && { ...resolved.value, path: realPath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension };
|
||||
}
|
||||
// For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files.
|
||||
return resolved && { value: resolved.value && { resolved: { path: realpath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension }, isExternalLibraryImport: true } };
|
||||
return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } };
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
const { path: candidate, parts } = normalizePathAndParts(combinePaths(containingDirectory, moduleName));
|
||||
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true);
|
||||
return resolved && toSearchResult({ resolved, isExternalLibraryImport: false });
|
||||
// Treat explicit "node_modules" import as an external library import.
|
||||
return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function realpath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
|
||||
function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
|
||||
if (!host.realpath) {
|
||||
return path;
|
||||
}
|
||||
@@ -755,7 +783,7 @@ namespace ts {
|
||||
}
|
||||
const resolvedFromFile = loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (resolvedFromFile) {
|
||||
return resolvedFromFile;
|
||||
return noPackageId(resolvedFromFile);
|
||||
}
|
||||
}
|
||||
if (!onlyRecordFailures) {
|
||||
@@ -776,11 +804,15 @@ namespace ts {
|
||||
return !host.directoryExists || host.directoryExists(directoryName);
|
||||
}
|
||||
|
||||
function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved {
|
||||
return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | 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, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (resolvedByAddingExtension) {
|
||||
@@ -800,7 +832,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Try to return an existing file that adds one of the `extensions` to `candidate`. */
|
||||
function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | 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);
|
||||
@@ -818,9 +850,9 @@ namespace ts {
|
||||
return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
|
||||
}
|
||||
|
||||
function tryExtension(extension: Extension): Resolved | undefined {
|
||||
const path = tryFile(candidate + extension, failedLookupLocations, onlyRecordFailures, state);
|
||||
return path && { path, extension };
|
||||
function tryExtension(ext: Extension): PathAndExtension | undefined {
|
||||
const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state);
|
||||
return path && { path, ext };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,12 +878,23 @@ namespace ts {
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true): Resolved | undefined {
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
|
||||
let packageId: PackageId | undefined;
|
||||
|
||||
if (considerPackageJson) {
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
const fromPackageJson = loadModuleFromPackageJson(packageJsonPath, extensions, candidate, failedLookupLocations, state);
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
|
||||
if (typeof jsonContent.name === "string" && typeof jsonContent.version === "string") {
|
||||
packageId = { name: jsonContent.name, version: jsonContent.version };
|
||||
}
|
||||
|
||||
const fromPackageJson = loadModuleFromPackageJson(jsonContent, extensions, candidate, failedLookupLocations, state);
|
||||
if (fromPackageJson) {
|
||||
return fromPackageJson;
|
||||
return withPackageId(packageId, fromPackageJson);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -863,15 +906,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state);
|
||||
return withPackageId(packageId, loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state));
|
||||
}
|
||||
|
||||
function loadModuleFromPackageJson(packageJsonPath: string, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
|
||||
const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, packageJsonPath, candidate, state);
|
||||
function loadModuleFromPackageJson(jsonContent: PackageJson, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): PathAndExtension | undefined {
|
||||
const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, jsonContent, candidate, state);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -891,13 +930,18 @@ namespace ts {
|
||||
// Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types"
|
||||
const nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions;
|
||||
// Don't do package.json lookup recursively, because Node.js' package lookup doesn't.
|
||||
return nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false);
|
||||
const result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false);
|
||||
if (result) {
|
||||
// It won't have a `packageId` set, because we disabled `considerPackageJson`.
|
||||
Debug.assert(result.packageId === undefined);
|
||||
return { path: result.path, ext: result.extension };
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): Resolved | undefined {
|
||||
const extension = tryGetExtensionFromPath(path);
|
||||
return extension !== undefined && extensionIsOk(extensions, extension) ? { path, extension } : undefined;
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): PathAndExtension | undefined {
|
||||
const ext = tryGetExtensionFromPath(path);
|
||||
return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext } : undefined;
|
||||
}
|
||||
|
||||
/** True if `extension` is one of the supported `extensions`. */
|
||||
@@ -919,7 +963,7 @@ namespace ts {
|
||||
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
|
||||
|
||||
return loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) ||
|
||||
return loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) ||
|
||||
loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state);
|
||||
}
|
||||
|
||||
@@ -1004,7 +1048,7 @@ namespace ts {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
|
||||
}
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension } };
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,13 +1062,13 @@ namespace ts {
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, /*isExternalLibraryImport*/ false, failedLookupLocations);
|
||||
|
||||
function tryResolve(extensions: Extensions): SearchResult<Resolved> {
|
||||
const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, state);
|
||||
const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, failedLookupLocations, state);
|
||||
if (resolvedUsingSettings) {
|
||||
return { value: resolvedUsingSettings };
|
||||
}
|
||||
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName);
|
||||
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
if (!isExternalModuleNameRelative(moduleName)) {
|
||||
// Climb up parent directories looking for a module.
|
||||
const resolved = forEachAncestorDirectory(containingDirectory, directory => {
|
||||
const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, traceEnabled, host);
|
||||
@@ -1032,7 +1076,7 @@ namespace ts {
|
||||
return resolutionFromCache;
|
||||
}
|
||||
const searchName = normalizePath(combinePaths(directory, moduleName));
|
||||
return toSearchResult(loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
});
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
@@ -1044,7 +1088,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
return toSearchResult(loadModuleFromFile(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+461
-571
File diff suppressed because it is too large
Load Diff
+167
-55
@@ -3,7 +3,6 @@
|
||||
/// <reference path="core.ts" />
|
||||
|
||||
namespace ts {
|
||||
const emptyArray: any[] = [];
|
||||
const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/;
|
||||
|
||||
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string {
|
||||
@@ -206,13 +205,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
|
||||
let diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
|
||||
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
program.getGlobalDiagnostics(cancellationToken),
|
||||
program.getSemanticDiagnostics(sourceFile, cancellationToken));
|
||||
const diagnostics = [
|
||||
...program.getOptionsDiagnostics(cancellationToken),
|
||||
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
...program.getGlobalDiagnostics(cancellationToken),
|
||||
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
|
||||
];
|
||||
|
||||
if (program.getCompilerOptions().declaration) {
|
||||
diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken));
|
||||
addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, cancellationToken));
|
||||
}
|
||||
|
||||
return sortAndDeduplicateDiagnostics(diagnostics);
|
||||
@@ -224,7 +225,7 @@ namespace ts {
|
||||
getNewLine(): string;
|
||||
}
|
||||
|
||||
export function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string {
|
||||
export function formatDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, host: FormatDiagnosticsHost): string {
|
||||
let output = "";
|
||||
|
||||
for (const diagnostic of diagnostics) {
|
||||
@@ -332,6 +333,7 @@ namespace ts {
|
||||
const categoryColor = getCategoryFormat(diagnostic.category);
|
||||
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
|
||||
output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`;
|
||||
output += sys.newLine;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -399,7 +401,7 @@ namespace ts {
|
||||
* @param oldProgram - Reuses an old program structure.
|
||||
* @returns A 'Program' object.
|
||||
*/
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
|
||||
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
let commonSourceDirectory: string;
|
||||
@@ -441,13 +443,13 @@ namespace ts {
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
|
||||
// Map storing if there is emit blocking diagnostics for given input
|
||||
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
|
||||
const hasEmitBlockingDiagnostics = createMap<boolean>();
|
||||
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression;
|
||||
|
||||
let moduleResolutionCache: ModuleResolutionCache;
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModuleFull[];
|
||||
if (host.resolveModuleNames) {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile).map(resolved => {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(checkAllDefined(moduleNames), containingFile).map(resolved => {
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
|
||||
return resolved as ResolvedModuleFull;
|
||||
@@ -460,22 +462,31 @@ namespace ts {
|
||||
else {
|
||||
moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x));
|
||||
const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule;
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(moduleNames, containingFile, loader);
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache(checkAllDefined(moduleNames), containingFile, loader);
|
||||
}
|
||||
|
||||
let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
|
||||
if (host.resolveTypeReferenceDirectives) {
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile);
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives(checkAllDefined(typeDirectiveNames), containingFile);
|
||||
}
|
||||
else {
|
||||
const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective;
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(typeReferenceDirectiveNames, containingFile, loader);
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache(checkAllDefined(typeReferenceDirectiveNames), containingFile, loader);
|
||||
}
|
||||
|
||||
// Map from a stringified PackageId to the source file with that id.
|
||||
// Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile).
|
||||
// `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around.
|
||||
const packageIdToSourceFile = createMap<SourceFile>();
|
||||
// Maps from a SourceFile's `.path` to the name of the package it was imported with.
|
||||
let sourceFileToPackageName = createMap<string>();
|
||||
// See `sourceFileIsRedirectedTo`.
|
||||
let redirectTargetsSet = createMap<true>();
|
||||
|
||||
const filesByName = createMap<SourceFile | undefined>();
|
||||
// stores 'filename -> file association' ignoring case
|
||||
// used to track cases when two file names differ only in casing
|
||||
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined;
|
||||
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap<SourceFile>() : undefined;
|
||||
|
||||
const structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
if (structuralIsReused !== StructureIsReused.Completely) {
|
||||
@@ -548,6 +559,8 @@ namespace ts {
|
||||
isSourceFileFromExternalLibrary,
|
||||
dropDiagnosticsProducingTypeChecker,
|
||||
getSourceFileFromReference,
|
||||
sourceFileToPackageName,
|
||||
redirectTargetsSet,
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
@@ -556,6 +569,10 @@ namespace ts {
|
||||
|
||||
return program;
|
||||
|
||||
function toPath(fileName: string): Path {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
|
||||
@@ -769,8 +786,12 @@ namespace ts {
|
||||
const modifiedSourceFiles: { oldFile: SourceFile, newFile: SourceFile }[] = [];
|
||||
oldProgram.structureIsReused = StructureIsReused.Completely;
|
||||
|
||||
for (const oldSourceFile of oldProgram.getSourceFiles()) {
|
||||
const newSourceFile = host.getSourceFileByPath
|
||||
const oldSourceFiles = oldProgram.getSourceFiles();
|
||||
const enum SeenPackageName { Exists, Modified }
|
||||
const seenPackageNames = createMap<SeenPackageName>();
|
||||
|
||||
for (const oldSourceFile of oldSourceFiles) {
|
||||
let newSourceFile = host.getSourceFileByPath
|
||||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target)
|
||||
: host.getSourceFile(oldSourceFile.fileName, options.target);
|
||||
|
||||
@@ -778,10 +799,46 @@ namespace ts {
|
||||
return oldProgram.structureIsReused = StructureIsReused.Not;
|
||||
}
|
||||
|
||||
Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`");
|
||||
|
||||
let fileChanged: boolean;
|
||||
if (oldSourceFile.redirectInfo) {
|
||||
// We got `newSourceFile` by path, so it is actually for the unredirected file.
|
||||
// This lets us know if the unredirected file has changed. If it has we should break the redirect.
|
||||
if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) {
|
||||
// Underlying file has changed. Might not redirect anymore. Must rebuild program.
|
||||
return oldProgram.structureIsReused = StructureIsReused.Not;
|
||||
}
|
||||
fileChanged = false;
|
||||
newSourceFile = oldSourceFile; // Use the redirect.
|
||||
}
|
||||
else if (oldProgram.redirectTargetsSet.has(oldSourceFile.path)) {
|
||||
// If a redirected-to source file changes, the redirect may be broken.
|
||||
if (newSourceFile !== oldSourceFile) {
|
||||
return oldProgram.structureIsReused = StructureIsReused.Not;
|
||||
}
|
||||
fileChanged = false;
|
||||
}
|
||||
else {
|
||||
fileChanged = newSourceFile !== oldSourceFile;
|
||||
}
|
||||
|
||||
newSourceFile.path = oldSourceFile.path;
|
||||
filePaths.push(newSourceFile.path);
|
||||
|
||||
if (oldSourceFile !== newSourceFile) {
|
||||
const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
|
||||
if (packageName !== undefined) {
|
||||
// If there are 2 different source files for the same package name and at least one of them changes,
|
||||
// they might become redirects. So we must rebuild the program.
|
||||
const prevKind = seenPackageNames.get(packageName);
|
||||
const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists;
|
||||
if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) {
|
||||
return oldProgram.structureIsReused = StructureIsReused.Not;
|
||||
}
|
||||
seenPackageNames.set(packageName, newKind);
|
||||
}
|
||||
|
||||
if (fileChanged) {
|
||||
// The `newSourceFile` object was created for the new program.
|
||||
|
||||
if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) {
|
||||
@@ -893,6 +950,9 @@ namespace ts {
|
||||
}
|
||||
resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives();
|
||||
|
||||
sourceFileToPackageName = oldProgram.sourceFileToPackageName;
|
||||
redirectTargetsSet = oldProgram.redirectTargetsSet;
|
||||
|
||||
return oldProgram.structureIsReused = StructureIsReused.Completely;
|
||||
}
|
||||
|
||||
@@ -934,11 +994,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isEmitBlocked(emitFileName: string): boolean {
|
||||
return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName));
|
||||
return hasEmitBlockingDiagnostics.has(toPath(emitFileName));
|
||||
}
|
||||
|
||||
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
|
||||
let declarationDiagnostics: Diagnostic[] = [];
|
||||
let declarationDiagnostics: ReadonlyArray<Diagnostic> = [];
|
||||
|
||||
if (options.noEmit) {
|
||||
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
|
||||
@@ -948,10 +1008,12 @@ namespace ts {
|
||||
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
|
||||
// get any preEmit diagnostics, not just the ones
|
||||
if (options.noEmitOnError) {
|
||||
const diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
|
||||
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
program.getGlobalDiagnostics(cancellationToken),
|
||||
program.getSemanticDiagnostics(sourceFile, cancellationToken));
|
||||
const diagnostics = [
|
||||
...program.getOptionsDiagnostics(cancellationToken),
|
||||
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
...program.getGlobalDiagnostics(cancellationToken),
|
||||
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
|
||||
];
|
||||
|
||||
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
|
||||
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
|
||||
@@ -993,7 +1055,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string): SourceFile {
|
||||
return getSourceFileByPath(toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
return getSourceFileByPath(toPath(fileName));
|
||||
}
|
||||
|
||||
function getSourceFileByPath(path: Path): SourceFile {
|
||||
@@ -1002,8 +1064,8 @@ namespace ts {
|
||||
|
||||
function getDiagnosticsHelper(
|
||||
sourceFile: SourceFile,
|
||||
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
|
||||
cancellationToken: CancellationToken): Diagnostic[] {
|
||||
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => ReadonlyArray<Diagnostic>,
|
||||
cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
if (sourceFile) {
|
||||
return getDiagnostics(sourceFile, cancellationToken);
|
||||
}
|
||||
@@ -1015,15 +1077,15 @@ namespace ts {
|
||||
}));
|
||||
}
|
||||
|
||||
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken);
|
||||
}
|
||||
|
||||
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken);
|
||||
}
|
||||
|
||||
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
const options = program.getCompilerOptions();
|
||||
// collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit)
|
||||
if (!sourceFile || options.out || options.outFile) {
|
||||
@@ -1034,7 +1096,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): ReadonlyArray<Diagnostic> {
|
||||
// For JavaScript files, we report semantic errors for using TypeScript-only
|
||||
// constructs from within a JavaScript file as syntactic errors.
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
@@ -1192,10 +1254,14 @@ namespace ts {
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
|
||||
return;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
const typeAssertionExpression = <TypeAssertion>node;
|
||||
diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
|
||||
case SyntaxKind.NonNullExpression:
|
||||
diagnostics.push(createDiagnosticForNode(node, Diagnostics.non_null_assertions_can_only_be_used_in_a_ts_file));
|
||||
return;
|
||||
case SyntaxKind.AsExpression:
|
||||
diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
|
||||
return;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX.
|
||||
}
|
||||
|
||||
const prevParent = parent;
|
||||
@@ -1385,8 +1451,8 @@ namespace ts {
|
||||
const isExternalModuleFile = isExternalModule(file);
|
||||
|
||||
// file.imports may not be undefined if there exists dynamic import
|
||||
let imports: LiteralExpression[];
|
||||
let moduleAugmentations: LiteralExpression[];
|
||||
let imports: StringLiteral[];
|
||||
let moduleAugmentations: StringLiteral[];
|
||||
let ambientModules: string[];
|
||||
|
||||
// If we are importing helpers, we need to add a synthetic reference to resolve the
|
||||
@@ -1421,35 +1487,36 @@ namespace ts {
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
const moduleNameExpr = getExternalModuleName(node);
|
||||
if (!moduleNameExpr || moduleNameExpr.kind !== SyntaxKind.StringLiteral) {
|
||||
if (!moduleNameExpr || !isStringLiteral(moduleNameExpr)) {
|
||||
break;
|
||||
}
|
||||
if (!(<LiteralExpression>moduleNameExpr).text) {
|
||||
if (!moduleNameExpr.text) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TypeScript 1.0 spec (April 2014): 12.1.6
|
||||
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
|
||||
// only through top - level external module names. Relative external module names are not permitted.
|
||||
if (!inAmbientModule || !isExternalModuleNameRelative((<LiteralExpression>moduleNameExpr).text)) {
|
||||
(imports || (imports = [])).push(<LiteralExpression>moduleNameExpr);
|
||||
if (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text)) {
|
||||
(imports || (imports = [])).push(moduleNameExpr);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) {
|
||||
const moduleName = <LiteralExpression>(<ModuleDeclaration>node).name;
|
||||
const moduleName = <StringLiteral>(<ModuleDeclaration>node).name; // TODO: GH#17347
|
||||
const nameText = ts.getTextOfIdentifierOrLiteral(moduleName);
|
||||
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
|
||||
// This will happen in two cases:
|
||||
// - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
|
||||
// - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name
|
||||
// immediately nested in top level ambient module declaration .
|
||||
if (isExternalModuleFile || (inAmbientModule && !isExternalModuleNameRelative(moduleName.text))) {
|
||||
if (isExternalModuleFile || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
|
||||
(moduleAugmentations || (moduleAugmentations = [])).push(moduleName);
|
||||
}
|
||||
else if (!inAmbientModule) {
|
||||
if (file.isDeclarationFile) {
|
||||
// for global .d.ts files record name of ambient module
|
||||
(ambientModules || (ambientModules = [])).push(moduleName.text);
|
||||
(ambientModules || (ambientModules = [])).push(nameText);
|
||||
}
|
||||
// An AmbientExternalModuleDeclaration declares an external module.
|
||||
// This type of declaration is permitted only in the global module.
|
||||
@@ -1484,7 +1551,7 @@ namespace ts {
|
||||
|
||||
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
|
||||
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
|
||||
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName, currentDirectory, getCanonicalFileName)));
|
||||
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)));
|
||||
}
|
||||
|
||||
function getSourceFileFromReferenceWorker(
|
||||
@@ -1528,7 +1595,7 @@ namespace ts {
|
||||
/** This has side effects through `findSourceFile`. */
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
|
||||
getSourceFileFromReferenceWorker(fileName,
|
||||
fileName => findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd),
|
||||
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile, refPos, refEnd, /*packageId*/ undefined),
|
||||
(diagnostic, ...args) => {
|
||||
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
|
||||
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
|
||||
@@ -1547,8 +1614,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path): SourceFile {
|
||||
const redirect: SourceFile = Object.create(redirectTarget);
|
||||
redirect.fileName = fileName;
|
||||
redirect.path = path;
|
||||
redirect.redirectInfo = { redirectTarget, unredirected };
|
||||
Object.defineProperties(redirect, {
|
||||
id: {
|
||||
get(this: SourceFile) { return this.redirectInfo.redirectTarget.id; },
|
||||
set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo.redirectTarget.id = value; },
|
||||
},
|
||||
symbol: {
|
||||
get(this: SourceFile) { return this.redirectInfo.redirectTarget.symbol; },
|
||||
set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo.redirectTarget.symbol = value; },
|
||||
},
|
||||
});
|
||||
return redirect;
|
||||
}
|
||||
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
|
||||
if (filesByName.has(path)) {
|
||||
const file = filesByName.get(path);
|
||||
// try to check if we've already seen this file but with a different casing in path
|
||||
@@ -1591,19 +1676,40 @@ namespace ts {
|
||||
}
|
||||
});
|
||||
|
||||
if (packageId) {
|
||||
const packageIdKey = `${packageId.name}@${packageId.version}`;
|
||||
const fileFromPackageId = packageIdToSourceFile.get(packageIdKey);
|
||||
if (fileFromPackageId) {
|
||||
// Some other SourceFile already exists with this package name and version.
|
||||
// Instead of creating a duplicate, just redirect to the existing one.
|
||||
const dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path);
|
||||
redirectTargetsSet.set(fileFromPackageId.path, true);
|
||||
filesByName.set(path, dupFile);
|
||||
sourceFileToPackageName.set(path, packageId.name);
|
||||
files.push(dupFile);
|
||||
return dupFile;
|
||||
}
|
||||
else if (file) {
|
||||
// This is the first source file to have this packageId.
|
||||
packageIdToSourceFile.set(packageIdKey, file);
|
||||
sourceFileToPackageName.set(path, packageId.name);
|
||||
}
|
||||
}
|
||||
|
||||
filesByName.set(path, file);
|
||||
if (file) {
|
||||
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
|
||||
file.path = path;
|
||||
|
||||
if (host.useCaseSensitiveFileNames()) {
|
||||
const pathLowerCase = path.toLowerCase();
|
||||
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
|
||||
const existingFile = filesByNameIgnoreCase.get(path);
|
||||
const existingFile = filesByNameIgnoreCase.get(pathLowerCase);
|
||||
if (existingFile) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
|
||||
}
|
||||
else {
|
||||
filesByNameIgnoreCase.set(path, file);
|
||||
filesByNameIgnoreCase.set(pathLowerCase, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1750,9 +1856,9 @@ namespace ts {
|
||||
modulesWithElidedImports.set(file.path, true);
|
||||
}
|
||||
else if (shouldAddFile) {
|
||||
const path = toPath(resolvedFileName, currentDirectory, getCanonicalFileName);
|
||||
const path = toPath(resolvedFileName);
|
||||
const pos = skipTrivia(file.text, file.imports[i].pos);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId);
|
||||
}
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
@@ -1969,7 +2075,7 @@ namespace ts {
|
||||
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
|
||||
if (!options.noEmit && !options.suppressOutputPathCheck) {
|
||||
const emitHost = getEmitHost();
|
||||
const emitFilesSeen = createFileMap<boolean>(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : key => key);
|
||||
const emitFilesSeen = createMap<true>();
|
||||
forEachEmittedFile(emitHost, (emitFileNames) => {
|
||||
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
|
||||
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
|
||||
@@ -1977,9 +2083,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Verify that all the emit files are unique and don't overwrite input files
|
||||
function verifyEmitFilePath(emitFileName: string, emitFilesSeen: FileMap<boolean>) {
|
||||
function verifyEmitFilePath(emitFileName: string, emitFilesSeen: Map<true>) {
|
||||
if (emitFileName) {
|
||||
const emitFilePath = toPath(emitFileName, currentDirectory, getCanonicalFileName);
|
||||
const emitFilePath = toPath(emitFileName);
|
||||
// Report error if the output overwrites input file
|
||||
if (filesByName.has(emitFilePath)) {
|
||||
let chain: DiagnosticMessageChain;
|
||||
@@ -1991,13 +2097,14 @@ namespace ts {
|
||||
blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain));
|
||||
}
|
||||
|
||||
const emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath;
|
||||
// Report error if multiple files write into same file
|
||||
if (emitFilesSeen.contains(emitFilePath)) {
|
||||
if (emitFilesSeen.has(emitFileKey)) {
|
||||
// Already seen the same emit file - report error
|
||||
blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName));
|
||||
}
|
||||
else {
|
||||
emitFilesSeen.set(emitFilePath, true);
|
||||
emitFilesSeen.set(emitFileKey, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2089,7 +2196,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) {
|
||||
hasEmitBlockingDiagnostics.set(toPath(emitFileName, currentDirectory, getCanonicalFileName), true);
|
||||
hasEmitBlockingDiagnostics.set(toPath(emitFileName), true);
|
||||
programDiagnostics.add(diag);
|
||||
}
|
||||
}
|
||||
@@ -2121,4 +2228,9 @@ namespace ts {
|
||||
return options.allowJs ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowJs_is_not_set;
|
||||
}
|
||||
}
|
||||
|
||||
function checkAllDefined(names: string[]): string[] {
|
||||
Debug.assert(names.every(name => name !== undefined), "A name is undefined.", () => JSON.stringify(names));
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-6
File diff suppressed because one or more lines are too long
@@ -0,0 +1,191 @@
|
||||
/** @internal */
|
||||
namespace ts {
|
||||
export function createGetSymbolWalker(
|
||||
getRestTypeOfSignature: (sig: Signature) => Type,
|
||||
getReturnTypeOfSignature: (sig: Signature) => Type,
|
||||
getBaseTypes: (type: Type) => Type[],
|
||||
resolveStructuredTypeMembers: (type: ObjectType) => ResolvedType,
|
||||
getTypeOfSymbol: (sym: Symbol) => Type,
|
||||
getResolvedSymbol: (node: Node) => Symbol,
|
||||
getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type,
|
||||
getConstraintFromTypeParameter: (typeParameter: TypeParameter) => Type,
|
||||
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier) {
|
||||
|
||||
return getSymbolWalker;
|
||||
|
||||
function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker {
|
||||
const visitedTypes = createMap<Type>(); // Key is id as string
|
||||
const visitedSymbols = createMap<Symbol>(); // Key is id as string
|
||||
|
||||
return {
|
||||
walkType: type => {
|
||||
visitedTypes.clear();
|
||||
visitedSymbols.clear();
|
||||
visitType(type);
|
||||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
|
||||
},
|
||||
walkSymbol: symbol => {
|
||||
visitedTypes.clear();
|
||||
visitedSymbols.clear();
|
||||
visitSymbol(symbol);
|
||||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
|
||||
},
|
||||
};
|
||||
|
||||
function visitType(type: Type): void {
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeIdString = type.id.toString();
|
||||
if (visitedTypes.has(typeIdString)) {
|
||||
return;
|
||||
}
|
||||
visitedTypes.set(typeIdString, type);
|
||||
|
||||
// Reuse visitSymbol to visit the type's symbol,
|
||||
// but be sure to bail on recuring into the type if accept declines the symbol.
|
||||
const shouldBail = visitSymbol(type.symbol);
|
||||
if (shouldBail) return;
|
||||
|
||||
// Visit the type's related types, if any
|
||||
if (type.flags & TypeFlags.Object) {
|
||||
const objectType = type as ObjectType;
|
||||
const objectFlags = objectType.objectFlags;
|
||||
if (objectFlags & ObjectFlags.Reference) {
|
||||
visitTypeReference(type as TypeReference);
|
||||
}
|
||||
if (objectFlags & ObjectFlags.Mapped) {
|
||||
visitMappedType(type as MappedType);
|
||||
}
|
||||
if (objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)) {
|
||||
visitInterfaceType(type as InterfaceType);
|
||||
}
|
||||
if (objectFlags & (ObjectFlags.Tuple | ObjectFlags.Anonymous)) {
|
||||
visitObjectType(objectType);
|
||||
}
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
visitTypeParameter(type as TypeParameter);
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
visitUnionOrIntersectionType(type as UnionOrIntersectionType);
|
||||
}
|
||||
if (type.flags & TypeFlags.Index) {
|
||||
visitIndexType(type as IndexType);
|
||||
}
|
||||
if (type.flags & TypeFlags.IndexedAccess) {
|
||||
visitIndexedAccessType(type as IndexedAccessType);
|
||||
}
|
||||
}
|
||||
|
||||
function visitTypeList(types: Type[]): void {
|
||||
if (!types) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
visitType(types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function visitTypeReference(type: TypeReference): void {
|
||||
visitType(type.target);
|
||||
visitTypeList(type.typeArguments);
|
||||
}
|
||||
|
||||
function visitTypeParameter(type: TypeParameter): void {
|
||||
visitType(getConstraintFromTypeParameter(type));
|
||||
}
|
||||
|
||||
function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void {
|
||||
visitTypeList(type.types);
|
||||
}
|
||||
|
||||
function visitIndexType(type: IndexType): void {
|
||||
visitType(type.type);
|
||||
}
|
||||
|
||||
function visitIndexedAccessType(type: IndexedAccessType): void {
|
||||
visitType(type.objectType);
|
||||
visitType(type.indexType);
|
||||
visitType(type.constraint);
|
||||
}
|
||||
|
||||
function visitMappedType(type: MappedType): void {
|
||||
visitType(type.typeParameter);
|
||||
visitType(type.constraintType);
|
||||
visitType(type.templateType);
|
||||
visitType(type.modifiersType);
|
||||
}
|
||||
|
||||
function visitSignature(signature: Signature): void {
|
||||
if (signature.typePredicate) {
|
||||
visitType(signature.typePredicate.type);
|
||||
}
|
||||
visitTypeList(signature.typeParameters);
|
||||
|
||||
for (const parameter of signature.parameters){
|
||||
visitSymbol(parameter);
|
||||
}
|
||||
visitType(getRestTypeOfSignature(signature));
|
||||
visitType(getReturnTypeOfSignature(signature));
|
||||
}
|
||||
|
||||
function visitInterfaceType(interfaceT: InterfaceType): void {
|
||||
visitObjectType(interfaceT);
|
||||
visitTypeList(interfaceT.typeParameters);
|
||||
visitTypeList(getBaseTypes(interfaceT));
|
||||
visitType(interfaceT.thisType);
|
||||
}
|
||||
|
||||
function visitObjectType(type: ObjectType): void {
|
||||
const stringIndexType = getIndexTypeOfStructuredType(type, IndexKind.String);
|
||||
visitType(stringIndexType);
|
||||
const numberIndexType = getIndexTypeOfStructuredType(type, IndexKind.Number);
|
||||
visitType(numberIndexType);
|
||||
|
||||
// The two checks above *should* have already resolved the type (if needed), so this should be cached
|
||||
const resolved = resolveStructuredTypeMembers(type);
|
||||
for (const signature of resolved.callSignatures) {
|
||||
visitSignature(signature);
|
||||
}
|
||||
for (const signature of resolved.constructSignatures) {
|
||||
visitSignature(signature);
|
||||
}
|
||||
for (const p of resolved.properties) {
|
||||
visitSymbol(p);
|
||||
}
|
||||
}
|
||||
|
||||
function visitSymbol(symbol: Symbol): boolean {
|
||||
if (!symbol) {
|
||||
return;
|
||||
}
|
||||
const symbolIdString = getSymbolId(symbol).toString();
|
||||
if (visitedSymbols.has(symbolIdString)) {
|
||||
return;
|
||||
}
|
||||
visitedSymbols.set(symbolIdString, symbol);
|
||||
if (!accept(symbol)) {
|
||||
return true;
|
||||
}
|
||||
const t = getTypeOfSymbol(symbol);
|
||||
visitType(t); // Should handle members on classes and such
|
||||
if (symbol.flags & SymbolFlags.HasExports) {
|
||||
symbol.exports.forEach(visitSymbol);
|
||||
}
|
||||
forEach(symbol.declarations, d => {
|
||||
// Type queries are too far resolved when we just visit the symbol's type
|
||||
// (their type resolved directly to the member deeply referenced)
|
||||
// So to get the intervening symbols, we need to check if there's a type
|
||||
// query node on any of the symbol's declarations and get symbols there
|
||||
if ((d as any).type && (d as any).type.kind === SyntaxKind.TypeQuery) {
|
||||
const query = (d as any).type as TypeQueryNode;
|
||||
const entity = getResolvedSymbol(getFirstIdentifier(query.exprName));
|
||||
visitSymbol(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-10
@@ -4,6 +4,18 @@ declare function setTimeout(handler: (...args: any[]) => void, timeout: number):
|
||||
declare function clearTimeout(handle: any): void;
|
||||
|
||||
namespace ts {
|
||||
/**
|
||||
* Set a high stack trace limit to provide more information in case of an error.
|
||||
* Called for command-line and server use cases.
|
||||
* Not called if TypeScript is used as a library.
|
||||
*/
|
||||
/* @internal */
|
||||
export function setStackTraceLimit() {
|
||||
if ((Error as any).stackTraceLimit < 100) { // Also tests that we won't set the property if it doesn't exist.
|
||||
(Error as any).stackTraceLimit = 100;
|
||||
}
|
||||
}
|
||||
|
||||
export enum FileWatcherEventKind {
|
||||
Created,
|
||||
Changed,
|
||||
@@ -23,7 +35,7 @@ namespace ts {
|
||||
newLine: string;
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
write(s: string): void;
|
||||
readFile(path: string, encoding?: string): string;
|
||||
readFile(path: string, encoding?: string): string | undefined;
|
||||
getFileSize?(path: string): number;
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
/**
|
||||
@@ -39,7 +51,7 @@ namespace ts {
|
||||
getExecutingFilePath(): string;
|
||||
getCurrentDirectory(): string;
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[];
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
/**
|
||||
* This should be cryptographically secure.
|
||||
@@ -97,10 +109,10 @@ namespace ts {
|
||||
directoryExists(path: string): boolean;
|
||||
createDirectory(path: string): void;
|
||||
resolvePath(path: string): string;
|
||||
readFile(path: string): string;
|
||||
readFile(path: string): string | undefined;
|
||||
writeFile(path: string, contents: string): void;
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: string[], basePaths?: string[], excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[];
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, basePaths?: ReadonlyArray<string>, excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[];
|
||||
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
|
||||
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
realpath(path: string): string;
|
||||
@@ -141,7 +153,7 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
watcher = _fs.watch(
|
||||
dirPath,
|
||||
dirPath || ".",
|
||||
{ persistent: true },
|
||||
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
|
||||
);
|
||||
@@ -196,15 +208,22 @@ namespace ts {
|
||||
if (platform === "win32" || platform === "win64") {
|
||||
return false;
|
||||
}
|
||||
// convert current file name to upper case / lower case and check if file exists
|
||||
// (guards against cases when name is already all uppercase or lowercase)
|
||||
return !fileExists(__filename.toUpperCase()) || !fileExists(__filename.toLowerCase());
|
||||
// If this file exists under a different case, we must be case-insensitve.
|
||||
return !fileExists(swapCase(__filename));
|
||||
}
|
||||
|
||||
/** Convert all lowercase chars to uppercase, and vice-versa */
|
||||
function swapCase(s: string): string {
|
||||
return s.replace(/\w/g, (ch) => {
|
||||
const up = ch.toUpperCase();
|
||||
return ch === up ? ch.toLowerCase() : up;
|
||||
});
|
||||
}
|
||||
|
||||
const platform: string = _os.platform();
|
||||
const useCaseSensitiveFileNames = isFileSystemCaseSensitive();
|
||||
|
||||
function readFile(fileName: string, _encoding?: string): string {
|
||||
function readFile(fileName: string, _encoding?: string): string | undefined {
|
||||
if (!fileExists(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -287,7 +306,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[], depth?: number): string[] {
|
||||
function readDirectory(path: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace ts {
|
||||
* @param transforms An array of `TransformerFactory` callbacks.
|
||||
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
|
||||
*/
|
||||
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: T[], transformers: TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
|
||||
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: ReadonlyArray<T>, transformers: ReadonlyArray<TransformerFactory<T>>, allowDtsFiles: boolean): TransformationResult<T> {
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
|
||||
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
|
||||
|
||||
@@ -331,11 +331,14 @@ namespace ts {
|
||||
location
|
||||
);
|
||||
}
|
||||
else if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)) {
|
||||
else if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)
|
||||
|| every(elements, isOmittedExpression)) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
// Or all the elements of the binding pattern are omitted expression such as "var [,] = [1,2]",
|
||||
// then we will create temporary variable.
|
||||
const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0;
|
||||
value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location);
|
||||
}
|
||||
@@ -415,7 +418,7 @@ namespace ts {
|
||||
return createElementAccess(value, argumentExpression);
|
||||
}
|
||||
else {
|
||||
const name = createIdentifier(unescapeLeadingUnderscores(propertyName.text));
|
||||
const name = createIdentifier(unescapeLeadingUnderscores(propertyName.escapedText));
|
||||
return createPropertyAccess(value, name);
|
||||
}
|
||||
}
|
||||
@@ -492,7 +495,7 @@ namespace ts {
|
||||
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
|
||||
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
|
||||
*/
|
||||
function createRestCall(context: TransformationContext, value: Expression, elements: BindingOrAssignmentElement[], computedTempVariables: Expression[], location: TextRange): Expression {
|
||||
function createRestCall(context: TransformationContext, value: Expression, elements: ReadonlyArray<BindingOrAssignmentElement>, computedTempVariables: ReadonlyArray<Expression>, location: TextRange): Expression {
|
||||
context.requestEmitHelper(restHelper);
|
||||
const propertyNames: Expression[] = [];
|
||||
let computedTempVariableOffset = 0;
|
||||
|
||||
@@ -339,64 +339,12 @@ namespace ts {
|
||||
&& !(<ReturnStatement>node).expression;
|
||||
}
|
||||
|
||||
function isClassLikeVariableStatement(node: Node) {
|
||||
if (!isVariableStatement(node)) return false;
|
||||
const variable = singleOrUndefined((<VariableStatement>node).declarationList.declarations);
|
||||
return variable
|
||||
&& variable.initializer
|
||||
&& isIdentifier(variable.name)
|
||||
&& (isClassLike(variable.initializer)
|
||||
|| (isAssignmentExpression(variable.initializer)
|
||||
&& isIdentifier(variable.initializer.left)
|
||||
&& isClassLike(variable.initializer.right)));
|
||||
}
|
||||
|
||||
function isTypeScriptClassWrapper(node: Node) {
|
||||
const call = tryCast(node, isCallExpression);
|
||||
if (!call || isParseTreeNode(call) ||
|
||||
some(call.typeArguments) ||
|
||||
some(call.arguments)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const func = tryCast(skipOuterExpressions(call.expression), isFunctionExpression);
|
||||
if (!func || isParseTreeNode(func) ||
|
||||
some(func.typeParameters) ||
|
||||
some(func.parameters) ||
|
||||
func.type ||
|
||||
!func.body) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const statements = func.body.statements;
|
||||
if (statements.length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firstStatement = statements[0];
|
||||
if (isParseTreeNode(firstStatement) ||
|
||||
!isClassLike(firstStatement) &&
|
||||
!isClassLikeVariableStatement(firstStatement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const lastStatement = elementAt(statements, -1);
|
||||
const returnStatement = tryCast(isVariableStatement(lastStatement) ? elementAt(statements, -2) : lastStatement, isReturnStatement);
|
||||
if (!returnStatement ||
|
||||
!returnStatement.expression ||
|
||||
!isIdentifier(skipOuterExpressions(returnStatement.expression))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldVisitNode(node: Node): boolean {
|
||||
return (node.transformFlags & TransformFlags.ContainsES2015) !== 0
|
||||
|| convertedLoopState !== undefined
|
||||
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && isStatement(node))
|
||||
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block)))
|
||||
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node))
|
||||
|| isTypeScriptClassWrapper(node);
|
||||
|| (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0;
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
@@ -647,7 +595,7 @@ namespace ts {
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
return node;
|
||||
}
|
||||
if (node.text !== "arguments" || !resolver.isArgumentsLocalBinding(node)) {
|
||||
if (node.escapedText !== "arguments" || !resolver.isArgumentsLocalBinding(node)) {
|
||||
return node;
|
||||
}
|
||||
return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments"));
|
||||
@@ -661,7 +609,7 @@ namespace ts {
|
||||
// - break/continue is non-labeled and located in non-converted loop/switch statement
|
||||
const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue;
|
||||
const canUseBreakOrContinue =
|
||||
(node.label && convertedLoopState.labels && convertedLoopState.labels.get(unescapeLeadingUnderscores(node.label.text))) ||
|
||||
(node.label && convertedLoopState.labels && convertedLoopState.labels.get(unescapeLeadingUnderscores(node.label.escapedText))) ||
|
||||
(!node.label && (convertedLoopState.allowedNonLabeledJumps & jump));
|
||||
|
||||
if (!canUseBreakOrContinue) {
|
||||
@@ -679,12 +627,12 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
if (node.kind === SyntaxKind.BreakStatement) {
|
||||
labelMarker = `break-${node.label.text}`;
|
||||
setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeLeadingUnderscores(node.label.text), labelMarker);
|
||||
labelMarker = `break-${node.label.escapedText}`;
|
||||
setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeLeadingUnderscores(node.label.escapedText), labelMarker);
|
||||
}
|
||||
else {
|
||||
labelMarker = `continue-${node.label.text}`;
|
||||
setLabeledJump(convertedLoopState, /*isBreak*/ false, unescapeLeadingUnderscores(node.label.text), labelMarker);
|
||||
labelMarker = `continue-${node.label.escapedText}`;
|
||||
setLabeledJump(convertedLoopState, /*isBreak*/ false, unescapeLeadingUnderscores(node.label.escapedText), labelMarker);
|
||||
}
|
||||
}
|
||||
let returnExpression: Expression = createLiteral(labelMarker);
|
||||
@@ -840,7 +788,7 @@ namespace ts {
|
||||
outer.end = skipTrivia(currentText, node.pos);
|
||||
setEmitFlags(outer, EmitFlags.NoComments);
|
||||
|
||||
return createParen(
|
||||
const result = createParen(
|
||||
createCall(
|
||||
outer,
|
||||
/*typeArguments*/ undefined,
|
||||
@@ -849,6 +797,8 @@ namespace ts {
|
||||
: []
|
||||
)
|
||||
);
|
||||
addSyntheticLeadingComment(result, SyntaxKind.MultiLineCommentTrivia, "* @class ");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1963,7 +1913,7 @@ namespace ts {
|
||||
updated,
|
||||
setTextRange(
|
||||
createNodeArray(
|
||||
prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true)
|
||||
prependCaptureNewTargetIfNeeded(updated.statements as MutableNodeArray<Statement>, node, /*copyOnWrite*/ true)
|
||||
),
|
||||
/*location*/ updated.statements
|
||||
)
|
||||
@@ -2105,13 +2055,14 @@ namespace ts {
|
||||
setCommentRange(declarationList, node);
|
||||
|
||||
if (node.transformFlags & TransformFlags.ContainsBindingPattern
|
||||
&& (isBindingPattern(node.declarations[0].name)
|
||||
|| isBindingPattern(lastOrUndefined(node.declarations).name))) {
|
||||
&& (isBindingPattern(node.declarations[0].name) || isBindingPattern(lastOrUndefined(node.declarations).name))) {
|
||||
// If the first or last declaration is a binding pattern, we need to modify
|
||||
// the source map range for the declaration list.
|
||||
const firstDeclaration = firstOrUndefined(declarations);
|
||||
const lastDeclaration = lastOrUndefined(declarations);
|
||||
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
|
||||
if (firstDeclaration) {
|
||||
const lastDeclaration = lastOrUndefined(declarations);
|
||||
setSourceMapRange(declarationList, createRange(firstDeclaration.pos, lastDeclaration.end));
|
||||
}
|
||||
}
|
||||
|
||||
return declarationList;
|
||||
@@ -2236,11 +2187,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function recordLabel(node: LabeledStatement) {
|
||||
convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.text), true);
|
||||
convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.escapedText), true);
|
||||
}
|
||||
|
||||
function resetLabel(node: LabeledStatement) {
|
||||
convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.text), false);
|
||||
convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.escapedText), false);
|
||||
}
|
||||
|
||||
function visitLabeledStatement(node: LabeledStatement): VisitResult<Statement> {
|
||||
@@ -2491,7 +2442,7 @@ namespace ts {
|
||||
const catchVariable = getGeneratedNameForNode(errorRecord);
|
||||
const returnMethod = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const values = createValuesHelper(context, expression, node.expression);
|
||||
const next = createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []);
|
||||
const next = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []);
|
||||
|
||||
hoistVariableDeclaration(errorRecord);
|
||||
hoistVariableDeclaration(returnMethod);
|
||||
@@ -3053,7 +3004,7 @@ namespace ts {
|
||||
else {
|
||||
loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
|
||||
if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) {
|
||||
const outParamName = createUniqueName("out_" + unescapeLeadingUnderscores(name.text));
|
||||
const outParamName = createUniqueName("out_" + unescapeLeadingUnderscores(name.escapedText));
|
||||
loopOutParameters.push({ originalName: name, outParamName });
|
||||
}
|
||||
}
|
||||
@@ -3173,6 +3124,7 @@ namespace ts {
|
||||
function visitCatchClause(node: CatchClause): CatchClause {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes);
|
||||
let updated: CatchClause;
|
||||
Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015.");
|
||||
if (isBindingPattern(node.variableDeclaration.name)) {
|
||||
const temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const newVariableDeclaration = createVariableDeclaration(temp);
|
||||
@@ -3199,7 +3151,7 @@ namespace ts {
|
||||
|
||||
function addStatementToStartOfBlock(block: Block, statement: Statement): Block {
|
||||
const transformedStatements = visitNodes(block.statements, visitor, isStatement);
|
||||
return updateBlock(block, [statement].concat(transformedStatements));
|
||||
return updateBlock(block, [statement, ...transformedStatements]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3304,13 +3256,14 @@ namespace ts {
|
||||
* @param node a CallExpression.
|
||||
*/
|
||||
function visitCallExpression(node: CallExpression) {
|
||||
if (isTypeScriptClassWrapper(node)) {
|
||||
if (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) {
|
||||
return visitTypeScriptClassWrapper(node);
|
||||
}
|
||||
|
||||
if (node.transformFlags & TransformFlags.ES2015) {
|
||||
return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true);
|
||||
}
|
||||
|
||||
return updateCall(
|
||||
node,
|
||||
visitNode(node.expression, callExpressionVisitor, isExpression),
|
||||
@@ -3353,7 +3306,7 @@ namespace ts {
|
||||
|
||||
// We skip any outer expressions in a number of places to get to the innermost
|
||||
// expression, but we will restore them later to preserve comments and source maps.
|
||||
const body = cast(skipOuterExpressions(node.expression), isFunctionExpression).body;
|
||||
const body = cast(cast(skipOuterExpressions(node.expression), isArrowFunction).body, isBlock);
|
||||
|
||||
// The class statements are the statements generated by visiting the first statement of the
|
||||
// body (1), while all other statements are added to remainingStatements (2)
|
||||
@@ -3579,7 +3532,7 @@ namespace ts {
|
||||
// Map spans of spread expressions into their expressions and spans of other
|
||||
// expressions into an array literal.
|
||||
const numElements = elements.length;
|
||||
const segments = flatten(
|
||||
const segments = flatten<Expression>(
|
||||
spanMap(elements, partitionSpread, (partition, visitPartition, _start, end) =>
|
||||
visitPartition(partition, multiLine, hasTrailingComma && end === numElements)
|
||||
)
|
||||
@@ -3591,7 +3544,7 @@ namespace ts {
|
||||
if (isCallExpression(firstSegment)
|
||||
&& isIdentifier(firstSegment.expression)
|
||||
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
|
||||
&& firstSegment.expression.text === "___spread") {
|
||||
&& firstSegment.expression.escapedText === "___spread") {
|
||||
return segments[0];
|
||||
}
|
||||
}
|
||||
@@ -3842,7 +3795,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitMetaProperty(node: MetaProperty) {
|
||||
if (node.keywordToken === SyntaxKind.NewKeyword && node.name.text === "target") {
|
||||
if (node.keywordToken === SyntaxKind.NewKeyword && node.name.escapedText === "target") {
|
||||
if (hierarchyFacts & HierarchyFacts.ComputedPropertyName) {
|
||||
hierarchyFacts |= HierarchyFacts.NewTargetInComputedPropertyName;
|
||||
}
|
||||
@@ -4067,7 +4020,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const expression = (<SpreadElement>callArgument).expression;
|
||||
return isIdentifier(expression) && expression.text === "arguments";
|
||||
return isIdentifier(expression) && expression.escapedText === "arguments";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ namespace ts {
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
createLiteral(unescapeLeadingUnderscores(node.name.text)),
|
||||
createLiteral(unescapeLeadingUnderscores(node.name.escapedText)),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace ts {
|
||||
* @param name An Identifier
|
||||
*/
|
||||
function trySubstituteReservedName(name: Identifier) {
|
||||
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(unescapeLeadingUnderscores(name.text)) : undefined);
|
||||
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(unescapeLeadingUnderscores(name.escapedText)) : undefined);
|
||||
if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
|
||||
return setTextRange(createLiteral(name), name);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ namespace ts {
|
||||
return visitExpressionStatement(node as ExpressionStatement);
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
|
||||
case SyntaxKind.CatchClause:
|
||||
return visitCatchClause(node as CatchClause);
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@@ -156,8 +158,8 @@ namespace ts {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function chunkObjectLiteralElements(elements: ObjectLiteralElement[]): Expression[] {
|
||||
let chunkObject: (ShorthandPropertyAssignment | PropertyAssignment)[];
|
||||
function chunkObjectLiteralElements(elements: ReadonlyArray<ObjectLiteralElementLike>): Expression[] {
|
||||
let chunkObject: ObjectLiteralElementLike[];
|
||||
const objects: Expression[] = [];
|
||||
for (const e of elements) {
|
||||
if (e.kind === SyntaxKind.SpreadAssignment) {
|
||||
@@ -177,7 +179,7 @@ namespace ts {
|
||||
chunkObject.push(createPropertyAssignment(p.name, visitNode(p.initializer, visitor, isExpression)));
|
||||
}
|
||||
else {
|
||||
chunkObject.push(e as ShorthandPropertyAssignment);
|
||||
chunkObject.push(visitNode(e, visitor, isObjectLiteralElementLike));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,6 +214,17 @@ namespace ts {
|
||||
return visitEachChild(node, noDestructuringValue ? visitorNoDestructuringValue : visitor, context);
|
||||
}
|
||||
|
||||
function visitCatchClause(node: CatchClause): CatchClause {
|
||||
if (!node.variableDeclaration) {
|
||||
return updateCatchClause(
|
||||
node,
|
||||
createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)),
|
||||
visitNode(node.block, visitor, isBlock)
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a BinaryExpression that contains a destructuring assignment.
|
||||
*
|
||||
@@ -776,7 +789,7 @@ namespace ts {
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
createLiteral(unescapeLeadingUnderscores(node.name.text)),
|
||||
createLiteral(unescapeLeadingUnderscores(node.name.escapedText)),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
@@ -164,12 +164,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
// A generated code block
|
||||
interface CodeBlock {
|
||||
kind: CodeBlockKind;
|
||||
}
|
||||
type CodeBlock = | ExceptionBlock | LabeledBlock | SwitchBlock | LoopBlock | WithBlock;
|
||||
|
||||
// a generated exception block, used for 'try' statements
|
||||
interface ExceptionBlock extends CodeBlock {
|
||||
interface ExceptionBlock {
|
||||
kind: CodeBlockKind.Exception;
|
||||
state: ExceptionBlockState;
|
||||
startLabel: Label;
|
||||
catchVariable?: Identifier;
|
||||
@@ -179,27 +178,31 @@ namespace ts {
|
||||
}
|
||||
|
||||
// A generated code that tracks the target for 'break' statements in a LabeledStatement.
|
||||
interface LabeledBlock extends CodeBlock {
|
||||
interface LabeledBlock {
|
||||
kind: CodeBlockKind.Labeled;
|
||||
labelText: string;
|
||||
isScript: boolean;
|
||||
breakLabel: Label;
|
||||
}
|
||||
|
||||
// a generated block that tracks the target for 'break' statements in a 'switch' statement
|
||||
interface SwitchBlock extends CodeBlock {
|
||||
interface SwitchBlock {
|
||||
kind: CodeBlockKind.Switch;
|
||||
isScript: boolean;
|
||||
breakLabel: Label;
|
||||
}
|
||||
|
||||
// a generated block that tracks the targets for 'break' and 'continue' statements, used for iteration statements
|
||||
interface LoopBlock extends CodeBlock {
|
||||
interface LoopBlock {
|
||||
kind: CodeBlockKind.Loop;
|
||||
continueLabel: Label;
|
||||
isScript: boolean;
|
||||
breakLabel: Label;
|
||||
}
|
||||
|
||||
// a generated block associated with a 'with' statement
|
||||
interface WithBlock extends CodeBlock {
|
||||
interface WithBlock {
|
||||
kind: CodeBlockKind.With;
|
||||
expression: Identifier;
|
||||
startLabel: Label;
|
||||
endLabel: Label;
|
||||
@@ -1176,7 +1179,7 @@ namespace ts {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function transformAndEmitStatements(statements: Statement[], start = 0) {
|
||||
function transformAndEmitStatements(statements: ReadonlyArray<Statement>, start = 0) {
|
||||
const numStatements = statements.length;
|
||||
for (let i = start; i < numStatements; i++) {
|
||||
transformAndEmitStatement(statements[i]);
|
||||
@@ -1635,14 +1638,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformAndEmitContinueStatement(node: ContinueStatement): void {
|
||||
const label = findContinueTarget(node.label ? unescapeLeadingUnderscores(node.label.text) : undefined);
|
||||
Debug.assert(label > 0, "Expected continue statment to point to a valid Label.");
|
||||
emitBreak(label, /*location*/ node);
|
||||
const label = findContinueTarget(node.label ? unescapeLeadingUnderscores(node.label.escapedText) : undefined);
|
||||
if (label > 0) {
|
||||
emitBreak(label, /*location*/ node);
|
||||
}
|
||||
else {
|
||||
// invalid continue without a containing loop. Leave the node as is, per #17875.
|
||||
emitStatement(node);
|
||||
}
|
||||
}
|
||||
|
||||
function visitContinueStatement(node: ContinueStatement): Statement {
|
||||
if (inStatementContainingYield) {
|
||||
const label = findContinueTarget(node.label && unescapeLeadingUnderscores(node.label.text));
|
||||
const label = findContinueTarget(node.label && unescapeLeadingUnderscores(node.label.escapedText));
|
||||
if (label > 0) {
|
||||
return createInlineBreak(label, /*location*/ node);
|
||||
}
|
||||
@@ -1652,14 +1660,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformAndEmitBreakStatement(node: BreakStatement): void {
|
||||
const label = findBreakTarget(node.label ? unescapeLeadingUnderscores(node.label.text) : undefined);
|
||||
Debug.assert(label > 0, "Expected break statment to point to a valid Label.");
|
||||
emitBreak(label, /*location*/ node);
|
||||
const label = findBreakTarget(node.label ? unescapeLeadingUnderscores(node.label.escapedText) : undefined);
|
||||
if (label > 0) {
|
||||
emitBreak(label, /*location*/ node);
|
||||
}
|
||||
else {
|
||||
// invalid break without a containing loop, switch, or labeled statement. Leave the node as is, per #17875.
|
||||
emitStatement(node);
|
||||
}
|
||||
}
|
||||
|
||||
function visitBreakStatement(node: BreakStatement): Statement {
|
||||
if (inStatementContainingYield) {
|
||||
const label = findBreakTarget(node.label && unescapeLeadingUnderscores(node.label.text));
|
||||
const label = findBreakTarget(node.label && unescapeLeadingUnderscores(node.label.escapedText));
|
||||
if (label > 0) {
|
||||
return createInlineBreak(label, /*location*/ node);
|
||||
}
|
||||
@@ -1838,7 +1851,7 @@ namespace ts {
|
||||
// /*body*/
|
||||
// .endlabeled
|
||||
// .mark endLabel
|
||||
beginLabeledBlock(unescapeLeadingUnderscores(node.label.text));
|
||||
beginLabeledBlock(unescapeLeadingUnderscores(node.label.escapedText));
|
||||
transformAndEmitEmbeddedStatement(node.statement);
|
||||
endLabeledBlock();
|
||||
}
|
||||
@@ -1849,7 +1862,7 @@ namespace ts {
|
||||
|
||||
function visitLabeledStatement(node: LabeledStatement) {
|
||||
if (inStatementContainingYield) {
|
||||
beginScriptLabeledBlock(unescapeLeadingUnderscores(node.label.text));
|
||||
beginScriptLabeledBlock(unescapeLeadingUnderscores(node.label.escapedText));
|
||||
}
|
||||
|
||||
node = visitEachChild(node, visitor, context);
|
||||
@@ -1950,7 +1963,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function substituteExpressionIdentifier(node: Identifier) {
|
||||
if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(unescapeLeadingUnderscores(node.text))) {
|
||||
if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(unescapeLeadingUnderscores(node.escapedText))) {
|
||||
const original = getOriginalNode(node);
|
||||
if (isIdentifier(original) && original.parent) {
|
||||
const declaration = resolver.getReferencedValueDeclaration(original);
|
||||
@@ -2070,7 +2083,7 @@ namespace ts {
|
||||
const startLabel = defineLabel();
|
||||
const endLabel = defineLabel();
|
||||
markLabel(startLabel);
|
||||
beginBlock(<WithBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.With,
|
||||
expression,
|
||||
startLabel,
|
||||
@@ -2087,10 +2100,6 @@ namespace ts {
|
||||
markLabel(block.endLabel);
|
||||
}
|
||||
|
||||
function isWithBlock(block: CodeBlock): block is WithBlock {
|
||||
return block.kind === CodeBlockKind.With;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a code block for a generated `try` statement.
|
||||
*/
|
||||
@@ -2098,7 +2107,7 @@ namespace ts {
|
||||
const startLabel = defineLabel();
|
||||
const endLabel = defineLabel();
|
||||
markLabel(startLabel);
|
||||
beginBlock(<ExceptionBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Exception,
|
||||
state: ExceptionBlockState.Try,
|
||||
startLabel,
|
||||
@@ -2123,7 +2132,7 @@ namespace ts {
|
||||
hoistVariableDeclaration(variable.name);
|
||||
}
|
||||
else {
|
||||
const text = unescapeLeadingUnderscores((<Identifier>variable.name).text);
|
||||
const text = unescapeLeadingUnderscores((<Identifier>variable.name).escapedText);
|
||||
name = declareLocal(text);
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = createMap<boolean>();
|
||||
@@ -2188,10 +2197,6 @@ namespace ts {
|
||||
exception.state = ExceptionBlockState.Done;
|
||||
}
|
||||
|
||||
function isExceptionBlock(block: CodeBlock): block is ExceptionBlock {
|
||||
return block.kind === CodeBlockKind.Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a code block that supports `break` or `continue` statements that are defined in
|
||||
* the source tree and not from generated code.
|
||||
@@ -2199,7 +2204,7 @@ namespace ts {
|
||||
* @param labelText Names from containing labeled statements.
|
||||
*/
|
||||
function beginScriptLoopBlock(): void {
|
||||
beginBlock(<LoopBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Loop,
|
||||
isScript: true,
|
||||
breakLabel: -1,
|
||||
@@ -2217,7 +2222,7 @@ namespace ts {
|
||||
*/
|
||||
function beginLoopBlock(continueLabel: Label): Label {
|
||||
const breakLabel = defineLabel();
|
||||
beginBlock(<LoopBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Loop,
|
||||
isScript: false,
|
||||
breakLabel,
|
||||
@@ -2245,7 +2250,7 @@ namespace ts {
|
||||
*
|
||||
*/
|
||||
function beginScriptSwitchBlock(): void {
|
||||
beginBlock(<SwitchBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Switch,
|
||||
isScript: true,
|
||||
breakLabel: -1
|
||||
@@ -2259,7 +2264,7 @@ namespace ts {
|
||||
*/
|
||||
function beginSwitchBlock(): Label {
|
||||
const breakLabel = defineLabel();
|
||||
beginBlock(<SwitchBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Switch,
|
||||
isScript: false,
|
||||
breakLabel,
|
||||
@@ -2280,7 +2285,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function beginScriptLabeledBlock(labelText: string) {
|
||||
beginBlock(<LabeledBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Labeled,
|
||||
isScript: true,
|
||||
labelText,
|
||||
@@ -2290,7 +2295,7 @@ namespace ts {
|
||||
|
||||
function beginLabeledBlock(labelText: string) {
|
||||
const breakLabel = defineLabel();
|
||||
beginBlock(<LabeledBlock>{
|
||||
beginBlock({
|
||||
kind: CodeBlockKind.Labeled,
|
||||
isScript: false,
|
||||
labelText,
|
||||
@@ -2356,27 +2361,27 @@ namespace ts {
|
||||
* @param labelText An optional name of a containing labeled statement.
|
||||
*/
|
||||
function findBreakTarget(labelText?: string): Label {
|
||||
Debug.assert(blocks !== undefined);
|
||||
if (labelText) {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsLabeledBreakOrContinue(block) && block.labelText === labelText) {
|
||||
return block.breakLabel;
|
||||
if (blockStack) {
|
||||
if (labelText) {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsLabeledBreakOrContinue(block) && block.labelText === labelText) {
|
||||
return block.breakLabel;
|
||||
}
|
||||
else if (supportsUnlabeledBreak(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
|
||||
return block.breakLabel;
|
||||
}
|
||||
}
|
||||
else if (supportsUnlabeledBreak(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
|
||||
return block.breakLabel;
|
||||
}
|
||||
else {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledBreak(block)) {
|
||||
return block.breakLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledBreak(block)) {
|
||||
return block.breakLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2386,24 +2391,24 @@ namespace ts {
|
||||
* @param labelText An optional name of a containing labeled statement.
|
||||
*/
|
||||
function findContinueTarget(labelText?: string): Label {
|
||||
Debug.assert(blocks !== undefined);
|
||||
if (labelText) {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledContinue(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
|
||||
return block.continueLabel;
|
||||
if (blockStack) {
|
||||
if (labelText) {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledContinue(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) {
|
||||
return block.continueLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledContinue(block)) {
|
||||
return block.continueLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let i = blockStack.length - 1; i >= 0; i--) {
|
||||
const block = blockStack[i];
|
||||
if (supportsUnlabeledContinue(block)) {
|
||||
return block.continueLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2448,7 +2453,7 @@ namespace ts {
|
||||
* @param location An optional source map location for the statement.
|
||||
*/
|
||||
function createInlineBreak(label: Label, location?: TextRange): ReturnStatement {
|
||||
Debug.assert(label > 0, `Invalid label: ${label}`);
|
||||
Debug.assertLessThan(0, label, "Invalid label");
|
||||
return setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
@@ -2878,34 +2883,37 @@ namespace ts {
|
||||
for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) {
|
||||
const block = blocks[blockIndex];
|
||||
const blockAction = blockActions[blockIndex];
|
||||
if (isExceptionBlock(block)) {
|
||||
if (blockAction === BlockAction.Open) {
|
||||
if (!exceptionBlockStack) {
|
||||
exceptionBlockStack = [];
|
||||
}
|
||||
switch (block.kind) {
|
||||
case CodeBlockKind.Exception:
|
||||
if (blockAction === BlockAction.Open) {
|
||||
if (!exceptionBlockStack) {
|
||||
exceptionBlockStack = [];
|
||||
}
|
||||
|
||||
if (!statements) {
|
||||
statements = [];
|
||||
}
|
||||
if (!statements) {
|
||||
statements = [];
|
||||
}
|
||||
|
||||
exceptionBlockStack.push(currentExceptionBlock);
|
||||
currentExceptionBlock = block;
|
||||
}
|
||||
else if (blockAction === BlockAction.Close) {
|
||||
currentExceptionBlock = exceptionBlockStack.pop();
|
||||
}
|
||||
}
|
||||
else if (isWithBlock(block)) {
|
||||
if (blockAction === BlockAction.Open) {
|
||||
if (!withBlockStack) {
|
||||
withBlockStack = [];
|
||||
exceptionBlockStack.push(currentExceptionBlock);
|
||||
currentExceptionBlock = block;
|
||||
}
|
||||
else if (blockAction === BlockAction.Close) {
|
||||
currentExceptionBlock = exceptionBlockStack.pop();
|
||||
}
|
||||
break;
|
||||
case CodeBlockKind.With:
|
||||
if (blockAction === BlockAction.Open) {
|
||||
if (!withBlockStack) {
|
||||
withBlockStack = [];
|
||||
}
|
||||
|
||||
withBlockStack.push(block);
|
||||
}
|
||||
else if (blockAction === BlockAction.Close) {
|
||||
withBlockStack.pop();
|
||||
}
|
||||
withBlockStack.push(block);
|
||||
}
|
||||
else if (blockAction === BlockAction.Close) {
|
||||
withBlockStack.pop();
|
||||
}
|
||||
break;
|
||||
// default: do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace ts {
|
||||
return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node);
|
||||
}
|
||||
|
||||
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) {
|
||||
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
|
||||
const tagName = getTagName(node);
|
||||
let objectProperties: Expression;
|
||||
const attrs = node.attributes.properties;
|
||||
@@ -88,7 +88,7 @@ namespace ts {
|
||||
else {
|
||||
// Map spans of JsxAttribute nodes into object literals and spans
|
||||
// of JsxSpreadAttribute nodes into expressions.
|
||||
const segments = flatten(
|
||||
const segments = flatten<Expression | ObjectLiteralExpression>(
|
||||
spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread
|
||||
? map(attrs, transformJsxSpreadAttributeToExpression)
|
||||
: createObjectLiteral(map(attrs, transformJsxAttributeToObjectLiteralElement))
|
||||
@@ -114,7 +114,7 @@ namespace ts {
|
||||
compilerOptions.reactNamespace,
|
||||
tagName,
|
||||
objectProperties,
|
||||
filter(map(children, transformJsxChildToExpression), isDefined),
|
||||
mapDefined(children, transformJsxChildToExpression),
|
||||
node,
|
||||
location
|
||||
);
|
||||
@@ -252,8 +252,8 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const name = (<JsxOpeningLikeElement>node).tagName;
|
||||
if (isIdentifier(name) && isIntrinsicJsxName(name.text)) {
|
||||
return createLiteral(unescapeLeadingUnderscores(name.text));
|
||||
if (isIdentifier(name) && isIntrinsicJsxName(name.escapedText)) {
|
||||
return createLiteral(unescapeLeadingUnderscores(name.escapedText));
|
||||
}
|
||||
else {
|
||||
return createExpressionFromEntityName(name);
|
||||
@@ -268,11 +268,11 @@ namespace ts {
|
||||
*/
|
||||
function getAttributeName(node: JsxAttribute): StringLiteral | Identifier {
|
||||
const name = node.name;
|
||||
if (/^[A-Za-z_]\w*$/.test(unescapeLeadingUnderscores(name.text))) {
|
||||
if (/^[A-Za-z_]\w*$/.test(unescapeLeadingUnderscores(name.escapedText))) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return createLiteral(unescapeLeadingUnderscores(name.text));
|
||||
return createLiteral(unescapeLeadingUnderscores(name.escapedText));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -430,26 +430,32 @@ namespace ts {
|
||||
*/
|
||||
function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
|
||||
if (currentModuleInfo.exportEquals) {
|
||||
if (emitAsReturn) {
|
||||
const statement = createReturn(currentModuleInfo.exportEquals.expression);
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
else {
|
||||
const statement = createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createIdentifier("module"),
|
||||
"exports"
|
||||
),
|
||||
currentModuleInfo.exportEquals.expression
|
||||
)
|
||||
);
|
||||
const expressionResult = importCallExpressionVisitor(currentModuleInfo.exportEquals.expression);
|
||||
if (expressionResult) {
|
||||
if (expressionResult instanceof Array) {
|
||||
return Debug.fail("export= expression should never be replaced with multiple expressions!");
|
||||
}
|
||||
if (emitAsReturn) {
|
||||
const statement = createReturn(expressionResult);
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
else {
|
||||
const statement = createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createIdentifier("module"),
|
||||
"exports"
|
||||
),
|
||||
expressionResult
|
||||
)
|
||||
);
|
||||
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,7 +503,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function importCallExpressionVisitor(node: Node): VisitResult<Node> {
|
||||
function importCallExpressionVisitor(node: Expression): VisitResult<Expression> {
|
||||
// This visitor does not need to descend into the tree if there is no dynamic import,
|
||||
// as export/import statements are only transformed at the top level of a file.
|
||||
if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) {
|
||||
@@ -924,7 +930,7 @@ namespace ts {
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, importCallExpressionVisitor),
|
||||
node.members
|
||||
visitNodes(node.members, importCallExpressionVisitor)
|
||||
),
|
||||
node
|
||||
),
|
||||
@@ -1204,7 +1210,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (hasModifier(decl, ModifierFlags.Export)) {
|
||||
const exportName = hasModifier(decl, ModifierFlags.Default) ? createIdentifier("default") : decl.name;
|
||||
const exportName = hasModifier(decl, ModifierFlags.Default) ? createIdentifier("default") : getDeclarationName(decl);
|
||||
statements = appendExportStatement(statements, exportName, getLocalName(decl), /*location*/ decl);
|
||||
}
|
||||
|
||||
@@ -1225,7 +1231,7 @@ namespace ts {
|
||||
*/
|
||||
function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration): Statement[] | undefined {
|
||||
const name = getDeclarationName(decl);
|
||||
const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.text));
|
||||
const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.escapedText));
|
||||
if (exportSpecifiers) {
|
||||
for (const exportSpecifier of exportSpecifiers) {
|
||||
statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name);
|
||||
|
||||
@@ -324,7 +324,7 @@ namespace ts {
|
||||
const exportedNames: ObjectLiteralElementLike[] = [];
|
||||
if (moduleInfo.exportedNames) {
|
||||
for (const exportedLocalName of moduleInfo.exportedNames) {
|
||||
if (exportedLocalName.text === "default") {
|
||||
if (exportedLocalName.escapedText === "default") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ namespace ts {
|
||||
// write name of indirectly exported entry, i.e. 'export {x} from ...'
|
||||
exportedNames.push(
|
||||
createPropertyAssignment(
|
||||
createLiteral(unescapeLeadingUnderscores((element.name || element.propertyName).text)),
|
||||
createLiteral(unescapeLeadingUnderscores((element.name || element.propertyName).escapedText)),
|
||||
createTrue()
|
||||
)
|
||||
);
|
||||
@@ -504,10 +504,10 @@ namespace ts {
|
||||
for (const e of (<ExportDeclaration>entry).exportClause.elements) {
|
||||
properties.push(
|
||||
createPropertyAssignment(
|
||||
createLiteral(unescapeLeadingUnderscores(e.name.text)),
|
||||
createLiteral(unescapeLeadingUnderscores(e.name.escapedText)),
|
||||
createElementAccess(
|
||||
parameterName,
|
||||
createLiteral(unescapeLeadingUnderscores((e.propertyName || e.name).text))
|
||||
createLiteral(unescapeLeadingUnderscores((e.propertyName || e.name).escapedText))
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -1028,7 +1028,7 @@ namespace ts {
|
||||
let excludeName: string;
|
||||
if (exportSelf) {
|
||||
statements = appendExportStatement(statements, decl.name, getLocalName(decl));
|
||||
excludeName = unescapeLeadingUnderscores(decl.name.text);
|
||||
excludeName = unescapeLeadingUnderscores(decl.name.escapedText);
|
||||
}
|
||||
|
||||
statements = appendExportsOfDeclaration(statements, decl, excludeName);
|
||||
@@ -1080,10 +1080,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
const name = getDeclarationName(decl);
|
||||
const exportSpecifiers = moduleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.text));
|
||||
const exportSpecifiers = moduleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.escapedText));
|
||||
if (exportSpecifiers) {
|
||||
for (const exportSpecifier of exportSpecifiers) {
|
||||
if (exportSpecifier.name.text !== excludeName) {
|
||||
if (exportSpecifier.name.escapedText !== excludeName) {
|
||||
statements = appendExportStatement(statements, exportSpecifier.name, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,17 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
|
||||
recordEmittedDeclarationInScope(node);
|
||||
// Record these declarations provided that they have a name.
|
||||
if ((node as ClassDeclaration | FunctionDeclaration).name) {
|
||||
recordEmittedDeclarationInScope(node as ClassDeclaration | FunctionDeclaration);
|
||||
}
|
||||
else {
|
||||
// These nodes should always have names unless they are default-exports;
|
||||
// however, class declaration parsing allows for undefined names, so syntactically invalid
|
||||
// programs may also have an undefined name.
|
||||
Debug.assert(node.kind === SyntaxKind.ClassDeclaration || hasModifier(node, ModifierFlags.Default));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -522,7 +532,7 @@ namespace ts {
|
||||
return parameter.decorators !== undefined && parameter.decorators.length > 0;
|
||||
}
|
||||
|
||||
function getClassFacts(node: ClassDeclaration, staticProperties: PropertyDeclaration[]) {
|
||||
function getClassFacts(node: ClassDeclaration, staticProperties: ReadonlyArray<PropertyDeclaration>) {
|
||||
let facts = ClassFacts.None;
|
||||
if (some(staticProperties)) facts |= ClassFacts.HasStaticInitializedProperties;
|
||||
if (getClassExtendsHeritageClauseElement(node)) facts |= ClassFacts.HasExtendsClause;
|
||||
@@ -603,13 +613,16 @@ namespace ts {
|
||||
|
||||
addRange(statements, context.endLexicalEnvironment());
|
||||
|
||||
const iife = createImmediatelyInvokedArrowFunction(statements);
|
||||
setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper);
|
||||
|
||||
const varStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false),
|
||||
/*type*/ undefined,
|
||||
createImmediatelyInvokedFunctionExpression(statements)
|
||||
iife
|
||||
)
|
||||
])
|
||||
);
|
||||
@@ -1051,7 +1064,7 @@ namespace ts {
|
||||
*
|
||||
* @param node The constructor node.
|
||||
*/
|
||||
function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ParameterDeclaration[] {
|
||||
function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray<ParameterDeclaration> {
|
||||
return filter(node.parameters, isParameterWithPropertyAssignment);
|
||||
}
|
||||
|
||||
@@ -1104,7 +1117,7 @@ namespace ts {
|
||||
* @param node The class node.
|
||||
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
|
||||
*/
|
||||
function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): PropertyDeclaration[] {
|
||||
function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<PropertyDeclaration> {
|
||||
return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty);
|
||||
}
|
||||
|
||||
@@ -1144,7 +1157,7 @@ namespace ts {
|
||||
* @param properties An array of property declarations to transform.
|
||||
* @param receiver The receiver on which each property should be assigned.
|
||||
*/
|
||||
function addInitializedPropertyStatements(statements: Statement[], properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
|
||||
function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
|
||||
for (const property of properties) {
|
||||
const statement = createStatement(transformInitializedProperty(property, receiver));
|
||||
setSourceMapRange(statement, moveRangePastModifiers(property));
|
||||
@@ -1159,7 +1172,7 @@ namespace ts {
|
||||
* @param properties An array of property declarations to transform.
|
||||
* @param receiver The receiver on which each property should be assigned.
|
||||
*/
|
||||
function generateInitializedPropertyExpressions(properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
|
||||
function generateInitializedPropertyExpressions(properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
|
||||
const expressions: Expression[] = [];
|
||||
for (const property of properties) {
|
||||
const expression = transformInitializedProperty(property, receiver);
|
||||
@@ -1194,7 +1207,7 @@ namespace ts {
|
||||
* @param isStatic A value indicating whether to retrieve static or instance members of
|
||||
* the class.
|
||||
*/
|
||||
function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): ClassElement[] {
|
||||
function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<ClassElement> {
|
||||
return filter(node.members, isStatic ? isStaticDecoratedClassElement : isInstanceDecoratedClassElement);
|
||||
}
|
||||
|
||||
@@ -1233,8 +1246,8 @@ namespace ts {
|
||||
* A structure describing the decorators for a class element.
|
||||
*/
|
||||
interface AllDecorators {
|
||||
decorators: Decorator[];
|
||||
parameters?: Decorator[][];
|
||||
decorators: ReadonlyArray<Decorator>;
|
||||
parameters?: ReadonlyArray<ReadonlyArray<Decorator>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1244,7 +1257,7 @@ namespace ts {
|
||||
* @param node The function-like node.
|
||||
*/
|
||||
function getDecoratorsOfParameters(node: FunctionLikeDeclaration) {
|
||||
let decorators: Decorator[][];
|
||||
let decorators: ReadonlyArray<Decorator>[];
|
||||
if (node) {
|
||||
const parameters = node.parameters;
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
@@ -1692,7 +1705,7 @@ namespace ts {
|
||||
const numParameters = parameters.length;
|
||||
for (let i = 0; i < numParameters; i++) {
|
||||
const parameter = parameters[i];
|
||||
if (i === 0 && isIdentifier(parameter.name) && parameter.name.text === "this") {
|
||||
if (i === 0 && isIdentifier(parameter.name) && parameter.name.escapedText === "this") {
|
||||
continue;
|
||||
}
|
||||
if (parameter.dotDotDotToken) {
|
||||
@@ -1841,7 +1854,7 @@ namespace ts {
|
||||
for (const typeNode of node.types) {
|
||||
const serializedIndividual = serializeTypeNode(typeNode);
|
||||
|
||||
if (isIdentifier(serializedIndividual) && serializedIndividual.text === "Object") {
|
||||
if (isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") {
|
||||
// One of the individual is global object, return immediately
|
||||
return serializedIndividual;
|
||||
}
|
||||
@@ -1851,7 +1864,7 @@ namespace ts {
|
||||
// Different types
|
||||
if (!isIdentifier(serializedUnion) ||
|
||||
!isIdentifier(serializedIndividual) ||
|
||||
serializedUnion.text !== serializedIndividual.text) {
|
||||
serializedUnion.escapedText !== serializedIndividual.escapedText) {
|
||||
return createIdentifier("Object");
|
||||
}
|
||||
}
|
||||
@@ -2007,7 +2020,7 @@ namespace ts {
|
||||
: (<ComputedPropertyName>name).expression;
|
||||
}
|
||||
else if (isIdentifier(name)) {
|
||||
return createLiteral(unescapeLeadingUnderscores(name.text));
|
||||
return createLiteral(unescapeLeadingUnderscores(name.escapedText));
|
||||
}
|
||||
else {
|
||||
return getSynthesizedClone(name);
|
||||
@@ -2639,36 +2652,33 @@ namespace ts {
|
||||
/**
|
||||
* Records that a declaration was emitted in the current scope, if it was the first
|
||||
* declaration for the provided symbol.
|
||||
*
|
||||
* NOTE: if there is ever a transformation above this one, we may not be able to rely
|
||||
* on symbol names.
|
||||
*/
|
||||
function recordEmittedDeclarationInScope(node: Node) {
|
||||
const name = node.symbol && node.symbol.name;
|
||||
if (name) {
|
||||
if (!currentScopeFirstDeclarationsOfName) {
|
||||
currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap<Node>();
|
||||
}
|
||||
function recordEmittedDeclarationInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration) {
|
||||
if (!currentScopeFirstDeclarationsOfName) {
|
||||
currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap<Node>();
|
||||
}
|
||||
|
||||
if (!currentScopeFirstDeclarationsOfName.has(name)) {
|
||||
currentScopeFirstDeclarationsOfName.set(name, node);
|
||||
}
|
||||
const name = declaredNameInScope(node);
|
||||
if (!currentScopeFirstDeclarationsOfName.has(name)) {
|
||||
currentScopeFirstDeclarationsOfName.set(name, node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a declaration is the first declaration with the same name emitted
|
||||
* in the current scope.
|
||||
* Determines whether a declaration is the first declaration with
|
||||
* the same name emitted in the current scope.
|
||||
*/
|
||||
function isFirstEmittedDeclarationInScope(node: Node) {
|
||||
function isFirstEmittedDeclarationInScope(node: ModuleDeclaration | EnumDeclaration) {
|
||||
if (currentScopeFirstDeclarationsOfName) {
|
||||
const name = node.symbol && node.symbol.name;
|
||||
if (name) {
|
||||
return currentScopeFirstDeclarationsOfName.get(name) === node;
|
||||
}
|
||||
const name = declaredNameInScope(node);
|
||||
return currentScopeFirstDeclarationsOfName.get(name) === node;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
function declaredNameInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration): __String {
|
||||
Debug.assertNode(node.name, isIdentifier);
|
||||
return (node.name as Identifier).escapedText;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2746,7 +2756,7 @@ namespace ts {
|
||||
return createNotEmittedStatement(node);
|
||||
}
|
||||
|
||||
Debug.assert(isIdentifier(node.name), "TypeScript module should have an Identifier name.");
|
||||
Debug.assertNode(node.name, isIdentifier, "A TypeScript namespace should have an Identifier name.");
|
||||
enableSubstitutionForNamespaceExports();
|
||||
|
||||
const statements: Statement[] = [];
|
||||
@@ -3210,7 +3220,7 @@ namespace ts {
|
||||
function getClassAliasIfNeeded(node: ClassDeclaration) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
|
||||
enableSubstitutionForClassAliases();
|
||||
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeLeadingUnderscores(node.name.text) : "default");
|
||||
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeLeadingUnderscores(node.name.escapedText) : "default");
|
||||
classAliases[getOriginalNodeId(node)] = classAlias;
|
||||
hoistVariableDeclaration(classAlias);
|
||||
return classAlias;
|
||||
|
||||
@@ -58,9 +58,9 @@ namespace ts {
|
||||
else {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(specifier.name.text))) {
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(specifier.name.escapedText))) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
exportSpecifiers.add(unescapeLeadingUnderscores(name.text), specifier);
|
||||
exportSpecifiers.add(unescapeLeadingUnderscores(name.escapedText), specifier);
|
||||
|
||||
const decl = resolver.getReferencedImportDeclaration(name)
|
||||
|| resolver.getReferencedValueDeclaration(name);
|
||||
@@ -69,7 +69,7 @@ namespace ts {
|
||||
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
|
||||
}
|
||||
|
||||
uniqueExports.set(unescapeLeadingUnderscores(specifier.name.text), true);
|
||||
uniqueExports.set(unescapeLeadingUnderscores(specifier.name.escapedText), true);
|
||||
exportedNames = append(exportedNames, specifier.name);
|
||||
}
|
||||
}
|
||||
@@ -103,9 +103,9 @@ namespace ts {
|
||||
else {
|
||||
// export function x() { }
|
||||
const name = (<FunctionDeclaration>node).name;
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) {
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(name.escapedText))) {
|
||||
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports.set(unescapeLeadingUnderscores(name.text), true);
|
||||
uniqueExports.set(unescapeLeadingUnderscores(name.escapedText), true);
|
||||
exportedNames = append(exportedNames, name);
|
||||
}
|
||||
}
|
||||
@@ -124,9 +124,9 @@ namespace ts {
|
||||
else {
|
||||
// export class x { }
|
||||
const name = (<ClassDeclaration>node).name;
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) {
|
||||
if (name && !uniqueExports.get(unescapeLeadingUnderscores(name.escapedText))) {
|
||||
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports.set(unescapeLeadingUnderscores(name.text), true);
|
||||
uniqueExports.set(unescapeLeadingUnderscores(name.escapedText), true);
|
||||
exportedNames = append(exportedNames, name);
|
||||
}
|
||||
}
|
||||
@@ -158,8 +158,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (!isGeneratedIdentifier(decl.name)) {
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(decl.name.text))) {
|
||||
uniqueExports.set(unescapeLeadingUnderscores(decl.name.text), true);
|
||||
if (!uniqueExports.get(unescapeLeadingUnderscores(decl.name.escapedText))) {
|
||||
uniqueExports.set(unescapeLeadingUnderscores(decl.name.escapedText), true);
|
||||
exportedNames = append(exportedNames, decl.name);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -61,7 +61,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: FormatDiagnosticsHost): void {
|
||||
sys.write(ts.formatDiagnosticsWithColorAndContext([diagnostic], host) + sys.newLine + sys.newLine);
|
||||
sys.write(ts.formatDiagnosticsWithColorAndContext([diagnostic], host) + sys.newLine);
|
||||
}
|
||||
|
||||
function reportWatchDiagnostic(diagnostic: Diagnostic) {
|
||||
@@ -469,7 +469,7 @@ namespace ts {
|
||||
let diagnostics: Diagnostic[];
|
||||
|
||||
// First get and report any syntactic errors.
|
||||
diagnostics = program.getSyntacticDiagnostics();
|
||||
diagnostics = program.getSyntacticDiagnostics().slice();
|
||||
|
||||
// If we didn't have any syntactic errors, then also try getting the global and
|
||||
// semantic errors.
|
||||
@@ -477,13 +477,13 @@ namespace ts {
|
||||
diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
|
||||
|
||||
if (diagnostics.length === 0) {
|
||||
diagnostics = program.getSemanticDiagnostics();
|
||||
diagnostics = program.getSemanticDiagnostics().slice();
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, emit and report any errors we ran into.
|
||||
const emitOutput = program.emit();
|
||||
diagnostics = diagnostics.concat(emitOutput.diagnostics);
|
||||
addRange(diagnostics, emitOutput.diagnostics);
|
||||
|
||||
reportDiagnostics(sortAndDeduplicateDiagnostics(diagnostics), compilerHost);
|
||||
|
||||
@@ -665,6 +665,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
ts.setStackTraceLimit();
|
||||
|
||||
if (ts.Debug.isDebugging) {
|
||||
ts.Debug.enableDebugInfo();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"symbolWalker.ts",
|
||||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
|
||||
+231
-207
@@ -8,13 +8,10 @@ namespace ts {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
/** ES6 Map interface. */
|
||||
export interface Map<T> {
|
||||
/** ES6 Map interface, only read methods included. */
|
||||
export interface ReadonlyMap<T> {
|
||||
get(key: string): T | undefined;
|
||||
has(key: string): boolean;
|
||||
set(key: string, value: T): this;
|
||||
delete(key: string): boolean;
|
||||
clear(): void;
|
||||
forEach(action: (value: T, key: string) => void): void;
|
||||
readonly size: number;
|
||||
keys(): Iterator<string>;
|
||||
@@ -22,26 +19,27 @@ namespace ts {
|
||||
entries(): Iterator<[string, T]>;
|
||||
}
|
||||
|
||||
/** ES6 Map interface. */
|
||||
export interface Map<T> extends ReadonlyMap<T> {
|
||||
set(key: string, value: T): this;
|
||||
delete(key: string): boolean;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/** ES6 Iterator type. */
|
||||
export interface Iterator<T> {
|
||||
next(): { value: T, done: false } | { value: never, done: true };
|
||||
}
|
||||
|
||||
/** Array that is only intended to be pushed to, never read. */
|
||||
export interface Push<T> {
|
||||
push(...values: T[]): void;
|
||||
}
|
||||
|
||||
// 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 };
|
||||
|
||||
export interface FileMap<T> {
|
||||
get(fileName: Path): T;
|
||||
set(fileName: Path, value: T): void;
|
||||
contains(fileName: Path): boolean;
|
||||
remove(fileName: Path): void;
|
||||
|
||||
forEachValue(f: (key: Path, v: T) => void): void;
|
||||
getKeys(): Path[];
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface TextRange {
|
||||
pos: number;
|
||||
end: number;
|
||||
@@ -358,19 +356,11 @@ namespace ts {
|
||||
JSDocAllType,
|
||||
// The ? type
|
||||
JSDocUnknownType,
|
||||
JSDocArrayType,
|
||||
JSDocUnionType,
|
||||
JSDocTupleType,
|
||||
JSDocNullableType,
|
||||
JSDocNonNullableType,
|
||||
JSDocRecordType,
|
||||
JSDocRecordMember,
|
||||
JSDocTypeReference,
|
||||
JSDocOptionalType,
|
||||
JSDocFunctionType,
|
||||
JSDocVariadicType,
|
||||
JSDocConstructorType,
|
||||
JSDocThisType,
|
||||
JSDocComment,
|
||||
JSDocTag,
|
||||
JSDocAugmentsTag,
|
||||
@@ -382,7 +372,6 @@ namespace ts {
|
||||
JSDocTypedefTag,
|
||||
JSDocPropertyTag,
|
||||
JSDocTypeLiteral,
|
||||
JSDocLiteralType,
|
||||
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
@@ -424,9 +413,9 @@ namespace ts {
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
LastJSDocNode = JSDocTypeLiteral,
|
||||
FirstJSDocTagNode = JSDocTag,
|
||||
LastJSDocTagNode = JSDocLiteralType
|
||||
LastJSDocTagNode = JSDocTypeLiteral
|
||||
}
|
||||
|
||||
export const enum NodeFlags {
|
||||
@@ -461,6 +450,7 @@ namespace ts {
|
||||
// we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used.
|
||||
/* @internal */
|
||||
PossiblyContainsDynamicImport = 1 << 19,
|
||||
JSDoc = 1 << 20, // If node was parsed inside jsdoc
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@@ -520,25 +510,28 @@ namespace ts {
|
||||
flags: NodeFlags;
|
||||
/* @internal */ modifierFlagsCache?: ModifierFlags;
|
||||
/* @internal */ transformFlags?: TransformFlags;
|
||||
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
/* @internal */ original?: Node; // The original node if this is an updated node.
|
||||
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
|
||||
/* @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node
|
||||
/* @internal */ jsDocCache?: (JSDoc | JSDocTag)[]; // All JSDoc that applies to the node, including parent docs and @param tags
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
|
||||
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
|
||||
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
|
||||
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
|
||||
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
|
||||
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding)
|
||||
/* @internal */ original?: Node; // The original node if this is an updated node.
|
||||
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
|
||||
/* @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node
|
||||
/* @internal */ jsDocCache?: ReadonlyArray<JSDocTag>; // Cache for getJSDocTags
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
|
||||
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
|
||||
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
|
||||
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
|
||||
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
|
||||
}
|
||||
|
||||
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
|
||||
/* @internal */
|
||||
export type MutableNodeArray<T extends Node> = NodeArray<T> & T[];
|
||||
|
||||
export interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
|
||||
hasTrailingComma?: boolean;
|
||||
/* @internal */ transformFlags?: TransformFlags;
|
||||
}
|
||||
@@ -586,15 +579,16 @@ namespace ts {
|
||||
export interface Identifier extends PrimaryExpression {
|
||||
kind: SyntaxKind.Identifier;
|
||||
/**
|
||||
* Text of identifier (with escapes converted to characters).
|
||||
* If the identifier begins with two underscores, this will begin with three.
|
||||
* Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.)
|
||||
* Text of identifier, but if the identifier begins with two underscores, this will begin with three.
|
||||
*/
|
||||
text: __String;
|
||||
escapedText: __String;
|
||||
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
|
||||
/*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
|
||||
/*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name.
|
||||
isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace
|
||||
/*@internal*/ typeArguments?: NodeArray<TypeNode>; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics.
|
||||
/*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id.<T>
|
||||
}
|
||||
|
||||
// Transient identifier node (marked by id === -1)
|
||||
@@ -614,6 +608,7 @@ namespace ts {
|
||||
kind: SyntaxKind.QualifiedName;
|
||||
left: EntityName;
|
||||
right: Identifier;
|
||||
/*@internal*/ jsdocDotPos?: number; // QualifiedName occurs in JSDoc-style generic: Id1.Id2.<T>
|
||||
}
|
||||
|
||||
export type EntityName = Identifier | QualifiedName;
|
||||
@@ -690,7 +685,7 @@ namespace ts {
|
||||
kind: SyntaxKind.Parameter;
|
||||
parent?: SignatureDeclaration;
|
||||
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
|
||||
name: BindingName; // Declared parameter name
|
||||
name: BindingName; // Declared parameter name.
|
||||
questionToken?: QuestionToken; // Present on optional parameter
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
@@ -705,7 +700,7 @@ namespace ts {
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
export interface TSPropertySignature extends TypeElement {
|
||||
export interface PropertySignature extends TypeElement {
|
||||
kind: SyntaxKind.PropertySignature;
|
||||
name: PropertyName; // Declared property name
|
||||
questionToken?: QuestionToken; // Present on optional property
|
||||
@@ -713,16 +708,6 @@ namespace ts {
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
export interface JSDocPropertySignature extends TypeElement {
|
||||
kind: SyntaxKind.JSDocRecordMember;
|
||||
name: PropertyName; // Declared property name
|
||||
questionToken?: QuestionToken; // Present on optional property
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
export type PropertySignature = TSPropertySignature | JSDocPropertySignature;
|
||||
|
||||
export interface PropertyDeclaration extends ClassElement {
|
||||
kind: SyntaxKind.PropertyDeclaration;
|
||||
questionToken?: QuestionToken; // Present for use with reporting a grammar error
|
||||
@@ -775,10 +760,11 @@ namespace ts {
|
||||
// SyntaxKind.ShorthandPropertyAssignment
|
||||
// SyntaxKind.EnumMember
|
||||
// SyntaxKind.JSDocPropertyTag
|
||||
// SyntaxKind.JSDocParameterTag
|
||||
export interface VariableLikeDeclaration extends NamedDeclaration {
|
||||
propertyName?: PropertyName;
|
||||
dotDotDotToken?: DotDotDotToken;
|
||||
name: DeclarationName;
|
||||
name?: DeclarationName; // May be missing for ParameterDeclaration, see comment there
|
||||
questionToken?: QuestionToken;
|
||||
type?: TypeNode;
|
||||
initializer?: Expression;
|
||||
@@ -933,7 +919,7 @@ namespace ts {
|
||||
kind: SyntaxKind.ConstructorType;
|
||||
}
|
||||
|
||||
export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference;
|
||||
export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
|
||||
|
||||
export interface TypeReferenceNode extends TypeNode {
|
||||
kind: SyntaxKind.TypeReference;
|
||||
@@ -1014,6 +1000,7 @@ namespace ts {
|
||||
export interface StringLiteral extends LiteralExpression {
|
||||
kind: SyntaxKind.StringLiteral;
|
||||
/* @internal */ textSourceNode?: Identifier | StringLiteral | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms).
|
||||
/* @internal */ singleQuote?: boolean;
|
||||
}
|
||||
|
||||
// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
|
||||
@@ -1823,7 +1810,7 @@ namespace ts {
|
||||
export interface CatchClause extends Node {
|
||||
kind: SyntaxKind.CatchClause;
|
||||
parent?: TryStatement;
|
||||
variableDeclaration: VariableDeclaration;
|
||||
variableDeclaration?: VariableDeclaration;
|
||||
block: Block;
|
||||
}
|
||||
|
||||
@@ -2052,9 +2039,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// represents a top level: { type } expression in a JSDoc comment.
|
||||
export interface JSDocTypeExpression extends Node {
|
||||
export interface JSDocTypeExpression extends TypeNode {
|
||||
kind: SyntaxKind.JSDocTypeExpression;
|
||||
type: JSDocType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocType extends TypeNode {
|
||||
@@ -2069,80 +2056,31 @@ namespace ts {
|
||||
kind: SyntaxKind.JSDocUnknownType;
|
||||
}
|
||||
|
||||
export interface JSDocArrayType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocArrayType;
|
||||
elementType: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocUnionType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocUnionType;
|
||||
types: NodeArray<JSDocType>;
|
||||
}
|
||||
|
||||
export interface JSDocTupleType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocTupleType;
|
||||
types: NodeArray<JSDocType>;
|
||||
}
|
||||
|
||||
export interface JSDocNonNullableType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocNonNullableType;
|
||||
type: JSDocType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocNullableType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocNullableType;
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocRecordType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocRecordType;
|
||||
literal: TypeLiteralNode;
|
||||
}
|
||||
|
||||
export interface JSDocTypeReference extends JSDocType {
|
||||
kind: SyntaxKind.JSDocTypeReference;
|
||||
name: EntityName;
|
||||
typeArguments: NodeArray<JSDocType>;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocOptionalType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocOptionalType;
|
||||
type: JSDocType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocFunctionType extends JSDocType, SignatureDeclaration {
|
||||
kind: SyntaxKind.JSDocFunctionType;
|
||||
parameters: NodeArray<ParameterDeclaration>;
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocVariadicType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocVariadicType;
|
||||
type: JSDocType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocConstructorType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocConstructorType;
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocThisType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocThisType;
|
||||
type: JSDocType;
|
||||
}
|
||||
|
||||
export interface JSDocLiteralType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocLiteralType;
|
||||
literal: LiteralTypeNode;
|
||||
}
|
||||
|
||||
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
|
||||
|
||||
export interface JSDocRecordMember extends JSDocPropertySignature {
|
||||
kind: SyntaxKind.JSDocRecordMember;
|
||||
name: Identifier | StringLiteral | NumericLiteral;
|
||||
type?: JSDocType;
|
||||
}
|
||||
export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
|
||||
|
||||
export interface JSDoc extends Node {
|
||||
kind: SyntaxKind.JSDocComment;
|
||||
@@ -2190,38 +2128,32 @@ namespace ts {
|
||||
kind: SyntaxKind.JSDocTypedefTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
jsDocTypeLiteral?: JSDocTypeLiteral;
|
||||
typeExpression?: JSDocTypeExpression | JSDocTypeLiteral;
|
||||
}
|
||||
|
||||
export interface JSDocPropertyTag extends JSDocTag, TypeElement {
|
||||
export interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocPropertyTag;
|
||||
name: Identifier;
|
||||
/** the parameter name, if provided *before* the type (TypeScript-style) */
|
||||
preParameterName?: Identifier;
|
||||
/** the parameter name, if provided *after* the type (JSDoc-standard) */
|
||||
postParameterName?: Identifier;
|
||||
name: EntityName;
|
||||
typeExpression: JSDocTypeExpression;
|
||||
/** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */
|
||||
isNameFirst: boolean;
|
||||
isBracketed: boolean;
|
||||
}
|
||||
|
||||
export interface JSDocPropertyTag extends JSDocPropertyLikeTag {
|
||||
kind: SyntaxKind.JSDocPropertyTag;
|
||||
}
|
||||
|
||||
export interface JSDocParameterTag extends JSDocPropertyLikeTag {
|
||||
kind: SyntaxKind.JSDocParameterTag;
|
||||
}
|
||||
|
||||
export interface JSDocTypeLiteral extends JSDocType {
|
||||
kind: SyntaxKind.JSDocTypeLiteral;
|
||||
jsDocPropertyTags?: NodeArray<JSDocPropertyTag>;
|
||||
jsDocPropertyTags?: ReadonlyArray<JSDocPropertyLikeTag>;
|
||||
jsDocTypeTag?: JSDocTypeTag;
|
||||
}
|
||||
|
||||
export interface JSDocParameterTag extends JSDocTag {
|
||||
kind: SyntaxKind.JSDocParameterTag;
|
||||
/** the parameter name, if provided *before* the type (TypeScript-style) */
|
||||
preParameterName?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
/** the parameter name, if provided *after* the type (JSDoc-standard) */
|
||||
postParameterName?: Identifier;
|
||||
/** the parameter name, regardless of the location it was provided */
|
||||
name: Identifier;
|
||||
isBracketed: boolean;
|
||||
/** If true, then this type literal represents an *array* of its type. */
|
||||
isArrayType?: boolean;
|
||||
}
|
||||
|
||||
export const enum FlowFlags {
|
||||
@@ -2246,16 +2178,18 @@ namespace ts {
|
||||
locked?: boolean;
|
||||
}
|
||||
|
||||
export interface AfterFinallyFlow extends FlowNode, FlowLock {
|
||||
export interface AfterFinallyFlow extends FlowNodeBase, FlowLock {
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
export interface PreFinallyFlow extends FlowNode {
|
||||
export interface PreFinallyFlow extends FlowNodeBase {
|
||||
antecedent: FlowNode;
|
||||
lock: FlowLock;
|
||||
}
|
||||
|
||||
export interface FlowNode {
|
||||
export type FlowNode =
|
||||
| AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation;
|
||||
export interface FlowNodeBase {
|
||||
flags: FlowFlags;
|
||||
id?: number; // Node id used by flow type cache in checker
|
||||
}
|
||||
@@ -2263,30 +2197,30 @@ namespace ts {
|
||||
// FlowStart represents the start of a control flow. For a function expression or arrow
|
||||
// function, the container property references the function (which in turn has a flowNode
|
||||
// property for the containing control flow).
|
||||
export interface FlowStart extends FlowNode {
|
||||
export interface FlowStart extends FlowNodeBase {
|
||||
container?: FunctionExpression | ArrowFunction | MethodDeclaration;
|
||||
}
|
||||
|
||||
// FlowLabel represents a junction with multiple possible preceding control flows.
|
||||
export interface FlowLabel extends FlowNode {
|
||||
export interface FlowLabel extends FlowNodeBase {
|
||||
antecedents: FlowNode[];
|
||||
}
|
||||
|
||||
// FlowAssignment represents a node that assigns a value to a narrowable reference,
|
||||
// i.e. an identifier or a dotted name that starts with an identifier or 'this'.
|
||||
export interface FlowAssignment extends FlowNode {
|
||||
export interface FlowAssignment extends FlowNodeBase {
|
||||
node: Expression | VariableDeclaration | BindingElement;
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
// FlowCondition represents a condition that is known to be true or false at the
|
||||
// node's location in the control flow.
|
||||
export interface FlowCondition extends FlowNode {
|
||||
export interface FlowCondition extends FlowNodeBase {
|
||||
expression: Expression;
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
|
||||
export interface FlowSwitchClause extends FlowNode {
|
||||
export interface FlowSwitchClause extends FlowNodeBase {
|
||||
switchStatement: SwitchStatement;
|
||||
clauseStart: number; // Start index of case/default clause range
|
||||
clauseEnd: number; // End index of case/default clause range
|
||||
@@ -2295,7 +2229,7 @@ namespace ts {
|
||||
|
||||
// FlowArrayMutation represents a node potentially mutates an array, i.e. an
|
||||
// operation of the form 'x.push(value)', 'x.unshift(value)' or 'x[n] = value'.
|
||||
export interface FlowArrayMutation extends FlowNode {
|
||||
export interface FlowArrayMutation extends FlowNodeBase {
|
||||
node: CallExpression | BinaryExpression;
|
||||
antecedent: FlowNode;
|
||||
}
|
||||
@@ -2321,10 +2255,21 @@ namespace ts {
|
||||
*/
|
||||
export interface SourceFileLike {
|
||||
readonly text: string;
|
||||
lineMap: number[];
|
||||
lineMap: ReadonlyArray<number>;
|
||||
}
|
||||
|
||||
|
||||
/* @internal */
|
||||
export interface RedirectInfo {
|
||||
/** Source file this redirects to. */
|
||||
readonly redirectTarget: SourceFile;
|
||||
/**
|
||||
* Source file for the duplicate package. This will not be used by the Program,
|
||||
* but we need to keep this around so we can watch for changes in underlying.
|
||||
*/
|
||||
readonly unredirected: SourceFile;
|
||||
}
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration {
|
||||
kind: SyntaxKind.SourceFile;
|
||||
@@ -2335,16 +2280,23 @@ namespace ts {
|
||||
/* @internal */ path: Path;
|
||||
text: string;
|
||||
|
||||
amdDependencies: AmdDependency[];
|
||||
/**
|
||||
* If two source files are for the same version of the same package, one will redirect to the other.
|
||||
* (See `createRedirectSourceFile` in program.ts.)
|
||||
* The redirect will have this set. The other will not have anything set, but see Program#sourceFileIsRedirectedTo.
|
||||
*/
|
||||
/* @internal */ redirectInfo?: RedirectInfo | undefined;
|
||||
|
||||
amdDependencies: ReadonlyArray<AmdDependency>;
|
||||
moduleName: string;
|
||||
referencedFiles: FileReference[];
|
||||
typeReferenceDirectives: FileReference[];
|
||||
referencedFiles: ReadonlyArray<FileReference>;
|
||||
typeReferenceDirectives: ReadonlyArray<FileReference>;
|
||||
languageVariant: LanguageVariant;
|
||||
isDeclarationFile: boolean;
|
||||
|
||||
// this map is used by transpiler to supply alternative names for dependencies (i.e. in case of bundling)
|
||||
/* @internal */
|
||||
renamedDependencies?: Map<string>;
|
||||
renamedDependencies?: ReadonlyMap<string>;
|
||||
|
||||
/**
|
||||
* lib.d.ts should have a reference comment like
|
||||
@@ -2380,27 +2332,27 @@ namespace ts {
|
||||
/* @internal */ jsDocDiagnostics?: Diagnostic[];
|
||||
|
||||
// Stores additional file-level diagnostics reported by the program
|
||||
/* @internal */ additionalSyntacticDiagnostics?: Diagnostic[];
|
||||
/* @internal */ additionalSyntacticDiagnostics?: ReadonlyArray<Diagnostic>;
|
||||
|
||||
// Stores a line map for the file.
|
||||
// This field should never be used directly to obtain line map, use getLineMap function instead.
|
||||
/* @internal */ lineMap: number[];
|
||||
/* @internal */ classifiableNames?: UnderscoreEscapedMap<true>;
|
||||
/* @internal */ lineMap: ReadonlyArray<number>;
|
||||
/* @internal */ classifiableNames?: ReadonlyUnderscoreEscapedMap<true>;
|
||||
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
|
||||
// It is used to resolve module names in the checker.
|
||||
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
|
||||
/* @internal */ resolvedModules: Map<ResolvedModuleFull>;
|
||||
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
|
||||
/* @internal */ imports: StringLiteral[];
|
||||
/* @internal */ moduleAugmentations: StringLiteral[];
|
||||
/* @internal */ imports: ReadonlyArray<StringLiteral>;
|
||||
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral>;
|
||||
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
|
||||
/* @internal */ ambientModuleNames: string[];
|
||||
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
|
||||
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
|
||||
}
|
||||
|
||||
export interface Bundle extends Node {
|
||||
kind: SyntaxKind.Bundle;
|
||||
sourceFiles: SourceFile[];
|
||||
sourceFiles: ReadonlyArray<SourceFile>;
|
||||
}
|
||||
|
||||
export interface JsonSourceFile extends SourceFile {
|
||||
@@ -2418,7 +2370,7 @@ namespace ts {
|
||||
export interface ParseConfigHost {
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
|
||||
readDirectory(rootDir: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[];
|
||||
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string>, includes: ReadonlyArray<string>, depth: number): string[];
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the specified path exists and is a file.
|
||||
@@ -2426,11 +2378,11 @@ namespace ts {
|
||||
*/
|
||||
fileExists(path: string): boolean;
|
||||
|
||||
readFile(path: string): string;
|
||||
readFile(path: string): string | undefined;
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void;
|
||||
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>): void;
|
||||
}
|
||||
|
||||
export class OperationCanceledException { }
|
||||
@@ -2447,19 +2399,19 @@ namespace ts {
|
||||
/**
|
||||
* Get a list of root file names that were passed to a 'createProgram'
|
||||
*/
|
||||
getRootFileNames(): string[];
|
||||
getRootFileNames(): ReadonlyArray<string>;
|
||||
|
||||
/**
|
||||
* Get a list of files in the program
|
||||
*/
|
||||
getSourceFiles(): SourceFile[];
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
|
||||
/**
|
||||
* Get a list of file names that were passed to 'createProgram' or referenced in a
|
||||
* program source file but could not be located.
|
||||
*/
|
||||
/* @internal */
|
||||
getMissingFilePaths(): Path[];
|
||||
getMissingFilePaths(): ReadonlyArray<Path>;
|
||||
|
||||
/**
|
||||
* Emits the JavaScript and declaration files. If targetSourceFile is not specified, then
|
||||
@@ -2473,14 +2425,14 @@ namespace ts {
|
||||
*/
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
|
||||
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
|
||||
/**
|
||||
* Gets a type checker that can be used to semantically analyze source fils in the program.
|
||||
* Gets a type checker that can be used to semantically analyze source files in the program.
|
||||
*/
|
||||
getTypeChecker(): TypeChecker;
|
||||
|
||||
@@ -2500,11 +2452,16 @@ namespace ts {
|
||||
|
||||
/* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection;
|
||||
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
|
||||
/* @internal */ isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
// For testing purposes only.
|
||||
/* @internal */ structureIsReused?: StructureIsReused;
|
||||
|
||||
/* @internal */ getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined;
|
||||
|
||||
/** Given a source file, get the name of the package it was imported from. */
|
||||
/* @internal */ sourceFileToPackageName: Map<string>;
|
||||
/** Set of all source files that some other source file redirects to. */
|
||||
/* @internal */ redirectTargetsSet: Map<true>;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2566,7 +2523,7 @@ namespace ts {
|
||||
export interface EmitResult {
|
||||
emitSkipped: boolean;
|
||||
/** Contains declaration emit diagnostics */
|
||||
diagnostics: Diagnostic[];
|
||||
diagnostics: ReadonlyArray<Diagnostic>;
|
||||
emittedFiles: string[]; // Array of files the compiler wrote to disk
|
||||
/* @internal */ sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
|
||||
}
|
||||
@@ -2575,9 +2532,9 @@ namespace ts {
|
||||
export interface TypeCheckerHost {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
|
||||
getSourceFiles(): SourceFile[];
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
getSourceFile(fileName: string): SourceFile;
|
||||
getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
|
||||
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective>;
|
||||
}
|
||||
|
||||
export interface TypeChecker {
|
||||
@@ -2597,6 +2554,7 @@ namespace ts {
|
||||
* Returns `any` if the index is not valid.
|
||||
*/
|
||||
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
|
||||
getNullableType(type: Type, flags: TypeFlags): Type;
|
||||
getNonNullableType(type: Type): Type;
|
||||
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
@@ -2611,6 +2569,15 @@ namespace ts {
|
||||
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
|
||||
getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined;
|
||||
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined;
|
||||
/**
|
||||
* If a symbol is a local symbol with an associated exported symbol, returns the exported symbol.
|
||||
* Otherwise returns its input.
|
||||
* For example, at `export type T = number;`:
|
||||
* - `getSymbolAtLocation` at the location `T` will return the exported symbol for `T`.
|
||||
* - But the result of `getSymbolsInScope` will contain the *local* symbol for `T`, not the exported symbol.
|
||||
* - Calling `getExportSymbolOfSymbol` on that local symbol will return the exported symbol.
|
||||
*/
|
||||
getExportSymbolOfSymbol(symbol: Symbol): Symbol;
|
||||
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined;
|
||||
getTypeAtLocation(node: Node): Type;
|
||||
getTypeFromTypeNode(node: TypeNode): Type;
|
||||
@@ -2650,6 +2617,8 @@ namespace ts {
|
||||
getAmbientModules(): Symbol[];
|
||||
|
||||
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
|
||||
/** Unlike `tryGetMemberInModuleExports`, this includes properties of an `export =` value. */
|
||||
/* @internal */ tryGetMemberInModuleExportsAndProperties(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
|
||||
getApparentType(type: Type): Type;
|
||||
getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined;
|
||||
getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
|
||||
@@ -2657,6 +2626,8 @@ namespace ts {
|
||||
|
||||
/* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined;
|
||||
|
||||
/* @internal */ getSymbolWalker(accept?: (symbol: Symbol) => boolean): SymbolWalker;
|
||||
|
||||
// Should not be called directly. Should only be accessed through the Program instance.
|
||||
/* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
|
||||
/* @internal */ getGlobalDiagnostics(): Diagnostic[];
|
||||
@@ -2673,9 +2644,8 @@ namespace ts {
|
||||
* Does not include properties of primitive types.
|
||||
*/
|
||||
/* @internal */ getAllPossiblePropertiesOfType(type: Type): Symbol[];
|
||||
|
||||
/* @internal */ resolveName(name: string, location: Node, meaning: SymbolFlags): Symbol | undefined;
|
||||
/* @internal */ getJsxNamespace(): string;
|
||||
/* @internal */ resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined;
|
||||
}
|
||||
|
||||
export enum NodeBuilderFlags {
|
||||
@@ -2702,6 +2672,14 @@ namespace ts {
|
||||
InTypeAlias = 1 << 23, // Writing type in type alias declaration
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface SymbolWalker {
|
||||
/** Note: Return values are not ordered. */
|
||||
walkType(root: Type): { visitedTypes: ReadonlyArray<Type>, visitedSymbols: ReadonlyArray<Symbol> };
|
||||
/** Note: Return values are not ordered. */
|
||||
walkSymbol(root: Symbol): { visitedTypes: ReadonlyArray<Type>, visitedSymbols: ReadonlyArray<Symbol> };
|
||||
}
|
||||
|
||||
export interface SymbolDisplayBuilder {
|
||||
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||
@@ -2750,10 +2728,12 @@ namespace ts {
|
||||
UseFullyQualifiedType = 1 << 8, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
|
||||
InFirstTypeArgument = 1 << 9, // Writing first type argument of the instantiated type
|
||||
InTypeAlias = 1 << 10, // Writing type in type alias declaration
|
||||
UseTypeAliasValue = 1 << 11, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
|
||||
SuppressAnyReturnType = 1 << 12, // If the return type is any-like, don't offer a return type.
|
||||
AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters
|
||||
WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class)
|
||||
InArrayType = 1 << 15, // Writing an array element type
|
||||
UseAliasDefinedOutsideCurrentScope = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value,
|
||||
// even though `T` can't be accessed in the current scope.
|
||||
}
|
||||
|
||||
export const enum SymbolFormatFlags {
|
||||
@@ -2902,13 +2882,11 @@ namespace ts {
|
||||
TypeParameter = 1 << 18, // Type parameter
|
||||
TypeAlias = 1 << 19, // Type alias
|
||||
ExportValue = 1 << 20, // Exported value marker (see comment in declareModuleMember in binder)
|
||||
ExportType = 1 << 21, // Exported type marker (see comment in declareModuleMember in binder)
|
||||
ExportNamespace = 1 << 22, // Exported namespace marker (see comment in declareModuleMember in binder)
|
||||
Alias = 1 << 23, // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
|
||||
Prototype = 1 << 24, // Prototype property (no source representation)
|
||||
ExportStar = 1 << 25, // Export * declaration
|
||||
Optional = 1 << 26, // Optional property
|
||||
Transient = 1 << 27, // Transient symbol (created during type check)
|
||||
Alias = 1 << 21, // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
|
||||
Prototype = 1 << 22, // Prototype property (no source representation)
|
||||
ExportStar = 1 << 23, // Export * declaration
|
||||
Optional = 1 << 24, // Optional property
|
||||
Transient = 1 << 25, // Transient symbol (created during type check)
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
@@ -2953,7 +2931,6 @@ namespace ts {
|
||||
BlockScoped = BlockScopedVariable | Class | Enum,
|
||||
|
||||
PropertyOrAccessor = Property | Accessor,
|
||||
Export = ExportNamespace | ExportType | ExportValue,
|
||||
|
||||
ClassMember = Method | Accessor | Property,
|
||||
|
||||
@@ -2965,7 +2942,7 @@ namespace ts {
|
||||
|
||||
export interface Symbol {
|
||||
flags: SymbolFlags; // Symbol flags
|
||||
name: __String; // Name of symbol
|
||||
escapedName: __String; // Name of symbol
|
||||
declarations?: Declaration[]; // Declarations associated with this symbol
|
||||
valueDeclaration?: Declaration; // First value declaration of the symbol
|
||||
members?: SymbolTable; // Class, interface or literal instance members
|
||||
@@ -2996,6 +2973,7 @@ namespace ts {
|
||||
leftSpread?: Symbol; // Left source for synthetic spread property
|
||||
rightSpread?: Symbol; // Right source for synthetic spread property
|
||||
syntheticOrigin?: Symbol; // For a property on a mapped or spread type, points back to the original property
|
||||
syntheticLiteralTypeOrigin?: StringLiteralType; // For a property on a mapped type, indicates the type whose text to use as the declaration name, instead of the symbol name
|
||||
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
@@ -3062,13 +3040,10 @@ namespace ts {
|
||||
*/
|
||||
export type __String = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName;
|
||||
|
||||
/** EscapedStringMap based on ES6 Map interface. */
|
||||
export interface UnderscoreEscapedMap<T> {
|
||||
/** ReadonlyMap where keys are `__String`s. */
|
||||
export interface ReadonlyUnderscoreEscapedMap<T> {
|
||||
get(key: __String): T | undefined;
|
||||
has(key: __String): boolean;
|
||||
set(key: __String, value: T): this;
|
||||
delete(key: __String): boolean;
|
||||
clear(): void;
|
||||
forEach(action: (value: T, key: __String) => void): void;
|
||||
readonly size: number;
|
||||
keys(): Iterator<__String>;
|
||||
@@ -3076,6 +3051,13 @@ namespace ts {
|
||||
entries(): Iterator<[__String, T]>;
|
||||
}
|
||||
|
||||
/** Map where keys are `__String`s. */
|
||||
export interface UnderscoreEscapedMap<T> extends ReadonlyUnderscoreEscapedMap<T> {
|
||||
set(key: __String, value: T): this;
|
||||
delete(key: __String): boolean;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/** SymbolTable based on ES6 Map interface. */
|
||||
export type SymbolTable = UnderscoreEscapedMap<Symbol>;
|
||||
|
||||
@@ -3132,6 +3114,7 @@ namespace ts {
|
||||
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
|
||||
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
|
||||
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
|
||||
resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element
|
||||
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
|
||||
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
|
||||
switchTypes?: Type[]; // Cached array of switch case expression types
|
||||
@@ -3166,7 +3149,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 1 << 23, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 24, // Type is or contains object literal type
|
||||
ContainsAnyFunctionType = 1 << 24, // Type is or contains the anyFunctionType
|
||||
NonPrimitive = 1 << 25, // intrinsic object type
|
||||
/* @internal */
|
||||
JsxAttributes = 1 << 26, // Jsx attributes type
|
||||
@@ -3253,7 +3236,7 @@ namespace ts {
|
||||
Instantiated = 1 << 7, // Instantiated anonymous or mapped type
|
||||
ObjectLiteral = 1 << 8, // Originates in an object literal
|
||||
EvolvingArray = 1 << 9, // Evolving array type
|
||||
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
|
||||
ObjectLiteralPatternWithComputedProperties = 1 << 10, // Object literal pattern with computed properties
|
||||
ClassOrInterface = Class | Interface
|
||||
}
|
||||
|
||||
@@ -3391,6 +3374,11 @@ namespace ts {
|
||||
awaitedTypeOfType?: Type;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface SyntheticDefaultModuleType extends Type {
|
||||
syntheticType?: Type;
|
||||
}
|
||||
|
||||
export interface TypeVariable extends Type {
|
||||
/* @internal */
|
||||
resolvedBaseConstraint: Type;
|
||||
@@ -3400,6 +3388,7 @@ namespace ts {
|
||||
|
||||
// Type parameters (TypeFlags.TypeParameter)
|
||||
export interface TypeParameter extends TypeVariable {
|
||||
/** Retrieve using getConstraintFromTypeParameter */
|
||||
constraint: Type; // Constraint
|
||||
default?: Type;
|
||||
/* @internal */
|
||||
@@ -3504,11 +3493,29 @@ namespace ts {
|
||||
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ternary values are defined such that
|
||||
* x & y is False if either x or y is False.
|
||||
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
* x & y is True if both x and y are True.
|
||||
* x | y is False if both x and y are False.
|
||||
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
* x | y is True if either x or y is True.
|
||||
*/
|
||||
export const enum Ternary {
|
||||
False = 0,
|
||||
Maybe = 1,
|
||||
True = -1
|
||||
}
|
||||
|
||||
export type TypeComparer = (s: Type, t: Type, reportErrors?: boolean) => Ternary;
|
||||
|
||||
/* @internal */
|
||||
export interface InferenceContext extends TypeMapper {
|
||||
signature: Signature; // Generic signature for which inferences are made
|
||||
inferences: InferenceInfo[]; // Inferences made for each type parameter
|
||||
flags: InferenceFlags; // Inference flags
|
||||
compareTypes: TypeComparer; // Type comparer function
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3638,6 +3645,7 @@ namespace ts {
|
||||
paths?: MapLike<string[]>;
|
||||
/*@internal*/ plugins?: PluginImport[];
|
||||
preserveConstEnums?: boolean;
|
||||
preserveSymlinks?: boolean;
|
||||
project?: string;
|
||||
/* @internal */ pretty?: DiagnosticStyle;
|
||||
reactNamespace?: string;
|
||||
@@ -3950,9 +3958,13 @@ namespace ts {
|
||||
fileExists(fileName: string): boolean;
|
||||
// readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json'
|
||||
// to determine location of bundled typings for node module
|
||||
readFile(fileName: string): string;
|
||||
readFile(fileName: string): string | undefined;
|
||||
trace?(s: string): void;
|
||||
directoryExists?(directoryName: string): boolean;
|
||||
/**
|
||||
* Resolve a symbolic link.
|
||||
* @see https://nodejs.org/api/fs.html#fs_fs_realpathsync_path_options
|
||||
*/
|
||||
realpath?(path: string): string;
|
||||
getCurrentDirectory?(): string;
|
||||
getDirectories?(path: string): string[];
|
||||
@@ -3968,18 +3980,14 @@ namespace ts {
|
||||
export interface ResolvedModule {
|
||||
/** Path of the file the module was resolved to. */
|
||||
resolvedFileName: string;
|
||||
/**
|
||||
* Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be a proper external module:
|
||||
* - be a .d.ts file
|
||||
* - use top level imports\exports
|
||||
* - don't use tripleslash references
|
||||
*/
|
||||
/** True if `resolvedFileName` comes from `node_modules`. */
|
||||
isExternalLibraryImport?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResolvedModule with an explicitly provided `extension` property.
|
||||
* Prefer this over `ResolvedModule`.
|
||||
* If changing this, remember to change `moduleResolutionIsEqualTo`.
|
||||
*/
|
||||
export interface ResolvedModuleFull extends ResolvedModule {
|
||||
/**
|
||||
@@ -3987,6 +3995,22 @@ namespace ts {
|
||||
* This is optional for backwards-compatibility, but will be added if not provided.
|
||||
*/
|
||||
extension: Extension;
|
||||
packageId?: PackageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unique identifier with a package name and version.
|
||||
* If changing this, remember to change `packageIdIsEqual`.
|
||||
*/
|
||||
export interface PackageId {
|
||||
/**
|
||||
* Name of the package.
|
||||
* Should not include `@types`.
|
||||
* If accessing a non-index file, this should include its name e.g. "foo/bar".
|
||||
*/
|
||||
name: string;
|
||||
/** Version of the package, e.g. "1.2.3" */
|
||||
version: string;
|
||||
}
|
||||
|
||||
export const enum Extension {
|
||||
@@ -4080,7 +4104,6 @@ namespace ts {
|
||||
ContainsBindingPattern = 1 << 23,
|
||||
ContainsYield = 1 << 24,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 25,
|
||||
|
||||
ContainsDynamicImport = 1 << 26,
|
||||
|
||||
// Please leave this as 1 << 29.
|
||||
@@ -4130,7 +4153,7 @@ namespace ts {
|
||||
export interface SourceMapSource {
|
||||
fileName: string;
|
||||
text: string;
|
||||
/* @internal */ lineMap: number[];
|
||||
/* @internal */ lineMap: ReadonlyArray<number>;
|
||||
skipTrivia?: (pos: number) => number;
|
||||
}
|
||||
|
||||
@@ -4177,6 +4200,7 @@ namespace ts {
|
||||
HasEndOfDeclarationMarker = 1 << 22, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
|
||||
Iterator = 1 << 23, // The expression to a `yield*` should be treated as an Iterator when down-leveling, not an Iterable.
|
||||
NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions.
|
||||
/*@internal*/ TypeScriptClassWrapper = 1 << 25, // The node is an IIFE class wrapper created by the ts transform.
|
||||
}
|
||||
|
||||
export interface EmitHelper {
|
||||
@@ -4237,7 +4261,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export interface EmitHost extends ScriptReferenceHost {
|
||||
getSourceFiles(): SourceFile[];
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
|
||||
/* @internal */
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
@@ -4365,7 +4389,7 @@ namespace ts {
|
||||
*/
|
||||
export type Visitor = (node: Node) => VisitResult<Node>;
|
||||
|
||||
export type VisitResult<T extends Node> = T | T[];
|
||||
export type VisitResult<T extends Node> = T | T[] | undefined;
|
||||
|
||||
export interface Printer {
|
||||
/**
|
||||
|
||||
+361
-463
File diff suppressed because it is too large
Load Diff
@@ -86,7 +86,7 @@ namespace ts {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
let updated: NodeArray<T>;
|
||||
let updated: MutableNodeArray<T>;
|
||||
|
||||
// Ensure start and count have valid values
|
||||
const length = nodes.length;
|
||||
@@ -901,7 +901,7 @@ namespace ts {
|
||||
*
|
||||
* @param nodes The NodeArray.
|
||||
*/
|
||||
function extractSingleNode(nodes: Node[]): Node {
|
||||
function extractSingleNode(nodes: ReadonlyArray<Node>): Node {
|
||||
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
|
||||
return singleOrUndefined(nodes);
|
||||
}
|
||||
@@ -1421,13 +1421,13 @@ namespace ts {
|
||||
/**
|
||||
* Merges generated lexical declarations into a new statement list.
|
||||
*/
|
||||
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: Statement[]): NodeArray<Statement>;
|
||||
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: ReadonlyArray<Statement>): NodeArray<Statement>;
|
||||
|
||||
/**
|
||||
* Appends generated lexical declarations to an array of statements.
|
||||
*/
|
||||
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]): Statement[];
|
||||
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]) {
|
||||
export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray<Statement>): Statement[];
|
||||
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: ReadonlyArray<Statement>) {
|
||||
if (!some(declarations)) {
|
||||
return statements;
|
||||
}
|
||||
@@ -1442,7 +1442,7 @@ namespace ts {
|
||||
*
|
||||
* @param nodes The NodeArray.
|
||||
*/
|
||||
export function liftToBlock(nodes: Node[]): Statement {
|
||||
export function liftToBlock(nodes: ReadonlyArray<Node>): Statement {
|
||||
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
|
||||
return <Statement>singleOrUndefined(nodes) || createBlock(<NodeArray<Statement>>nodes);
|
||||
}
|
||||
|
||||
+185
-73
@@ -130,7 +130,7 @@ namespace FourSlash {
|
||||
// 0 - cancelled
|
||||
// >0 - not cancelled
|
||||
// <0 - not cancelled and value denotes number of isCancellationRequested after which token become cancelled
|
||||
private static NotCanceled: number = -1;
|
||||
private static readonly NotCanceled: number = -1;
|
||||
private numberOfCallsBeforeCancellation: number = TestCancellationToken.NotCanceled;
|
||||
|
||||
public isCancellationRequested(): boolean {
|
||||
@@ -187,6 +187,9 @@ namespace FourSlash {
|
||||
|
||||
// The current caret position in the active file
|
||||
public currentCaretPosition = 0;
|
||||
// The position of the end of the current selection, or -1 if nothing is selected
|
||||
public selectionEnd = -1;
|
||||
|
||||
public lastKnownMarker = "";
|
||||
|
||||
// The file that's currently 'opened'
|
||||
@@ -219,7 +222,7 @@ namespace FourSlash {
|
||||
|
||||
// Add input file which has matched file name with the given reference-file path.
|
||||
// This is necessary when resolveReference flag is specified
|
||||
private addMatchedInputFile(referenceFilePath: string, extensions: string[]) {
|
||||
private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray<string>) {
|
||||
const inputFiles = this.inputFiles;
|
||||
const languageServiceAdapterHost = this.languageServiceAdapterHost;
|
||||
if (!extensions) {
|
||||
@@ -433,11 +436,19 @@ namespace FourSlash {
|
||||
|
||||
public goToPosition(pos: number) {
|
||||
this.currentCaretPosition = pos;
|
||||
this.selectionEnd = -1;
|
||||
}
|
||||
|
||||
public select(startMarker: string, endMarker: string) {
|
||||
const start = this.getMarkerByName(startMarker), end = this.getMarkerByName(endMarker);
|
||||
this.goToPosition(start.position);
|
||||
this.selectionEnd = end.position;
|
||||
}
|
||||
|
||||
public moveCaretRight(count = 1) {
|
||||
this.currentCaretPosition += count;
|
||||
this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length);
|
||||
this.selectionEnd = -1;
|
||||
}
|
||||
|
||||
// Opens a file given its 0-based index or fileName
|
||||
@@ -451,7 +462,7 @@ namespace FourSlash {
|
||||
this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content, scriptKindName);
|
||||
}
|
||||
|
||||
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
|
||||
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, shouldExist: boolean) {
|
||||
const startMarker = this.getMarkerByName(startMarkerName);
|
||||
const endMarker = this.getMarkerByName(endMarkerName);
|
||||
const predicate = (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) =>
|
||||
@@ -459,9 +470,9 @@ namespace FourSlash {
|
||||
|
||||
const exists = this.anyErrorInRange(predicate, startMarker, endMarker);
|
||||
|
||||
if (exists !== negative) {
|
||||
this.printErrorLog(negative, this.getAllDiagnostics());
|
||||
throw new Error(`Failure between markers: '${startMarkerName}', '${endMarkerName}'`);
|
||||
if (exists !== shouldExist) {
|
||||
this.printErrorLog(shouldExist, this.getAllDiagnostics());
|
||||
throw new Error(`${shouldExist ? "Expected" : "Did not expect"} failure between markers: '${startMarkerName}', '${endMarkerName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,14 +490,16 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private getDiagnostics(fileName: string): ts.Diagnostic[] {
|
||||
return this.languageService.getSyntacticDiagnostics(fileName).concat(this.languageService.getSemanticDiagnostics(fileName));
|
||||
return ts.concatenate(this.languageService.getSyntacticDiagnostics(fileName),
|
||||
this.languageService.getSemanticDiagnostics(fileName));
|
||||
}
|
||||
|
||||
private getAllDiagnostics(): ts.Diagnostic[] {
|
||||
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName => this.getDiagnostics(fileName));
|
||||
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName =>
|
||||
ts.isAnySupportedFileExtension(fileName) ? this.getDiagnostics(fileName) : []);
|
||||
}
|
||||
|
||||
public verifyErrorExistsAfterMarker(markerName: string, negative: boolean, after: boolean) {
|
||||
public verifyErrorExistsAfterMarker(markerName: string, shouldExist: boolean, after: boolean) {
|
||||
const marker: Marker = this.getMarkerByName(markerName);
|
||||
let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean;
|
||||
|
||||
@@ -502,30 +515,15 @@ namespace FourSlash {
|
||||
const exists = this.anyErrorInRange(predicate, marker);
|
||||
const diagnostics = this.getAllDiagnostics();
|
||||
|
||||
if (exists !== negative) {
|
||||
this.printErrorLog(negative, diagnostics);
|
||||
throw new Error("Failure at marker: " + markerName);
|
||||
if (exists !== shouldExist) {
|
||||
this.printErrorLog(shouldExist, diagnostics);
|
||||
throw new Error(`${shouldExist ? "Expected" : "Did not expect"} failure at marker '${markerName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean, startMarker: Marker, endMarker?: Marker) {
|
||||
|
||||
const errors = this.getDiagnostics(startMarker.fileName);
|
||||
let exists = false;
|
||||
|
||||
const startPos = startMarker.position;
|
||||
let endPos: number = undefined;
|
||||
if (endMarker !== undefined) {
|
||||
endPos = endMarker.position;
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
if (predicate(error.start, error.start + error.length, startPos, endPos)) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
|
||||
return exists;
|
||||
private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean, startMarker: Marker, endMarker?: Marker): boolean {
|
||||
return this.getDiagnostics(startMarker.fileName).some(({ start, length }) =>
|
||||
predicate(start, start + length, startMarker.position, endMarker === undefined ? undefined : endMarker.position));
|
||||
}
|
||||
|
||||
private printErrorLog(expectErrors: boolean, errors: ts.Diagnostic[]) {
|
||||
@@ -550,6 +548,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyNoErrors() {
|
||||
ts.forEachKey(this.inputFiles, fileName => {
|
||||
if (!ts.isAnySupportedFileExtension(fileName)) return;
|
||||
const errors = this.getDiagnostics(fileName);
|
||||
if (errors.length) {
|
||||
this.printErrorLog(/*expectErrors*/ false, errors);
|
||||
@@ -605,7 +604,7 @@ namespace FourSlash {
|
||||
this.verifyGoToXPlain(arg0, endMarkerNames, getDefs);
|
||||
}
|
||||
else if (ts.isArray(arg0)) {
|
||||
const pairs: [string | string[], string | string[]][] = arg0;
|
||||
const pairs: ReadonlyArray<[string | string[], string | string[]]> = arg0;
|
||||
for (const [start, end] of pairs) {
|
||||
this.verifyGoToXPlain(start, end, getDefs);
|
||||
}
|
||||
@@ -949,6 +948,22 @@ namespace FourSlash {
|
||||
this.verifySymbol(symbol, declarationRanges);
|
||||
}
|
||||
|
||||
public symbolsInScope(range: Range): ts.Symbol[] {
|
||||
const node = this.goToAndGetNode(range);
|
||||
return this.getChecker().getSymbolsInScope(node, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace);
|
||||
}
|
||||
|
||||
public verifyTypeOfSymbolAtLocation(range: Range, symbol: ts.Symbol, expected: string): void {
|
||||
const node = this.goToAndGetNode(range);
|
||||
const checker = this.getChecker();
|
||||
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
|
||||
|
||||
const actual = checker.typeToString(type);
|
||||
if (actual !== expected) {
|
||||
this.raiseError(`Expected: '${expected}', actual: '${actual}'`);
|
||||
}
|
||||
}
|
||||
|
||||
private verifyReferencesAre(expectedReferences: Range[]) {
|
||||
const actualReferences = this.getReferencesAtCaret() || [];
|
||||
|
||||
@@ -964,9 +979,9 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
for (const reference of expectedReferences) {
|
||||
const {fileName, start, end} = reference;
|
||||
const { fileName, start, end } = reference;
|
||||
if (reference.marker && reference.marker.data) {
|
||||
const {isWriteAccess, isDefinition} = reference.marker.data;
|
||||
const { isWriteAccess, isDefinition } = reference.marker.data;
|
||||
this.verifyReferencesWorker(actualReferences, fileName, start, end, isWriteAccess, isDefinition);
|
||||
}
|
||||
else {
|
||||
@@ -1134,7 +1149,7 @@ namespace FourSlash {
|
||||
this.testDiagnostics(expected, diagnostics);
|
||||
}
|
||||
|
||||
private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) {
|
||||
private testDiagnostics(expected: string, diagnostics: ReadonlyArray<ts.Diagnostic>) {
|
||||
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
|
||||
const actual = stringify(realized);
|
||||
assert.equal(actual, expected);
|
||||
@@ -1177,7 +1192,7 @@ namespace FourSlash {
|
||||
displayParts: ts.SymbolDisplayPart[],
|
||||
documentation: ts.SymbolDisplayPart[],
|
||||
tags: ts.JSDocTagInfo[]
|
||||
) {
|
||||
) {
|
||||
|
||||
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind"));
|
||||
@@ -1571,7 +1586,7 @@ namespace FourSlash {
|
||||
public printErrorList() {
|
||||
const syntacticErrors = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
|
||||
const semanticErrors = this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
|
||||
const errorList = syntacticErrors.concat(semanticErrors);
|
||||
const errorList = ts.concatenate(syntacticErrors, semanticErrors);
|
||||
Harness.IO.log(`Error list (${errorList.length} errors)`);
|
||||
|
||||
if (errorList.length) {
|
||||
@@ -1773,28 +1788,37 @@ namespace FourSlash {
|
||||
// We get back a set of edits, but langSvc.editScript only accepts one at a time. Use this to keep track
|
||||
// of the incremental offset from each edit to the next. We assume these edit ranges don't overlap
|
||||
|
||||
edits = edits.sort((a, b) => a.span.start - b.span.start);
|
||||
for (let i = 0; i < edits.length - 1; i++) {
|
||||
const firstEditSpan = edits[i].span;
|
||||
const firstEditEnd = firstEditSpan.start + firstEditSpan.length;
|
||||
assert.isTrue(firstEditEnd <= edits[i + 1].span.start);
|
||||
}
|
||||
// Copy this so we don't ruin someone else's copy
|
||||
edits = JSON.parse(JSON.stringify(edits));
|
||||
|
||||
// Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters
|
||||
const oldContent = this.getFileContent(fileName);
|
||||
let runningOffset = 0;
|
||||
|
||||
for (const edit of edits) {
|
||||
const offsetStart = edit.span.start + runningOffset;
|
||||
for (let i = 0; i < edits.length; i++) {
|
||||
const edit = edits[i];
|
||||
const offsetStart = edit.span.start;
|
||||
const offsetEnd = offsetStart + edit.span.length;
|
||||
this.editScriptAndUpdateMarkers(fileName, offsetStart, offsetEnd, edit.newText);
|
||||
const editDelta = edit.newText.length - edit.span.length;
|
||||
if (offsetStart <= this.currentCaretPosition) {
|
||||
this.currentCaretPosition += editDelta;
|
||||
if (offsetEnd <= this.currentCaretPosition) {
|
||||
// The entirety of the edit span falls before the caret position, shift the caret accordingly
|
||||
this.currentCaretPosition += editDelta;
|
||||
}
|
||||
else {
|
||||
// The span being replaced includes the caret position, place the caret at the beginning of the span
|
||||
this.currentCaretPosition = offsetStart;
|
||||
}
|
||||
}
|
||||
runningOffset += editDelta;
|
||||
// TODO: Consider doing this at least some of the time for higher fidelity. Currently causes a failure (bug 707150)
|
||||
// this.languageService.getScriptLexicalStructure(fileName);
|
||||
|
||||
// Update positions of any future edits affected by this change
|
||||
for (let j = i + 1; j < edits.length; j++) {
|
||||
if (edits[j].span.start >= edits[i].span.start) {
|
||||
edits[j].span.start += editDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isFormattingEdit) {
|
||||
@@ -1878,7 +1902,7 @@ namespace FourSlash {
|
||||
this.goToPosition(len);
|
||||
}
|
||||
|
||||
public goToRangeStart({fileName, start}: Range) {
|
||||
public goToRangeStart({ fileName, start }: Range) {
|
||||
this.openFile(fileName);
|
||||
this.goToPosition(start);
|
||||
}
|
||||
@@ -2052,7 +2076,7 @@ namespace FourSlash {
|
||||
return result;
|
||||
}
|
||||
|
||||
private rangeText({fileName, start, end}: Range): string {
|
||||
private rangeText({ fileName, start, end }: Range): string {
|
||||
return this.getFileContent(fileName).slice(start, end);
|
||||
}
|
||||
|
||||
@@ -2320,35 +2344,25 @@ namespace FourSlash {
|
||||
* @param fileName Path to file where error should be retrieved from.
|
||||
*/
|
||||
private getCodeFixActions(fileName: string, errorCode?: number): ts.CodeAction[] {
|
||||
const diagnosticsForCodeFix = this.getDiagnostics(fileName).map(diagnostic => {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
code: diagnostic.code
|
||||
};
|
||||
});
|
||||
const dedupedDiagnositcs = ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties);
|
||||
|
||||
let actions: ts.CodeAction[] = undefined;
|
||||
|
||||
for (const diagnostic of dedupedDiagnositcs) {
|
||||
const diagnosticsForCodeFix = this.getDiagnostics(fileName).map(diagnostic => ({
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
code: diagnostic.code
|
||||
}));
|
||||
|
||||
return ts.flatMap(ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties), diagnostic => {
|
||||
if (errorCode && errorCode !== diagnostic.code) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code], this.formatCodeSettings);
|
||||
if (newActions && newActions.length) {
|
||||
actions = actions ? actions.concat(newActions) : newActions;
|
||||
}
|
||||
}
|
||||
return actions;
|
||||
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code], this.formatCodeSettings);
|
||||
});
|
||||
}
|
||||
|
||||
private applyCodeActions(actions: ts.CodeAction[], index?: number): void {
|
||||
if (index === undefined) {
|
||||
if (!(actions && actions.length === 1)) {
|
||||
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
|
||||
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found. ${actions ? actions.map(a => `${Harness.IO.newLine()} "${a.description}"`) : ""}`);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
@@ -2373,7 +2387,7 @@ namespace FourSlash {
|
||||
|
||||
const codeFixes = this.getCodeFixActions(this.activeFile.fileName, errorCode);
|
||||
|
||||
if (!codeFixes || codeFixes.length === 0) {
|
||||
if (codeFixes.length === 0) {
|
||||
if (expectedTextArray.length !== 0) {
|
||||
this.raiseError("No codefixes returned.");
|
||||
}
|
||||
@@ -2392,7 +2406,7 @@ namespace FourSlash {
|
||||
const sortedActualArray = actualTextArray.sort();
|
||||
if (!ts.arrayIsEqualTo(sortedExpectedArray, sortedActualArray)) {
|
||||
this.raiseError(
|
||||
`Actual text array doesn't match expected text array. \nActual: \n"${sortedActualArray.join("\n\n")}"\n---\nExpected: \n'${sortedExpectedArray.join("\n\n")}'`);
|
||||
`Actual text array doesn't match expected text array. \nActual: \n'${sortedActualArray.join("\n\n")}'\n---\nExpected: \n'${sortedExpectedArray.join("\n\n")}'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2495,6 +2509,23 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifySpanOfEnclosingComment(negative: boolean, onlyMultiLineDiverges?: boolean) {
|
||||
const expected = !negative;
|
||||
const position = this.currentCaretPosition;
|
||||
const fileName = this.activeFile.fileName;
|
||||
const actual = !!this.languageService.getSpanOfEnclosingComment(fileName, position, /*onlyMultiLine*/ false);
|
||||
const actualOnlyMultiLine = !!this.languageService.getSpanOfEnclosingComment(fileName, position, /*onlyMultiLine*/ true);
|
||||
if (expected !== actual || onlyMultiLineDiverges === (actual === actualOnlyMultiLine)) {
|
||||
this.raiseError(`verifySpanOfEnclosingComment failed:
|
||||
position: '${position}'
|
||||
fileName: '${fileName}'
|
||||
onlyMultiLineDiverges: '${onlyMultiLineDiverges}'
|
||||
actual: '${actual}'
|
||||
actualOnlyMultiLine: '${actualOnlyMultiLine}'
|
||||
expected: '${expected}'.`);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Check number of navigationItems which match both searchValue and matchKind,
|
||||
if a filename is passed in, limit the results to that file.
|
||||
@@ -2702,11 +2733,11 @@ namespace FourSlash {
|
||||
public verifyCodeFixAvailable(negative: boolean) {
|
||||
const codeFix = this.getCodeFixActions(this.activeFile.fileName);
|
||||
|
||||
if (negative && codeFix) {
|
||||
if (negative && codeFix.length) {
|
||||
this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found one.`);
|
||||
}
|
||||
|
||||
if (!(negative || codeFix)) {
|
||||
if (!(negative || codeFix.length)) {
|
||||
this.raiseError(`verifyCodeFixAvailable failed - expected code fixes but none found.`);
|
||||
}
|
||||
}
|
||||
@@ -2723,6 +2754,35 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private getSelection() {
|
||||
return ({
|
||||
pos: this.currentCaretPosition,
|
||||
end: this.selectionEnd === -1 ? this.currentCaretPosition : this.selectionEnd
|
||||
});
|
||||
}
|
||||
|
||||
public verifyRefactorAvailable(negative: boolean, name: string, actionName?: string) {
|
||||
const selection = this.getSelection();
|
||||
|
||||
let refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, selection) || [];
|
||||
refactors = refactors.filter(r => r.name === name && (actionName === undefined || r.actions.some(a => a.name === actionName)));
|
||||
const isAvailable = refactors.length > 0;
|
||||
|
||||
if (negative) {
|
||||
if (isAvailable) {
|
||||
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected no refactor but found: ${refactors.map(r => r.name).join(", ")}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isAvailable) {
|
||||
this.raiseError(`verifyApplicableRefactorAvailableForRange failed - expected a refactor but found none.`);
|
||||
}
|
||||
if (refactors.length > 1) {
|
||||
this.raiseError(`${refactors.length} available refactors both have name ${name} and action ${actionName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public verifyApplicableRefactorAvailableForRange(negative: boolean) {
|
||||
const ranges = this.getRanges();
|
||||
if (!(ranges && ranges.length === 1)) {
|
||||
@@ -2739,6 +2799,28 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public applyRefactor({ refactorName, actionName, actionDescription }: FourSlashInterface.ApplyRefactorOptions) {
|
||||
const range = this.getSelection();
|
||||
const refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, range);
|
||||
const refactor = refactors.find(r => r.name === refactorName);
|
||||
if (!refactor) {
|
||||
this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.`);
|
||||
}
|
||||
|
||||
const action = refactor.actions.find(a => a.name === actionName);
|
||||
if (!action) {
|
||||
this.raiseError(`The expected action: ${action} is not included in: ${refactor.actions.map(a => a.name)}`);
|
||||
}
|
||||
if (action.description !== actionDescription) {
|
||||
this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`);
|
||||
}
|
||||
|
||||
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName);
|
||||
for (const edit of editInfo.edits) {
|
||||
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyFileAfterApplyingRefactorAtMarker(
|
||||
markerName: string,
|
||||
expectedContent: string,
|
||||
@@ -3426,6 +3508,10 @@ namespace FourSlashInterface {
|
||||
public markerByName(s: string): FourSlash.Marker {
|
||||
return this.state.getMarkerByName(s);
|
||||
}
|
||||
|
||||
public symbolsInScope(range: FourSlash.Range): ts.Symbol[] {
|
||||
return this.state.symbolsInScope(range);
|
||||
}
|
||||
}
|
||||
|
||||
export class GoTo {
|
||||
@@ -3479,6 +3565,10 @@ namespace FourSlashInterface {
|
||||
public file(indexOrName: any, content?: string, scriptKindName?: string): void {
|
||||
this.state.openFile(indexOrName, content, scriptKindName);
|
||||
}
|
||||
|
||||
public select(startMarker: string, endMarker: string) {
|
||||
this.state.select(startMarker, endMarker);
|
||||
}
|
||||
}
|
||||
|
||||
export class VerifyNegatable {
|
||||
@@ -3589,6 +3679,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace);
|
||||
}
|
||||
|
||||
public isInCommentAtPosition(onlyMultiLineDiverges?: boolean) {
|
||||
this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges);
|
||||
}
|
||||
|
||||
public codeFixAvailable() {
|
||||
this.state.verifyCodeFixAvailable(this.negative);
|
||||
}
|
||||
@@ -3600,6 +3694,10 @@ namespace FourSlashInterface {
|
||||
public applicableRefactorAvailableForRange() {
|
||||
this.state.verifyApplicableRefactorAvailableForRange(this.negative);
|
||||
}
|
||||
|
||||
public refactorAvailable(name: string, actionName?: string) {
|
||||
this.state.verifyRefactorAvailable(this.negative, name, actionName);
|
||||
}
|
||||
}
|
||||
|
||||
export class Verify extends VerifyNegatable {
|
||||
@@ -3694,6 +3792,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifySymbolAtLocation(startRange, declarationRanges);
|
||||
}
|
||||
|
||||
public typeOfSymbolAtLocation(range: FourSlash.Range, symbol: ts.Symbol, expected: string) {
|
||||
this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected);
|
||||
}
|
||||
|
||||
public referencesOf(start: FourSlash.Range, references: FourSlash.Range[]) {
|
||||
this.state.verifyReferencesOf(start, references);
|
||||
}
|
||||
@@ -3991,6 +4093,10 @@ namespace FourSlashInterface {
|
||||
public disableFormatting() {
|
||||
this.state.enableFormatting = false;
|
||||
}
|
||||
|
||||
public applyRefactor(options: ApplyRefactorOptions) {
|
||||
this.state.applyRefactor(options);
|
||||
}
|
||||
}
|
||||
|
||||
export class Debug {
|
||||
@@ -4202,4 +4308,10 @@ namespace FourSlashInterface {
|
||||
return { classificationType, text, textSpan };
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApplyRefactorOptions {
|
||||
refactorName: string;
|
||||
actionName: string;
|
||||
actionDescription: string;
|
||||
}
|
||||
}
|
||||
|
||||
+72
-45
@@ -67,17 +67,16 @@ namespace Utils {
|
||||
|
||||
export let currentExecutionEnvironment = getExecutionEnvironment();
|
||||
|
||||
const Buffer: typeof global.Buffer = currentExecutionEnvironment !== ExecutionEnvironment.Browser
|
||||
? require("buffer").Buffer
|
||||
: undefined;
|
||||
// Thanks to browserify, Buffer is always available nowadays
|
||||
const Buffer: typeof global.Buffer = require("buffer").Buffer;
|
||||
|
||||
export function encodeString(s: string): string {
|
||||
return Buffer ? (new Buffer(s)).toString("utf8") : s;
|
||||
return Buffer.from(s).toString("utf8");
|
||||
}
|
||||
|
||||
export function byteLength(s: string, encoding?: string): number {
|
||||
// stub implementation if Buffer is not available (in-browser case)
|
||||
return Buffer ? Buffer.byteLength(s, encoding) : s.length;
|
||||
return Buffer.byteLength(s, encoding);
|
||||
}
|
||||
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
@@ -133,17 +132,18 @@ namespace Utils {
|
||||
return content;
|
||||
}
|
||||
|
||||
export function memoize<T extends Function>(f: T): T {
|
||||
const cache: { [idx: string]: any } = {};
|
||||
export function memoize<T extends Function>(f: T, memoKey: (...anything: any[]) => string): T {
|
||||
const cache = ts.createMap<any>();
|
||||
|
||||
return <any>(function(this: any) {
|
||||
const key = Array.prototype.join.call(arguments);
|
||||
const cachedResult = cache[key];
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
return <any>(function(this: any, ...args: any[]) {
|
||||
const key = memoKey(...args);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
}
|
||||
else {
|
||||
return cache[key] = f.apply(this, arguments);
|
||||
const value = f.apply(this, args);
|
||||
cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -207,7 +207,7 @@ namespace Utils {
|
||||
return a !== undefined && typeof a.pos === "number";
|
||||
}
|
||||
|
||||
export function convertDiagnostics(diagnostics: ts.Diagnostic[]) {
|
||||
export function convertDiagnostics(diagnostics: ReadonlyArray<ts.Diagnostic>) {
|
||||
return diagnostics.map(convertDiagnostic);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ namespace Utils {
|
||||
}
|
||||
}
|
||||
|
||||
export function assertDiagnosticsEquals(array1: ts.Diagnostic[], array2: ts.Diagnostic[]) {
|
||||
export function assertDiagnosticsEquals(array1: ReadonlyArray<ts.Diagnostic>, array2: ReadonlyArray<ts.Diagnostic>) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +420,7 @@ namespace Utils {
|
||||
|
||||
const maxHarnessFrames = 1;
|
||||
|
||||
export function filterStack(error: Error, stackTraceLimit: number = Infinity) {
|
||||
export function filterStack(error: Error, stackTraceLimit = Infinity) {
|
||||
const stack = <string>(<any>error).stack;
|
||||
if (stack) {
|
||||
const lines = stack.split(/\r\n?|\n/g);
|
||||
@@ -479,7 +479,7 @@ namespace Harness {
|
||||
getCurrentDirectory(): string;
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
resolvePath(path: string): string;
|
||||
readFile(path: string): string;
|
||||
readFile(path: string): string | undefined;
|
||||
writeFile(path: string, contents: string): void;
|
||||
directoryName(path: string): string;
|
||||
getDirectories(path: string): string[];
|
||||
@@ -493,7 +493,7 @@ namespace Harness {
|
||||
args(): string[];
|
||||
getExecutingFilePath(): string;
|
||||
exit(exitCode?: number): void;
|
||||
readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[], depth?: number): string[];
|
||||
readDirectory(path: string, extension?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
tryEnableSourceMapsForHost?(): void;
|
||||
getEnvironmentVariable?(name: string): string;
|
||||
}
|
||||
@@ -564,7 +564,7 @@ namespace Harness {
|
||||
}
|
||||
|
||||
export let listFiles: typeof IO.listFiles = (path, spec?, options?) => {
|
||||
options = options || <{ recursive?: boolean; }>{};
|
||||
options = options || {};
|
||||
|
||||
function filesInFolder(folder: string): string[] {
|
||||
let paths: string[] = [];
|
||||
@@ -686,7 +686,7 @@ namespace Harness {
|
||||
|
||||
return dirPath;
|
||||
}
|
||||
export let directoryName: typeof IO.directoryName = Utils.memoize(directoryNameImpl);
|
||||
export let directoryName: typeof IO.directoryName = Utils.memoize(directoryNameImpl, path => path);
|
||||
|
||||
export function resolvePath(path: string) {
|
||||
const response = Http.getFileFromServerSync(serverRoot + path + "?resolve=true");
|
||||
@@ -703,23 +703,24 @@ namespace Harness {
|
||||
return response.status === 200;
|
||||
}
|
||||
|
||||
export let listFiles = Utils.memoize((path: string, spec?: RegExp): string[] => {
|
||||
export const listFiles = Utils.memoize((path: string, spec?: RegExp, options?: { recursive?: boolean }): string[] => {
|
||||
const response = Http.getFileFromServerSync(serverRoot + path);
|
||||
if (response.status === 200) {
|
||||
const results = response.responseText.split(",");
|
||||
let results = response.responseText.split(",");
|
||||
if (spec) {
|
||||
return results.filter(file => spec.test(file));
|
||||
results = results.filter(file => spec.test(file));
|
||||
}
|
||||
else {
|
||||
return results;
|
||||
if (options && !options.recursive) {
|
||||
results = results.filter(file => (ts.getDirectoryPath(ts.normalizeSlashes(file)) === path));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
else {
|
||||
return [""];
|
||||
}
|
||||
});
|
||||
}, (path: string, spec?: RegExp, options?: { recursive?: boolean }) => `${path}|${spec}|${options ? options.recursive : undefined}`);
|
||||
|
||||
export function readFile(file: string) {
|
||||
export function readFile(file: string): string | undefined {
|
||||
const response = Http.getFileFromServerSync(serverRoot + file);
|
||||
if (response.status === 200) {
|
||||
return response.responseText;
|
||||
@@ -976,7 +977,7 @@ namespace Harness {
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getNewLine: () => newLine,
|
||||
fileExists: fileName => fileMap.has(toPath(fileName)),
|
||||
readFile: (fileName: string): string => {
|
||||
readFile(fileName: string): string | undefined {
|
||||
const file = fileMap.get(toPath(fileName));
|
||||
if (ts.endsWith(fileName, "json")) {
|
||||
// strip comments
|
||||
@@ -1194,13 +1195,21 @@ namespace Harness {
|
||||
return { result, options };
|
||||
}
|
||||
|
||||
export function compileDeclarationFiles(inputFiles: TestFile[],
|
||||
export interface DeclarationCompilationContext {
|
||||
declInputFiles: TestFile[];
|
||||
declOtherFiles: TestFile[];
|
||||
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions;
|
||||
options: ts.CompilerOptions;
|
||||
currentDirectory: string;
|
||||
}
|
||||
|
||||
export function prepareDeclarationCompilationContext(inputFiles: TestFile[],
|
||||
otherFiles: TestFile[],
|
||||
result: CompilerResult,
|
||||
harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions,
|
||||
options: ts.CompilerOptions,
|
||||
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
|
||||
currentDirectory: string) {
|
||||
currentDirectory: string): DeclarationCompilationContext | undefined {
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
|
||||
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
|
||||
}
|
||||
@@ -1212,8 +1221,7 @@ namespace Harness {
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
|
||||
ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
|
||||
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
|
||||
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory || harnessSettings["currentDirectory"]);
|
||||
return { declInputFiles, declOtherFiles, declResult: output.result };
|
||||
return { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory: currentDirectory || harnessSettings["currentDirectory"] };
|
||||
}
|
||||
|
||||
function addDtsFile(file: TestFile, dtsFiles: TestFile[]) {
|
||||
@@ -1259,6 +1267,15 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
export function compileDeclarationFiles(context: DeclarationCompilationContext | undefined) {
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
const { declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory } = context;
|
||||
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory);
|
||||
return { declInputFiles, declOtherFiles, declResult: output.result };
|
||||
}
|
||||
|
||||
function normalizeLineEndings(text: string, lineEnding: string): string {
|
||||
let normalized = text.replace(/\r\n?/g, "\n");
|
||||
if (lineEnding !== "\n") {
|
||||
@@ -1267,16 +1284,25 @@ namespace Harness {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function minimalDiagnosticsToString(diagnostics: ts.Diagnostic[]) {
|
||||
export function minimalDiagnosticsToString(diagnostics: ReadonlyArray<ts.Diagnostic>) {
|
||||
return ts.formatDiagnostics(diagnostics, { getCanonicalFileName, getCurrentDirectory: () => "", getNewLine: () => Harness.IO.newLine() });
|
||||
}
|
||||
|
||||
export function getErrorBaseline(inputFiles: TestFile[], diagnostics: ts.Diagnostic[]) {
|
||||
diagnostics.sort(ts.compareDiagnostics);
|
||||
const outputLines: string[] = [];
|
||||
export function getErrorBaseline(inputFiles: ReadonlyArray<TestFile>, diagnostics: ReadonlyArray<ts.Diagnostic>) {
|
||||
diagnostics = diagnostics.slice().sort(ts.compareDiagnostics);
|
||||
let outputLines = "";
|
||||
// Count up all errors that were found in files other than lib.d.ts so we don't miss any
|
||||
let totalErrorsReportedInNonLibraryFiles = 0;
|
||||
|
||||
let firstLine = true;
|
||||
function newLine() {
|
||||
if (firstLine) {
|
||||
firstLine = false;
|
||||
return "";
|
||||
}
|
||||
return "\r\n";
|
||||
}
|
||||
|
||||
function outputErrorText(error: ts.Diagnostic) {
|
||||
const message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine());
|
||||
|
||||
@@ -1285,7 +1311,7 @@ namespace Harness {
|
||||
.map(s => s.length > 0 && s.charAt(s.length - 1) === "\r" ? s.substr(0, s.length - 1) : s)
|
||||
.filter(s => s.length > 0)
|
||||
.map(s => "!!! " + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
|
||||
errLines.forEach(e => outputLines.push(e));
|
||||
errLines.forEach(e => outputLines += (newLine() + e));
|
||||
|
||||
// do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics
|
||||
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
|
||||
@@ -1311,7 +1337,7 @@ namespace Harness {
|
||||
|
||||
|
||||
// Header
|
||||
outputLines.push("==== " + inputFile.unitName + " (" + fileErrors.length + " errors) ====");
|
||||
outputLines += (newLine() + "==== " + inputFile.unitName + " (" + fileErrors.length + " errors) ====");
|
||||
|
||||
// Make sure we emit something for every error
|
||||
let markedErrorCount = 0;
|
||||
@@ -1340,7 +1366,7 @@ namespace Harness {
|
||||
nextLineStart = lineStarts[lineIndex + 1];
|
||||
}
|
||||
// Emit this line from the original file
|
||||
outputLines.push(" " + line);
|
||||
outputLines += (newLine() + " " + line);
|
||||
fileErrors.forEach(err => {
|
||||
// Does any error start or continue on to this line? Emit squiggles
|
||||
const end = ts.textSpanEnd(err);
|
||||
@@ -1352,7 +1378,7 @@ namespace Harness {
|
||||
// Calculate the start of the squiggle
|
||||
const squiggleStart = Math.max(0, relativeOffset);
|
||||
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
|
||||
outputLines.push(" " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"));
|
||||
outputLines += (newLine() + " " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"));
|
||||
|
||||
// If the error ended here, or we're at the end of the file, emit its message
|
||||
if ((lineIndex === lines.length - 1) || nextLineStart > end) {
|
||||
@@ -1383,7 +1409,7 @@ namespace Harness {
|
||||
assert.equal(totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length, "total number of errors");
|
||||
|
||||
return minimalDiagnosticsToString(diagnostics) +
|
||||
Harness.IO.newLine() + Harness.IO.newLine() + outputLines.join("\r\n");
|
||||
Harness.IO.newLine() + Harness.IO.newLine() + outputLines;
|
||||
}
|
||||
|
||||
export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[]) {
|
||||
@@ -1586,9 +1612,10 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
const declFileCompilationResult =
|
||||
Harness.Compiler.compileDeclarationFiles(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
|
||||
const declFileContext = Harness.Compiler.prepareDeclarationCompilationContext(
|
||||
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined
|
||||
);
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declFileContext);
|
||||
|
||||
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
|
||||
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
|
||||
@@ -1963,7 +1990,7 @@ namespace Harness {
|
||||
IO.writeFile(actualFileName + ".delete", "");
|
||||
}
|
||||
else {
|
||||
IO.writeFile(actualFileName, actual);
|
||||
IO.writeFile(actualFileName, encoded_actual);
|
||||
}
|
||||
throw new Error(`The baseline file ${relativeFileName} has changed.`);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
class DefaultHostCancellationToken implements ts.HostCancellationToken {
|
||||
public static Instance = new DefaultHostCancellationToken();
|
||||
public static readonly Instance = new DefaultHostCancellationToken();
|
||||
|
||||
public isCancellationRequested() {
|
||||
return false;
|
||||
@@ -193,7 +193,9 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
getCurrentDirectory(): string { return virtualFileSystemRoot; }
|
||||
getDefaultLibFileName(): string { return Harness.Compiler.defaultLibFileName; }
|
||||
getScriptFileNames(): string[] { return this.getFilenames(); }
|
||||
getScriptFileNames(): string[] {
|
||||
return this.getFilenames().filter(ts.isAnySupportedFileExtension);
|
||||
}
|
||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
||||
const script = this.getScriptInfo(fileName);
|
||||
return script ? new ScriptSnapshot(script) : undefined;
|
||||
@@ -208,14 +210,14 @@ namespace Harness.LanguageService {
|
||||
const script = this.getScriptSnapshot(fileName);
|
||||
return script !== undefined;
|
||||
}
|
||||
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[] {
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
return ts.matchFiles(path, extensions, exclude, include,
|
||||
/*useCaseSensitiveFileNames*/ false,
|
||||
this.getCurrentDirectory(),
|
||||
depth,
|
||||
(p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p));
|
||||
}
|
||||
readFile(path: string): string {
|
||||
readFile(path: string): string | undefined {
|
||||
const snapshot = this.getScriptSnapshot(path);
|
||||
return snapshot.getText(0, snapshot.getLength());
|
||||
}
|
||||
@@ -485,6 +487,9 @@ namespace Harness.LanguageService {
|
||||
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean {
|
||||
return unwrapJSONCallResult(this.shim.isValidBraceCompletionAtPosition(fileName, position, openingBrace));
|
||||
}
|
||||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan {
|
||||
return unwrapJSONCallResult(this.shim.getSpanOfEnclosingComment(fileName, position, onlyMultiLine));
|
||||
}
|
||||
getCodeFixesAtPosition(): ts.CodeAction[] {
|
||||
throw new Error("Not supported on the shim.");
|
||||
}
|
||||
@@ -619,7 +624,7 @@ namespace Harness.LanguageService {
|
||||
this.writeMessage(message);
|
||||
}
|
||||
|
||||
readFile(fileName: string): string {
|
||||
readFile(fileName: string): string | undefined {
|
||||
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
|
||||
fileName = Harness.Compiler.defaultLibFileName;
|
||||
}
|
||||
@@ -681,11 +686,11 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
info(message: string): void {
|
||||
return this.host.log(message);
|
||||
this.host.log(message);
|
||||
}
|
||||
|
||||
msg(message: string) {
|
||||
return this.host.log(message);
|
||||
msg(message: string): void {
|
||||
this.host.log(message);
|
||||
}
|
||||
|
||||
loggingEnabled() {
|
||||
@@ -700,17 +705,13 @@ namespace Harness.LanguageService {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
endGroup(): void {
|
||||
}
|
||||
startGroup() { throw ts.notImplemented(); }
|
||||
endGroup() { throw ts.notImplemented(); }
|
||||
|
||||
perftrc(message: string): void {
|
||||
return this.host.log(message);
|
||||
}
|
||||
|
||||
startGroup(): void {
|
||||
}
|
||||
|
||||
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any {
|
||||
return setTimeout(callback, ms, args);
|
||||
}
|
||||
@@ -795,7 +796,7 @@ namespace Harness.LanguageService {
|
||||
default:
|
||||
return {
|
||||
module: undefined,
|
||||
error: "Could not resolve module"
|
||||
error: new Error("Could not resolve module")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -828,6 +829,7 @@ namespace Harness.LanguageService {
|
||||
host: serverHost,
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const fs: any = require("fs");
|
||||
const path: any = require("path");
|
||||
import fs = require("fs");
|
||||
import path = require("path");
|
||||
|
||||
function instrumentForRecording(fn: string, tscPath: string) {
|
||||
instrument(tscPath, `
|
||||
@@ -38,7 +38,9 @@ function instrument(tscPath: string, prepareCode: string, cleanupCode = "") {
|
||||
|
||||
const index2 = index1 + invocationLine.length;
|
||||
const newContent = tscContent.substr(0, index1) + loggerContent + prepareCode + invocationLine + cleanupCode + tscContent.substr(index2) + "\r\n";
|
||||
fs.writeFile(tscPath, newContent);
|
||||
fs.writeFile(tscPath, newContent, err => {
|
||||
if (err) throw err;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -64,11 +64,11 @@ interface IOLog {
|
||||
}[];
|
||||
directoriesRead: {
|
||||
path: string,
|
||||
extensions: string[],
|
||||
exclude: string[],
|
||||
include: string[],
|
||||
extensions: ReadonlyArray<string>,
|
||||
exclude: ReadonlyArray<string>,
|
||||
include: ReadonlyArray<string>,
|
||||
depth: number,
|
||||
result: string[]
|
||||
result: ReadonlyArray<string>,
|
||||
}[];
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
interface ProjectRunnerTestCase {
|
||||
scenario: string;
|
||||
projectRoot: string; // project where it lives - this also is the current directory when compiling
|
||||
inputFiles: string[]; // list of input files to be given to program
|
||||
inputFiles: ReadonlyArray<string>; // list of input files to be given to program
|
||||
resolveMapRoot?: boolean; // should we resolve this map root and give compiler the absolute disk path as map root?
|
||||
resolveSourceRoot?: boolean; // should we resolve this source root and give compiler the absolute disk path as map root?
|
||||
baselineCheck?: boolean; // Verify the baselines of output files, if this is false, we will write to output to the disk but there is no verification of baselines
|
||||
@@ -15,8 +15,8 @@ interface ProjectRunnerTestCase {
|
||||
|
||||
interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
|
||||
// Apart from actual test case the results of the resolution
|
||||
resolvedInputFiles: string[]; // List of files that were asked to read by compiler
|
||||
emittedFiles: string[]; // List of files that were emitted by the compiler
|
||||
resolvedInputFiles: ReadonlyArray<string>; // List of files that were asked to read by compiler
|
||||
emittedFiles: ReadonlyArray<string>; // List of files that were emitted by the compiler
|
||||
}
|
||||
|
||||
interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.GeneratedFile {
|
||||
@@ -24,12 +24,12 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera
|
||||
}
|
||||
|
||||
interface CompileProjectFilesResult {
|
||||
configFileSourceFiles: ts.SourceFile[];
|
||||
configFileSourceFiles: ReadonlyArray<ts.SourceFile>;
|
||||
moduleKind: ts.ModuleKind;
|
||||
program?: ts.Program;
|
||||
compilerOptions?: ts.CompilerOptions;
|
||||
errors: ts.Diagnostic[];
|
||||
sourceMapData?: ts.SourceMapData[];
|
||||
errors: ReadonlyArray<ts.Diagnostic>;
|
||||
sourceMapData?: ReadonlyArray<ts.SourceMapData>;
|
||||
}
|
||||
|
||||
interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
|
||||
@@ -125,17 +125,17 @@ class ProjectRunner extends RunnerBase {
|
||||
return Harness.IO.resolvePath(testCase.projectRoot);
|
||||
}
|
||||
|
||||
function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ts.SourceFile[],
|
||||
getInputFiles: () => string[],
|
||||
function compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: ReadonlyArray<ts.SourceFile>,
|
||||
getInputFiles: () => ReadonlyArray<string>,
|
||||
getSourceFileTextImpl: (fileName: string) => string,
|
||||
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void,
|
||||
compilerOptions: ts.CompilerOptions): CompileProjectFilesResult {
|
||||
|
||||
const program = ts.createProgram(getInputFiles(), compilerOptions, createCompilerHost());
|
||||
let errors = ts.getPreEmitDiagnostics(program);
|
||||
const errors = ts.getPreEmitDiagnostics(program);
|
||||
|
||||
const emitResult = program.emit();
|
||||
errors = ts.concatenate(errors, emitResult.diagnostics);
|
||||
ts.addRange(errors, emitResult.diagnostics);
|
||||
const sourceMapData = emitResult.sourceMaps;
|
||||
|
||||
// Clean up source map data that will be used in baselining
|
||||
@@ -235,7 +235,7 @@ class ProjectRunner extends RunnerBase {
|
||||
compilerOptions,
|
||||
sourceMapData: projectCompilerResult.sourceMapData,
|
||||
outputFiles,
|
||||
errors: errors ? errors.concat(projectCompilerResult.errors) : projectCompilerResult.errors,
|
||||
errors: errors ? ts.concatenate(errors, projectCompilerResult.errors) : projectCompilerResult.errors,
|
||||
};
|
||||
|
||||
function createCompilerOptions() {
|
||||
@@ -289,7 +289,7 @@ class ProjectRunner extends RunnerBase {
|
||||
return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
|
||||
function readFile(fileName: string): string {
|
||||
function readFile(fileName: string): string | undefined {
|
||||
return Harness.IO.readFile(getFileNameInTheProjectTest(fileName));
|
||||
}
|
||||
|
||||
@@ -422,16 +422,21 @@ class ProjectRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
|
||||
const inputFiles = ts.map(compilerResult.configFileSourceFiles.concat(
|
||||
compilerResult.program ?
|
||||
ts.filter(compilerResult.program.getSourceFiles(), sourceFile => !Harness.isDefaultLibraryFile(sourceFile.fileName)) :
|
||||
[]),
|
||||
sourceFile => <Harness.Compiler.TestFile>{
|
||||
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
|
||||
RunnerBase.removeFullPaths(sourceFile.fileName) :
|
||||
sourceFile.fileName,
|
||||
content: sourceFile.text
|
||||
});
|
||||
const inputSourceFiles = compilerResult.configFileSourceFiles.slice();
|
||||
if (compilerResult.program) {
|
||||
for (const sourceFile of compilerResult.program.getSourceFiles()) {
|
||||
if (!Harness.isDefaultLibraryFile(sourceFile.fileName)) {
|
||||
inputSourceFiles.push(sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const inputFiles = inputSourceFiles.map<Harness.Compiler.TestFile>(sourceFile => ({
|
||||
unitName: ts.isRootedDiskPath(sourceFile.fileName) ?
|
||||
RunnerBase.removeFullPaths(sourceFile.fileName) :
|
||||
sourceFile.fileName,
|
||||
content: sourceFile.text
|
||||
}));
|
||||
|
||||
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
|
||||
}
|
||||
|
||||
+26
-16
@@ -54,7 +54,8 @@ namespace RWC {
|
||||
useCustomLibraryFile = undefined;
|
||||
});
|
||||
|
||||
it("can compile", () => {
|
||||
it("can compile", function(this: Mocha.ITestCallbackContext) {
|
||||
this.timeout(800000); // Allow long timeouts for RWC compilations
|
||||
let opts: ts.ParsedCommandLine;
|
||||
|
||||
const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
|
||||
@@ -89,9 +90,16 @@ namespace RWC {
|
||||
ts.setConfigFileInOptions(opts.options, configParseResult.options.configFile);
|
||||
}
|
||||
|
||||
// Load the files
|
||||
// Deduplicate files so they are only printed once in baselines (they are deduplicated within the compiler already)
|
||||
const uniqueNames = ts.createMap<true>();
|
||||
for (const fileName of fileNames) {
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileName));
|
||||
// Must maintain order, build result list while checking map
|
||||
const normalized = ts.normalizeSlashes(fileName);
|
||||
if (!uniqueNames.has(normalized)) {
|
||||
uniqueNames.set(normalized, true);
|
||||
// Load the file
|
||||
inputFiles.push(getHarnessCompilerInputUnit(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
// Add files to compilation
|
||||
@@ -207,6 +215,14 @@ namespace RWC {
|
||||
}, baselineOpts);
|
||||
});
|
||||
|
||||
it("has the expected types", () => {
|
||||
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
|
||||
.concat(otherFiles)
|
||||
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
|
||||
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), 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", () => {
|
||||
@@ -216,8 +232,12 @@ namespace RWC {
|
||||
return null;
|
||||
}
|
||||
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
|
||||
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
|
||||
const declContext = Harness.Compiler.prepareDeclarationCompilationContext(
|
||||
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory
|
||||
);
|
||||
// Reset compilerResult before calling into `compileDeclarationFiles` so the memory from the original compilation can be freed
|
||||
compilerResult = undefined;
|
||||
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext);
|
||||
|
||||
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
|
||||
Harness.IO.newLine() + Harness.IO.newLine() +
|
||||
@@ -225,23 +245,13 @@ namespace RWC {
|
||||
}, baselineOpts);
|
||||
}
|
||||
});
|
||||
|
||||
it("has the expected types", () => {
|
||||
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
|
||||
.concat(otherFiles)
|
||||
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
|
||||
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class RWCRunner extends RunnerBase {
|
||||
private static sourcePath = "internal/cases/rwc/";
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
return Harness.IO.listFiles("internal/cases/rwc/", /.+\.json$/);
|
||||
}
|
||||
|
||||
public kind(): TestRunnerKind {
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
/* tslint:disable:no-null-keyword */
|
||||
|
||||
class Test262BaselineRunner extends RunnerBase {
|
||||
private static basePath = "internal/cases/test262";
|
||||
private static helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
|
||||
private static helperFile: Harness.Compiler.TestFile = {
|
||||
private static readonly basePath = "internal/cases/test262";
|
||||
private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
|
||||
private static readonly helperFile: Harness.Compiler.TestFile = {
|
||||
unitName: Test262BaselineRunner.helpersFilePath,
|
||||
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath),
|
||||
};
|
||||
private static testFileExtensionRegex = /\.js$/;
|
||||
private static options: ts.CompilerOptions = {
|
||||
private static readonly testFileExtensionRegex = /\.js$/;
|
||||
private static readonly options: ts.CompilerOptions = {
|
||||
allowNonTsExtensions: true,
|
||||
target: ts.ScriptTarget.Latest,
|
||||
module: ts.ModuleKind.CommonJS
|
||||
};
|
||||
private static baselineOptions: Harness.Baseline.BaselineOptions = {
|
||||
private static readonly baselineOptions: Harness.Baseline.BaselineOptions = {
|
||||
Subfolder: "test262",
|
||||
Baselinefolder: "internal/baselines"
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"../compiler/parser.ts",
|
||||
"../compiler/utilities.ts",
|
||||
"../compiler/binder.ts",
|
||||
"../compiler/symbolWalker.ts",
|
||||
"../compiler/checker.ts",
|
||||
"../compiler/factory.ts",
|
||||
"../compiler/visitor.ts",
|
||||
@@ -74,11 +75,6 @@
|
||||
"../services/formatting/tokenRange.ts",
|
||||
"../services/codeFixProvider.ts",
|
||||
"../services/codefixes/fixes.ts",
|
||||
"../services/codefixes/fixExtendsInterfaceBecomesImplements.ts",
|
||||
"../services/codefixes/fixClassIncorrectlyImplementsInterface.ts",
|
||||
"../services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
|
||||
"../services/codefixes/fixClassSuperMustPrecedeThisAccess.ts",
|
||||
"../services/codefixes/fixConstructorForDerivedNeedSuperCall.ts",
|
||||
"../services/codefixes/helpers.ts",
|
||||
"../services/codefixes/importFixes.ts",
|
||||
"../services/codefixes/fixUnusedIdentifier.ts",
|
||||
@@ -108,6 +104,7 @@
|
||||
"./unittests/services/preProcessFile.ts",
|
||||
"./unittests/services/patternMatcher.ts",
|
||||
"./unittests/session.ts",
|
||||
"./unittests/symbolWalker.ts",
|
||||
"./unittests/versionCache.ts",
|
||||
"./unittests/convertToBase64.ts",
|
||||
"./unittests/transpile.ts",
|
||||
@@ -128,6 +125,7 @@
|
||||
"./unittests/printer.ts",
|
||||
"./unittests/transform.ts",
|
||||
"./unittests/customTransforms.ts",
|
||||
"./unittests/extractMethods.ts",
|
||||
"./unittests/textChanges.ts",
|
||||
"./unittests/telemetry.ts",
|
||||
"./unittests/programMissingFiles.ts"
|
||||
|
||||
@@ -52,23 +52,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createProject(rootFile: string, serverHost: server.ServerHost): { project: server.Project, rootScriptInfo: server.ScriptInfo } {
|
||||
const logger: server.Logger = {
|
||||
close: noop,
|
||||
hasLevel: () => false,
|
||||
loggingEnabled: () => false,
|
||||
perftrc: noop,
|
||||
info: noop,
|
||||
startGroup: noop,
|
||||
endGroup: noop,
|
||||
msg: noop,
|
||||
getLogFileName: (): string => undefined
|
||||
};
|
||||
|
||||
const svcOpts: server.ProjectServiceOptions = {
|
||||
host: serverHost,
|
||||
logger,
|
||||
logger: projectSystem.nullLogger,
|
||||
cancellationToken: { isCancellationRequested: () => false },
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined
|
||||
};
|
||||
const projectService = new server.ProjectService(svcOpts);
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace ts.projectSystem {
|
||||
host,
|
||||
cancellationToken: nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
@@ -518,18 +519,20 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([f], { newLine });
|
||||
const session = createSession(host);
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
const openRequest: server.protocol.OpenRequest = {
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "open",
|
||||
command: server.protocol.CommandTypes.Open,
|
||||
arguments: { file: f.path }
|
||||
});
|
||||
session.executeCommand(<server.protocol.CompileOnSaveEmitFileRequest>{
|
||||
};
|
||||
session.executeCommand(openRequest);
|
||||
const emitFileRequest: server.protocol.CompileOnSaveEmitFileRequest = {
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "compileOnSaveEmitFile",
|
||||
command: server.protocol.CommandTypes.CompileOnSaveEmitFile,
|
||||
arguments: { file: f.path }
|
||||
});
|
||||
};
|
||||
session.executeCommand(emitFileRequest);
|
||||
const emitOutput = host.readFile(path + ts.Extension.Js);
|
||||
assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline");
|
||||
}
|
||||
@@ -550,7 +553,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
const session = createSession(host, { typingsInstaller });
|
||||
|
||||
openFilesForSession([file1, file2], session);
|
||||
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });
|
||||
|
||||
@@ -67,14 +67,14 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"]
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -92,7 +92,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -100,7 +100,7 @@ namespace ts {
|
||||
allowJs: false,
|
||||
lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"]
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -117,7 +117,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -146,7 +146,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
@@ -174,7 +174,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
@@ -201,7 +201,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
},
|
||||
@@ -227,7 +227,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
noImplicitAny: false,
|
||||
sourceMap: false,
|
||||
},
|
||||
@@ -255,7 +255,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -286,7 +286,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -317,7 +317,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -348,7 +348,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -379,7 +379,7 @@ namespace ts {
|
||||
}
|
||||
}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES5,
|
||||
noImplicitAny: false,
|
||||
@@ -415,8 +415,8 @@ namespace ts {
|
||||
it("Convert default tsconfig.json to compiler-options ", () => {
|
||||
assertCompilerOptions({}, "tsconfig.json",
|
||||
{
|
||||
compilerOptions: {} as CompilerOptions,
|
||||
errors: <Diagnostic[]>[]
|
||||
compilerOptions: {},
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -434,7 +434,7 @@ namespace ts {
|
||||
}
|
||||
}, "jsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
allowJs: true,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true,
|
||||
@@ -445,7 +445,7 @@ namespace ts {
|
||||
sourceMap: false,
|
||||
lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"]
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -463,7 +463,7 @@ namespace ts {
|
||||
}
|
||||
}, "jsconfig.json",
|
||||
{
|
||||
compilerOptions: <CompilerOptions>{
|
||||
compilerOptions: {
|
||||
allowJs: false,
|
||||
maxNodeModuleJsDepth: 2,
|
||||
allowSyntheticDefaultImports: true,
|
||||
@@ -474,7 +474,7 @@ namespace ts {
|
||||
sourceMap: false,
|
||||
lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"]
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -516,7 +516,7 @@ namespace ts {
|
||||
allowSyntheticDefaultImports: true,
|
||||
skipLibCheck: true
|
||||
},
|
||||
errors: <Diagnostic[]>[]
|
||||
errors: []
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="tsserverProjectSystem.ts" />
|
||||
|
||||
namespace ts {
|
||||
interface Range {
|
||||
start: number;
|
||||
end: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Test {
|
||||
source: string;
|
||||
ranges: Map<Range>;
|
||||
}
|
||||
|
||||
function extractTest(source: string): Test {
|
||||
const activeRanges: Range[] = [];
|
||||
let text = "";
|
||||
let lastPos = 0;
|
||||
let pos = 0;
|
||||
const ranges = createMap<Range>();
|
||||
|
||||
while (pos < source.length) {
|
||||
if (source.charCodeAt(pos) === CharacterCodes.openBracket &&
|
||||
(source.charCodeAt(pos + 1) === CharacterCodes.hash || source.charCodeAt(pos + 1) === CharacterCodes.$)) {
|
||||
const saved = pos;
|
||||
pos += 2;
|
||||
const s = pos;
|
||||
consumeIdentifier();
|
||||
const e = pos;
|
||||
if (source.charCodeAt(pos) === CharacterCodes.bar) {
|
||||
pos++;
|
||||
text += source.substring(lastPos, saved);
|
||||
const name = s === e
|
||||
? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted"
|
||||
: source.substring(s, e);
|
||||
activeRanges.push({ name, start: text.length, end: undefined });
|
||||
lastPos = pos;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
pos = saved;
|
||||
}
|
||||
}
|
||||
else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) {
|
||||
text += source.substring(lastPos, pos);
|
||||
activeRanges[activeRanges.length - 1].end = text.length;
|
||||
const range = activeRanges.pop();
|
||||
if (range.name in ranges) {
|
||||
throw new Error(`Duplicate name of range ${range.name}`);
|
||||
}
|
||||
ranges.set(range.name, range);
|
||||
pos += 2;
|
||||
lastPos = pos;
|
||||
continue;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
text += source.substring(lastPos, pos);
|
||||
|
||||
function consumeIdentifier() {
|
||||
while (isIdentifierPart(source.charCodeAt(pos), ScriptTarget.Latest)) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
return { source: text, ranges };
|
||||
}
|
||||
|
||||
const newLineCharacter = "\n";
|
||||
function getRuleProvider(action?: (opts: FormatCodeSettings) => void) {
|
||||
const options = {
|
||||
indentSize: 4,
|
||||
tabSize: 4,
|
||||
newLineCharacter,
|
||||
convertTabsToSpaces: true,
|
||||
indentStyle: ts.IndentStyle.Smart,
|
||||
insertSpaceAfterConstructor: false,
|
||||
insertSpaceAfterCommaDelimiter: true,
|
||||
insertSpaceAfterSemicolonInForStatements: true,
|
||||
insertSpaceBeforeAndAfterBinaryOperators: true,
|
||||
insertSpaceAfterKeywordsInControlFlowStatements: true,
|
||||
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
|
||||
insertSpaceBeforeFunctionParenthesis: false,
|
||||
placeOpenBraceOnNewLineForFunctions: false,
|
||||
placeOpenBraceOnNewLineForControlBlocks: false,
|
||||
};
|
||||
if (action) {
|
||||
action(options);
|
||||
}
|
||||
const rulesProvider = new formatting.RulesProvider();
|
||||
rulesProvider.ensureUpToDate(options);
|
||||
return rulesProvider;
|
||||
}
|
||||
|
||||
function testExtractRangeFailed(caption: string, s: string, expectedErrors: string[]) {
|
||||
return it(caption, () => {
|
||||
const t = extractTest(s);
|
||||
const file = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
|
||||
const selectionRange = t.ranges.get("selection");
|
||||
if (!selectionRange) {
|
||||
throw new Error(`Test ${s} does not specify selection range`);
|
||||
}
|
||||
const result = refactor.extractMethod.getRangeToExtract(file, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
|
||||
assert(result.targetRange === undefined, "failure expected");
|
||||
const sortedErrors = result.errors.map(e => <string>e.messageText).sort();
|
||||
assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors");
|
||||
});
|
||||
}
|
||||
|
||||
function testExtractRange(s: string): void {
|
||||
const t = extractTest(s);
|
||||
const f = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true);
|
||||
const selectionRange = t.ranges.get("selection");
|
||||
if (!selectionRange) {
|
||||
throw new Error(`Test ${s} does not specify selection range`);
|
||||
}
|
||||
const result = refactor.extractMethod.getRangeToExtract(f, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
|
||||
const expectedRange = t.ranges.get("extracted");
|
||||
if (expectedRange) {
|
||||
let start: number, end: number;
|
||||
if (ts.isArray(result.targetRange.range)) {
|
||||
start = result.targetRange.range[0].getStart(f);
|
||||
end = ts.lastOrUndefined(result.targetRange.range).getEnd();
|
||||
}
|
||||
else {
|
||||
start = result.targetRange.range.getStart(f);
|
||||
end = result.targetRange.range.getEnd();
|
||||
}
|
||||
assert.equal(start, expectedRange.start, "incorrect start of range");
|
||||
assert.equal(end, expectedRange.end, "incorrect end of range");
|
||||
}
|
||||
else {
|
||||
assert.isTrue(!result.targetRange, `expected range to extract to be undefined`);
|
||||
}
|
||||
}
|
||||
|
||||
describe("extractMethods", () => {
|
||||
it("get extract range from selection", () => {
|
||||
testExtractRange(`
|
||||
[#|
|
||||
[$|var x = 1;
|
||||
var y = 2;|]|]
|
||||
`);
|
||||
testExtractRange(`
|
||||
[#|
|
||||
var x = 1;
|
||||
var y = 2|];
|
||||
`);
|
||||
testExtractRange(`
|
||||
[#|var x = 1|];
|
||||
var y = 2;
|
||||
`);
|
||||
testExtractRange(`
|
||||
if ([#|[#extracted|a && b && c && d|]|]) {
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
if [#|(a && b && c && d|]) {
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
if (a && b && c && d) {
|
||||
[#| [$|var x = 1;
|
||||
console.log(x);|] |]
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
[#|
|
||||
if (a) {
|
||||
return 100;
|
||||
} |]
|
||||
`);
|
||||
testExtractRange(`
|
||||
function foo() {
|
||||
[#| [$|if (a) {
|
||||
}
|
||||
return 100|] |]
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
[#|
|
||||
[$|l1:
|
||||
if (x) {
|
||||
break l1;
|
||||
}|]|]
|
||||
`);
|
||||
testExtractRange(`
|
||||
[#|
|
||||
[$|l2:
|
||||
{
|
||||
if (x) {
|
||||
}
|
||||
break l2;
|
||||
}|]|]
|
||||
`);
|
||||
testExtractRange(`
|
||||
while (true) {
|
||||
[#| if(x) {
|
||||
}
|
||||
break; |]
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
while (true) {
|
||||
[#| if(x) {
|
||||
}
|
||||
continue; |]
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
l3:
|
||||
{
|
||||
[#|
|
||||
if (x) {
|
||||
}
|
||||
break l3; |]
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
function f() {
|
||||
while (true) {
|
||||
[#|
|
||||
if (x) {
|
||||
return;
|
||||
} |]
|
||||
}
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
function f() {
|
||||
while (true) {
|
||||
[#|
|
||||
[$|if (x) {
|
||||
}
|
||||
return;|]
|
||||
|]
|
||||
}
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
function f() {
|
||||
return [#| [$|1 + 2|] |]+ 3;
|
||||
}
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
function f() {
|
||||
return [$|1 + [#|2 + 3|]|];
|
||||
}
|
||||
}
|
||||
`);
|
||||
testExtractRange(`
|
||||
function f() {
|
||||
return [$|1 + 2 + [#|3 + 4|]|];
|
||||
}
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed1",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
[#|
|
||||
let x = 1
|
||||
if (x) {
|
||||
return 10;
|
||||
}
|
||||
|]
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing conditional return statement."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed2",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
while (true) {
|
||||
[#|
|
||||
let x = 1
|
||||
if (x) {
|
||||
break;
|
||||
}
|
||||
|]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing conditional break or continue statements."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed3",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
while (true) {
|
||||
[#|
|
||||
let x = 1
|
||||
if (x) {
|
||||
continue;
|
||||
}
|
||||
|]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing conditional break or continue statements."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed4",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
l1: {
|
||||
[#|
|
||||
let x = 1
|
||||
if (x) {
|
||||
break l1;
|
||||
}
|
||||
|]
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing labeled break or continue with target outside of the range."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed5",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
[#|
|
||||
try {
|
||||
f2()
|
||||
return 10;
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|]
|
||||
}
|
||||
function f2() {
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing conditional return statement."
|
||||
]);
|
||||
|
||||
testExtractRangeFailed("extractRangeFailed6",
|
||||
`
|
||||
namespace A {
|
||||
function f() {
|
||||
[#|
|
||||
try {
|
||||
f2()
|
||||
}
|
||||
catch (e) {
|
||||
return 10;
|
||||
}
|
||||
|]
|
||||
}
|
||||
function f2() {
|
||||
}
|
||||
}
|
||||
`,
|
||||
[
|
||||
"Cannot extract range containing conditional return statement."
|
||||
]);
|
||||
|
||||
testExtractMethod("extractMethod1",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
function foo() {
|
||||
}
|
||||
namespace B {
|
||||
function a() {
|
||||
let a = 1;
|
||||
[#|
|
||||
let y = 5;
|
||||
let z = x;
|
||||
a = y;
|
||||
foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod2",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
function foo() {
|
||||
}
|
||||
namespace B {
|
||||
function a() {
|
||||
[#|
|
||||
let y = 5;
|
||||
let z = x;
|
||||
return foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod3",
|
||||
`namespace A {
|
||||
function foo() {
|
||||
}
|
||||
namespace B {
|
||||
function* a(z: number) {
|
||||
[#|
|
||||
let y = 5;
|
||||
yield z;
|
||||
return foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod4",
|
||||
`namespace A {
|
||||
function foo() {
|
||||
}
|
||||
namespace B {
|
||||
async function a(z: number, z1: any) {
|
||||
[#|
|
||||
let y = 5;
|
||||
if (z) {
|
||||
await z1;
|
||||
}
|
||||
return foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod5",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
export function foo() {
|
||||
}
|
||||
namespace B {
|
||||
function a() {
|
||||
let a = 1;
|
||||
[#|
|
||||
let y = 5;
|
||||
let z = x;
|
||||
a = y;
|
||||
foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod6",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
export function foo() {
|
||||
}
|
||||
namespace B {
|
||||
function a() {
|
||||
let a = 1;
|
||||
[#|
|
||||
let y = 5;
|
||||
let z = x;
|
||||
a = y;
|
||||
return foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod7",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
export namespace C {
|
||||
export function foo() {
|
||||
}
|
||||
}
|
||||
namespace B {
|
||||
function a() {
|
||||
let a = 1;
|
||||
[#|
|
||||
let y = 5;
|
||||
let z = x;
|
||||
a = y;
|
||||
return C.foo();|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod8",
|
||||
`namespace A {
|
||||
let x = 1;
|
||||
namespace B {
|
||||
function a() {
|
||||
let a1 = 1;
|
||||
return 1 + [#|a1 + x|] + 100;
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod9",
|
||||
`namespace A {
|
||||
export interface I { x: number };
|
||||
namespace B {
|
||||
function a() {
|
||||
[#|let a1: I = { x: 1 };
|
||||
return a1.x + 10;|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod10",
|
||||
`namespace A {
|
||||
export interface I { x: number };
|
||||
class C {
|
||||
a() {
|
||||
let z = 1;
|
||||
[#|let a1: I = { x: 1 };
|
||||
return a1.x + 10;|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod11",
|
||||
`namespace A {
|
||||
let y = 1;
|
||||
class C {
|
||||
a() {
|
||||
let z = 1;
|
||||
[#|let a1 = { x: 1 };
|
||||
y = 10;
|
||||
z = 42;
|
||||
return a1.x + 10;|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
testExtractMethod("extractMethod12",
|
||||
`namespace A {
|
||||
let y = 1;
|
||||
class C {
|
||||
b() {}
|
||||
a() {
|
||||
let z = 1;
|
||||
[#|let a1 = { x: 1 };
|
||||
y = 10;
|
||||
z = 42;
|
||||
this.b();
|
||||
return a1.x + 10;|]
|
||||
}
|
||||
}
|
||||
}`);
|
||||
});
|
||||
|
||||
|
||||
function testExtractMethod(caption: string, text: string) {
|
||||
it(caption, () => {
|
||||
Harness.Baseline.runBaseline(`extractMethod/${caption}.js`, () => {
|
||||
const t = extractTest(text);
|
||||
const selectionRange = t.ranges.get("selection");
|
||||
if (!selectionRange) {
|
||||
throw new Error(`Test ${caption} does not specify selection range`);
|
||||
}
|
||||
const f = {
|
||||
path: "/a.ts",
|
||||
content: t.source
|
||||
};
|
||||
const host = projectSystem.createServerHost([f]);
|
||||
const projectService = projectSystem.createProjectService(host);
|
||||
projectService.openClientFile(f.path);
|
||||
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
|
||||
const sourceFile = program.getSourceFile(f.path);
|
||||
const context: RefactorContext = {
|
||||
cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } },
|
||||
newLineCharacter,
|
||||
program,
|
||||
file: sourceFile,
|
||||
startPosition: -1,
|
||||
rulesProvider: getRuleProvider()
|
||||
};
|
||||
const result = refactor.extractMethod.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end));
|
||||
assert.equal(result.errors, undefined, "expect no errors");
|
||||
const results = refactor.extractMethod.getPossibleExtractions(result.targetRange, context);
|
||||
const data: string[] = [];
|
||||
data.push(`==ORIGINAL==`);
|
||||
data.push(sourceFile.text);
|
||||
for (const r of results) {
|
||||
const changes = refactor.extractMethod.getPossibleExtractions(result.targetRange, context, results.indexOf(r))[0].changes;
|
||||
data.push(`==SCOPE::${r.scopeDescription}==`);
|
||||
data.push(textChanges.applyChanges(sourceFile.text, changes[0].textChanges));
|
||||
}
|
||||
return data.join(newLineCharacter);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,8 @@ namespace ts {
|
||||
parsesCorrectly("functionType1", "{function()}");
|
||||
parsesCorrectly("functionType2", "{function(string, boolean)}");
|
||||
parsesCorrectly("functionReturnType1", "{function(string, boolean)}");
|
||||
parsesCorrectly("thisType1", "{this:a.b}");
|
||||
parsesCorrectly("newType1", "{new:a.b}");
|
||||
parsesCorrectly("thisType1", "{function(this:a.b)}");
|
||||
parsesCorrectly("newType1", "{function(new:a.b)}");
|
||||
parsesCorrectly("variadicType", "{...number}");
|
||||
parsesCorrectly("optionalType", "{number=}");
|
||||
parsesCorrectly("optionalNullable", "{?=}");
|
||||
@@ -54,7 +54,7 @@ namespace ts {
|
||||
parsesCorrectly("typeReference3", "{a.function}");
|
||||
parsesCorrectly("arrayType1", "{a[]}");
|
||||
parsesCorrectly("arrayType2", "{a[][]}");
|
||||
parsesCorrectly("arrayType3", "{a[][]=}");
|
||||
parsesCorrectly("arrayType3", "{(a[][])=}");
|
||||
parsesCorrectly("keyword1", "{var}");
|
||||
parsesCorrectly("keyword2", "{null}");
|
||||
parsesCorrectly("keyword3", "{undefined}");
|
||||
@@ -62,6 +62,12 @@ namespace ts {
|
||||
parsesCorrectly("tupleType1", "{[number]}");
|
||||
parsesCorrectly("tupleType2", "{[number,string]}");
|
||||
parsesCorrectly("tupleType3", "{[number,string,boolean]}");
|
||||
parsesCorrectly("tupleTypeWithTrailingComma", "{[number,]}");
|
||||
parsesCorrectly("typeOfType", "{typeof M}");
|
||||
parsesCorrectly("tsConstructorType", "{new () => string}");
|
||||
parsesCorrectly("tsFunctionType", "{() => string}");
|
||||
parsesCorrectly("typeArgumentsNotFollowingDot", "{a<>}");
|
||||
parsesCorrectly("functionTypeWithTrailingComma", "{function(a,)}");
|
||||
});
|
||||
|
||||
describe("parsesIncorrectly", () => {
|
||||
@@ -69,21 +75,13 @@ namespace ts {
|
||||
parsesIncorrectly("unionTypeWithTrailingBar", "{(a|)}");
|
||||
parsesIncorrectly("unionTypeWithoutTypes", "{()}");
|
||||
parsesIncorrectly("nullableTypeWithoutType", "{!}");
|
||||
parsesIncorrectly("functionTypeWithTrailingComma", "{function(a,)}");
|
||||
parsesIncorrectly("thisWithoutType", "{this:}");
|
||||
parsesIncorrectly("newWithoutType", "{new:}");
|
||||
parsesIncorrectly("variadicWithoutType", "{...}");
|
||||
parsesIncorrectly("optionalWithoutType", "{=}");
|
||||
parsesIncorrectly("allWithType", "{*foo}");
|
||||
parsesIncorrectly("typeArgumentsNotFollowingDot", "{a<>}");
|
||||
parsesIncorrectly("emptyTypeArguments", "{a.<>}");
|
||||
parsesIncorrectly("typeArgumentsWithTrailingComma", "{a.<a,>}");
|
||||
parsesIncorrectly("tsFunctionType", "{() => string}");
|
||||
parsesIncorrectly("tsConstructoType", "{new () => string}");
|
||||
parsesIncorrectly("typeOfType", "{typeof M}");
|
||||
parsesIncorrectly("namedParameter", "{function(a: number)}");
|
||||
parsesIncorrectly("tupleTypeWithComma", "{[,]}");
|
||||
parsesIncorrectly("tupleTypeWithTrailingComma", "{[number,]}");
|
||||
parsesIncorrectly("tupleTypeWithLeadingComma", "{[,number]}");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace ts {
|
||||
"c:/dev/a.d.ts",
|
||||
"c:/dev/a.js",
|
||||
"c:/dev/b.ts",
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/node_modules/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts"
|
||||
@@ -109,23 +110,21 @@ namespace ts {
|
||||
}
|
||||
{
|
||||
const actual = ts.parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
|
||||
expected.errors = map(expected.errors, error => {
|
||||
return <Diagnostic>{
|
||||
category: error.category,
|
||||
code: error.code,
|
||||
file: undefined,
|
||||
length: undefined,
|
||||
messageText: error.messageText,
|
||||
start: undefined,
|
||||
};
|
||||
});
|
||||
expected.errors = expected.errors.map<Diagnostic>(error => ({
|
||||
category: error.category,
|
||||
code: error.code,
|
||||
file: undefined,
|
||||
length: undefined,
|
||||
messageText: error.messageText,
|
||||
start: undefined,
|
||||
}));
|
||||
assertParsed(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
function createDiagnosticForConfigFile(json: any, start: number, length: number, diagnosticMessage: DiagnosticMessage, arg0: string) {
|
||||
const text = JSON.stringify(json);
|
||||
const file = <SourceFile>{
|
||||
const file = <SourceFile>{ // tslint:disable-line no-object-literal-type-assertion
|
||||
fileName: caseInsensitiveTsconfigPath,
|
||||
kind: SyntaxKind.SourceFile,
|
||||
text
|
||||
@@ -141,7 +140,8 @@ namespace ts {
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/b.ts"
|
||||
"c:/dev/b.ts",
|
||||
"c:/dev/x/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
@@ -462,7 +462,6 @@ namespace ts {
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
});
|
||||
|
||||
it("same named declarations are excluded", () => {
|
||||
const json = {
|
||||
include: [
|
||||
@@ -651,71 +650,127 @@ namespace ts {
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("with common package folders and no exclusions", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("with common package folders and exclusions", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
],
|
||||
exclude: [
|
||||
"a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("with common package folders and empty exclude", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
],
|
||||
exclude: <string[]>[]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
describe("with common package folders", () => {
|
||||
it("and no exclusions", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/x/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("and exclusions", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/?.ts"
|
||||
],
|
||||
exclude: [
|
||||
"a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/b.ts",
|
||||
"c:/dev/x/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("and empty exclude", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
],
|
||||
exclude: <string[]>[]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/x/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("and explicit recursive include", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts",
|
||||
"**/node_modules/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("and wildcard include", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"*/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/x/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
it("and explicit wildcard include", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"*/a.ts",
|
||||
"node_modules/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
});
|
||||
});
|
||||
it("exclude .js files when allowJs=false", () => {
|
||||
const json = {
|
||||
@@ -1066,6 +1121,7 @@ namespace ts {
|
||||
};
|
||||
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
});
|
||||
|
||||
describe("with trailing recursive directory", () => {
|
||||
it("in includes", () => {
|
||||
const json = {
|
||||
@@ -1264,6 +1320,7 @@ namespace ts {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with files or folders that begin with a .", () => {
|
||||
it("that are not explicitly included", () => {
|
||||
const json = {
|
||||
|
||||
@@ -26,10 +26,19 @@ namespace ts {
|
||||
interface File {
|
||||
name: string;
|
||||
content?: string;
|
||||
symlinks?: string[];
|
||||
}
|
||||
|
||||
function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[]): ModuleResolutionHost {
|
||||
const map = arrayToMap(files, f => f.name);
|
||||
const map = createMap<File>();
|
||||
for (const file of files) {
|
||||
map.set(file.name, file);
|
||||
if (file.symlinks) {
|
||||
for (const symlink of file.symlinks) {
|
||||
map.set(symlink, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDirectoryExists) {
|
||||
const directories = createMap<string>();
|
||||
@@ -46,6 +55,7 @@ namespace ts {
|
||||
}
|
||||
return {
|
||||
readFile,
|
||||
realpath,
|
||||
directoryExists: path => directories.has(path),
|
||||
fileExists: path => {
|
||||
assert.isTrue(directories.has(getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`);
|
||||
@@ -54,12 +64,15 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
else {
|
||||
return { readFile, fileExists: path => map.has(path) };
|
||||
return { readFile, realpath, fileExists: path => map.has(path) };
|
||||
}
|
||||
function readFile(path: string): string {
|
||||
function readFile(path: string): string | undefined {
|
||||
const file = map.get(path);
|
||||
return file && file.content;
|
||||
}
|
||||
function realpath(path: string): string {
|
||||
return map.get(path).name;
|
||||
}
|
||||
}
|
||||
|
||||
describe("Node module resolution - relative paths", () => {
|
||||
@@ -233,8 +246,8 @@ namespace ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
const containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
const moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
const containingFile: File = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
const moduleFile: File = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true), [
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.ts",
|
||||
@@ -289,6 +302,19 @@ namespace ts {
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
testPreserveSymlinks(/*preserveSymlinks*/ false);
|
||||
testPreserveSymlinks(/*preserveSymlinks*/ true);
|
||||
function testPreserveSymlinks(preserveSymlinks: boolean) {
|
||||
it(`preserveSymlinks: ${preserveSymlinks}`, () => {
|
||||
const realFileName = "/linked/index.d.ts";
|
||||
const symlinkFileName = "/app/node_modulex/linked/index.d.ts";
|
||||
const host = createModuleResolutionHost(/*hasDirectoryExists*/ true, { name: realFileName, symlinks: [symlinkFileName] });
|
||||
const resolution = nodeModuleNameResolver("linked", "/app/app.ts", { preserveSymlinks }, host);
|
||||
const resolvedFileName = preserveSymlinks ? symlinkFileName : realFileName;
|
||||
checkResolvedModule(resolution.resolvedModule, { resolvedFileName, isExternalLibraryImport: true, extension: Extension.Dts });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("Module resolution - relative imports", () => {
|
||||
@@ -399,7 +425,7 @@ export = C;
|
||||
readFile: notImplemented
|
||||
};
|
||||
const program = createProgram(rootFiles, options, host);
|
||||
const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics().concat(program.getOptionsDiagnostics()));
|
||||
const diagnostics = sortAndDeduplicateDiagnostics([...program.getSemanticDiagnostics(), ...program.getOptionsDiagnostics()]);
|
||||
assert.equal(diagnostics.length, diagnosticCodes.length, `Incorrect number of expected diagnostics, expected ${diagnosticCodes.length}, got '${Harness.Compiler.minimalDiagnosticsToString(diagnostics)}'`);
|
||||
for (let i = 0; i < diagnosticCodes.length; i++) {
|
||||
assert.equal(diagnostics[i].code, diagnosticCodes[i], `Expected diagnostic code ${diagnosticCodes[i]}, got '${diagnostics[i].code}': '${diagnostics[i].messageText}'`);
|
||||
|
||||
@@ -48,18 +48,18 @@ namespace ts {
|
||||
const program = createProgram(["./nonexistent.ts"], options, testCompilerHost);
|
||||
const missing = program.getMissingFilePaths();
|
||||
assert.isDefined(missing);
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts"]); // Absolute path
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts" as Path]); // Absolute path
|
||||
});
|
||||
|
||||
it("handles multiple missing root files", () => {
|
||||
const program = createProgram(["./nonexistent0.ts", "./nonexistent1.ts"], options, testCompilerHost);
|
||||
const missing = program.getMissingFilePaths().sort();
|
||||
const missing = program.getMissingFilePaths().slice().sort();
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]);
|
||||
});
|
||||
|
||||
it("handles a mix of present and missing root files", () => {
|
||||
const program = createProgram(["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], options, testCompilerHost);
|
||||
const missing = program.getMissingFilePaths().sort();
|
||||
const missing = program.getMissingFilePaths().slice().sort();
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]);
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace ts {
|
||||
const program = createProgram(["./nonexistent.ts", "./nonexistent.ts"], options, testCompilerHost);
|
||||
const missing = program.getMissingFilePaths();
|
||||
assert.isDefined(missing);
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts"]);
|
||||
assert.deepEqual(missing, ["d:/pretend/nonexistent.ts" as Path]);
|
||||
});
|
||||
|
||||
it("normalizes file paths", () => {
|
||||
@@ -81,7 +81,7 @@ namespace ts {
|
||||
|
||||
it("handles missing triple slash references", () => {
|
||||
const program = createProgram([referenceFileRelativePath], options, testCompilerHost);
|
||||
const missing = program.getMissingFilePaths().sort();
|
||||
const missing = program.getMissingFilePaths().slice().sort();
|
||||
assert.isDefined(missing);
|
||||
assert.deepEqual(missing, [
|
||||
// From absolute reference
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
namespace ts.projectSystem {
|
||||
describe("Project errors", () => {
|
||||
function checkProjectErrors(projectFiles: server.ProjectFilesWithTSDiagnostics, expectedErrors: string[]) {
|
||||
function checkProjectErrors(projectFiles: server.ProjectFilesWithTSDiagnostics, expectedErrors: ReadonlyArray<string>): void {
|
||||
assert.isTrue(projectFiles !== undefined, "missing project files");
|
||||
checkProjectErrorsWorker(projectFiles.projectErrors, expectedErrors);
|
||||
}
|
||||
|
||||
function checkProjectErrorsWorker(errors: Diagnostic[], expectedErrors: string[]) {
|
||||
function checkProjectErrorsWorker(errors: ReadonlyArray<Diagnostic>, expectedErrors: ReadonlyArray<string>): void {
|
||||
assert.equal(errors ? errors.length : 0, expectedErrors.length, `expected ${expectedErrors.length} error in the list`);
|
||||
if (expectedErrors.length) {
|
||||
for (let i = 0; i < errors.length; i++) {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
interface ProgramWithSourceTexts extends Program {
|
||||
sourceTexts?: NamedSourceText[];
|
||||
sourceTexts?: ReadonlyArray<NamedSourceText>;
|
||||
host: TestCompilerHost;
|
||||
}
|
||||
|
||||
@@ -106,10 +106,13 @@ namespace ts {
|
||||
return file;
|
||||
}
|
||||
|
||||
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
|
||||
function createTestCompilerHost(texts: ReadonlyArray<NamedSourceText>, target: ScriptTarget, oldProgram?: ProgramWithSourceTexts): TestCompilerHost {
|
||||
const files = arrayToMap(texts, t => t.name, t => {
|
||||
if (oldProgram) {
|
||||
const oldFile = <SourceFileWithText>oldProgram.getSourceFile(t.name);
|
||||
let oldFile = <SourceFileWithText>oldProgram.getSourceFile(t.name);
|
||||
if (oldFile && oldFile.redirectInfo) {
|
||||
oldFile = oldFile.redirectInfo.unredirected;
|
||||
}
|
||||
if (oldFile && oldFile.sourceText.getVersion() === t.text.getVersion()) {
|
||||
return oldFile;
|
||||
}
|
||||
@@ -159,7 +162,7 @@ namespace ts {
|
||||
return program;
|
||||
}
|
||||
|
||||
function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: string[], options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
|
||||
function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
|
||||
if (!newTexts) {
|
||||
newTexts = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
|
||||
}
|
||||
@@ -171,11 +174,16 @@ namespace ts {
|
||||
return program;
|
||||
}
|
||||
|
||||
function updateProgramText(files: ReadonlyArray<NamedSourceText>, fileName: string, newProgramText: string) {
|
||||
const file = find(files, f => f.name === fileName)!;
|
||||
file.text = file.text.updateProgram(newProgramText);
|
||||
}
|
||||
|
||||
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}'`);
|
||||
assert.equal(expected.resolvedFileName, actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.equal(expected.primary, actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -238,7 +246,7 @@ namespace ts {
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 100");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Completely);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
const program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
const program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
assert.equal(program1Diagnostics.length, program2Diagnostics.length);
|
||||
@@ -249,7 +257,7 @@ namespace ts {
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 100");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Completely);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
const program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
const program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
assert.equal(program1Diagnostics.length, program2Diagnostics.length);
|
||||
@@ -263,19 +271,19 @@ namespace ts {
|
||||
`;
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.SafeModules);
|
||||
});
|
||||
|
||||
it("fails if change affects type references", () => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { types: ["a"] });
|
||||
updateProgram(program_1, ["a.ts"], { types: ["b"] }, noop);
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Not);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
});
|
||||
|
||||
it("succeeds if change doesn't affect type references", () => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { types: ["a"] });
|
||||
updateProgram(program_1, ["a.ts"], { types: ["a"] }, noop);
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Completely);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
});
|
||||
|
||||
it("fails if change affects imports", () => {
|
||||
@@ -283,7 +291,7 @@ namespace ts {
|
||||
updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[2].text = files[2].text.updateImportsAndExports("import x from 'b'");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.SafeModules);
|
||||
});
|
||||
|
||||
it("fails if change affects type directives", () => {
|
||||
@@ -295,25 +303,25 @@ namespace ts {
|
||||
/// <reference types="typerefs1" />`;
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.SafeModules);
|
||||
});
|
||||
|
||||
it("fails if module kind changes", () => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS });
|
||||
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.AMD }, noop);
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Not);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
});
|
||||
|
||||
it("fails if rootdir changes", () => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" });
|
||||
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, noop);
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Not);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
});
|
||||
|
||||
it("fails if config path changes", () => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" });
|
||||
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, noop);
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Not);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
});
|
||||
|
||||
it("succeeds if missing files remain missing", () => {
|
||||
@@ -357,7 +365,7 @@ namespace ts {
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Completely);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts") }));
|
||||
@@ -367,7 +375,7 @@ namespace ts {
|
||||
const program_3 = updateProgram(program_2, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateImportsAndExports("");
|
||||
});
|
||||
assert.isTrue(program_2.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_2.structureIsReused, StructureIsReused.SafeModules);
|
||||
checkResolvedModulesCache(program_3, "a.ts", /*expectedContent*/ undefined);
|
||||
|
||||
const program_4 = updateProgram(program_3, ["a.ts"], options, files => {
|
||||
@@ -376,7 +384,7 @@ namespace ts {
|
||||
`;
|
||||
files[0].text = files[0].text.updateImportsAndExports(newImports);
|
||||
});
|
||||
assert.isTrue(program_3.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_3.structureIsReused, StructureIsReused.SafeModules);
|
||||
checkResolvedModulesCache(program_4, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts"), "c": undefined }));
|
||||
});
|
||||
|
||||
@@ -394,7 +402,7 @@ namespace ts {
|
||||
const program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused === StructureIsReused.Completely);
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
@@ -405,7 +413,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateReferences("");
|
||||
});
|
||||
|
||||
assert.isTrue(program_2.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_2.structureIsReused, StructureIsReused.SafeModules);
|
||||
checkResolvedTypeDirectivesCache(program_3, "/a.ts", /*expectedContent*/ undefined);
|
||||
|
||||
updateProgram(program_3, ["/a.ts"], options, files => {
|
||||
@@ -414,7 +422,7 @@ namespace ts {
|
||||
`;
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
});
|
||||
assert.isTrue(program_3.structureIsReused === StructureIsReused.SafeModules);
|
||||
assert.equal(program_3.structureIsReused, StructureIsReused.SafeModules);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
});
|
||||
|
||||
@@ -454,7 +462,7 @@ namespace ts {
|
||||
"initialProgram: execute module resolution normally.");
|
||||
|
||||
const initialProgramDiagnostics = initialProgram.getSemanticDiagnostics(initialProgram.getSourceFile("file1.ts"));
|
||||
assert(initialProgramDiagnostics.length === 1, `initialProgram: import should fail.`);
|
||||
assert.lengthOf(initialProgramDiagnostics, 1, `initialProgram: import should fail.`);
|
||||
}
|
||||
|
||||
const afterNpmInstallProgram = updateProgram(initialProgram, rootFiles.map(f => f.name), options, f => {
|
||||
@@ -478,7 +486,7 @@ namespace ts {
|
||||
"afterNpmInstallProgram: execute module resolution normally.");
|
||||
|
||||
const afterNpmInstallProgramDiagnostics = afterNpmInstallProgram.getSemanticDiagnostics(afterNpmInstallProgram.getSourceFile("file1.ts"));
|
||||
assert(afterNpmInstallProgramDiagnostics.length === 0, `afterNpmInstallProgram: program is well-formed with import.`);
|
||||
assert.lengthOf(afterNpmInstallProgramDiagnostics, 0, `afterNpmInstallProgram: program is well-formed with import.`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -617,10 +625,10 @@ namespace ts {
|
||||
"File 'f1.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './f1' was successfully resolved to 'f1.ts'. ========"
|
||||
],
|
||||
"program_1: execute module reoslution normally.");
|
||||
"program_1: execute module resolution normally.");
|
||||
|
||||
const program_1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("f2.ts"));
|
||||
assert(program_1Diagnostics.length === expectedErrors, `initial program should be well-formed`);
|
||||
assert.lengthOf(program_1Diagnostics, expectedErrors, `initial program should be well-formed`);
|
||||
}
|
||||
const indexOfF1 = 6;
|
||||
const program_2 = updateProgram(program_1, program_1.getRootFileNames(), options, f => {
|
||||
@@ -630,7 +638,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_2Diagnostics = program_2.getSemanticDiagnostics(program_2.getSourceFile("f2.ts"));
|
||||
assert(program_2Diagnostics.length === expectedErrors, `removing no-default-lib shouldn't affect any types used.`);
|
||||
assert.lengthOf(program_2Diagnostics, expectedErrors, `removing no-default-lib shouldn't affect any types used.`);
|
||||
|
||||
assert.deepEqual(program_2.host.getTrace(), [
|
||||
"======== Resolving type reference directive 'typerefs1', containing file 'f1.ts', root directory 'node_modules/@types'. ========",
|
||||
@@ -659,7 +667,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_3Diagnostics = program_3.getSemanticDiagnostics(program_3.getSourceFile("f2.ts"));
|
||||
assert(program_3Diagnostics.length === expectedErrors, `typerefs2 was unused, so diagnostics should be unaffected.`);
|
||||
assert.lengthOf(program_3Diagnostics, expectedErrors, `typerefs2 was unused, so diagnostics should be unaffected.`);
|
||||
|
||||
assert.deepEqual(program_3.host.getTrace(), [
|
||||
"======== Resolving module './b1' from 'f1.ts'. ========",
|
||||
@@ -684,7 +692,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_4Diagnostics = program_4.getSemanticDiagnostics(program_4.getSourceFile("f2.ts"));
|
||||
assert(program_4Diagnostics.length === expectedErrors, `a1.ts was unused, so diagnostics should be unaffected.`);
|
||||
assert.lengthOf(program_4Diagnostics, expectedErrors, `a1.ts was unused, so diagnostics should be unaffected.`);
|
||||
|
||||
assert.deepEqual(program_4.host.getTrace(), [
|
||||
"======== Resolving module './b1' from 'f1.ts'. ========",
|
||||
@@ -708,7 +716,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_5Diagnostics = program_5.getSemanticDiagnostics(program_5.getSourceFile("f2.ts"));
|
||||
assert(program_5Diagnostics.length === ++expectedErrors, `import of BB in f1 fails. BB is of type any. Add one error`);
|
||||
assert.lengthOf(program_5Diagnostics, ++expectedErrors, `import of BB in f1 fails. BB is of type any. Add one error`);
|
||||
|
||||
assert.deepEqual(program_5.host.getTrace(), [
|
||||
"======== Resolving module './b1' from 'f1.ts'. ========",
|
||||
@@ -725,7 +733,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_6Diagnostics = program_6.getSemanticDiagnostics(program_6.getSourceFile("f2.ts"));
|
||||
assert(program_6Diagnostics.length === expectedErrors, `import of BB in f1 fails.`);
|
||||
assert.lengthOf(program_6Diagnostics, expectedErrors, `import of BB in f1 fails.`);
|
||||
|
||||
assert.deepEqual(program_6.host.getTrace(), [
|
||||
"======== Resolving module './b1' from 'f1.ts'. ========",
|
||||
@@ -749,7 +757,7 @@ namespace ts {
|
||||
|
||||
{
|
||||
const program_7Diagnostics = program_7.getSemanticDiagnostics(program_7.getSourceFile("f2.ts"));
|
||||
assert(program_7Diagnostics.length === expectedErrors, `removing import is noop with respect to program, so no change in diagnostics.`);
|
||||
assert.lengthOf(program_7Diagnostics, expectedErrors, `removing import is noop with respect to program, so no change in diagnostics.`);
|
||||
|
||||
assert.deepEqual(program_7.host.getTrace(), [
|
||||
"======== Resolving type reference directive 'typerefs2', containing file 'f2.ts', root directory 'node_modules/@types'. ========",
|
||||
@@ -762,6 +770,98 @@ namespace ts {
|
||||
], "program_7 should reuse module resolutions in f2 since it is unchanged");
|
||||
}
|
||||
});
|
||||
|
||||
describe("redirects", () => {
|
||||
const axIndex = "/node_modules/a/node_modules/x/index.d.ts";
|
||||
const axPackage = "/node_modules/a/node_modules/x/package.json";
|
||||
const bxIndex = "/node_modules/b/node_modules/x/index.d.ts";
|
||||
const bxPackage = "/node_modules/b/node_modules/x/package.json";
|
||||
const root = "/a.ts";
|
||||
const compilerOptions = { target, moduleResolution: ModuleResolutionKind.NodeJs };
|
||||
|
||||
function createRedirectProgram(options?: { bText: string, bVersion: string }): ProgramWithSourceTexts {
|
||||
const files: NamedSourceText[] = [
|
||||
{
|
||||
name: "/node_modules/a/index.d.ts",
|
||||
text: SourceText.New("", 'import X from "x";', "export function a(x: X): void;"),
|
||||
},
|
||||
{
|
||||
name: axIndex,
|
||||
text: SourceText.New("", "", "export default class X { private x: number; }"),
|
||||
},
|
||||
{
|
||||
name: axPackage,
|
||||
text: SourceText.New("", "", JSON.stringify({ name: "x", version: "1.2.3" })),
|
||||
},
|
||||
{
|
||||
name: "/node_modules/b/index.d.ts",
|
||||
text: SourceText.New("", 'import X from "x";', "export const b: X;"),
|
||||
},
|
||||
{
|
||||
name: bxIndex,
|
||||
text: SourceText.New("", "", options ? options.bText : "export default class X { private x: number; }"),
|
||||
},
|
||||
{
|
||||
name: bxPackage,
|
||||
text: SourceText.New("", "", JSON.stringify({ name: "x", version: options ? options.bVersion : "1.2.3" })),
|
||||
},
|
||||
{
|
||||
name: root,
|
||||
text: SourceText.New("", 'import { a } from "a"; import { b } from "b";', "a(b)"),
|
||||
},
|
||||
];
|
||||
|
||||
return newProgram(files, [root], compilerOptions);
|
||||
}
|
||||
|
||||
function updateRedirectProgram(program: ProgramWithSourceTexts, updater: (files: NamedSourceText[]) => void): ProgramWithSourceTexts {
|
||||
return updateProgram(program, [root], compilerOptions, updater);
|
||||
}
|
||||
|
||||
it("No changes -> redirect not broken", () => {
|
||||
const program_1 = createRedirectProgram();
|
||||
|
||||
const program_2 = updateRedirectProgram(program_1, files => {
|
||||
updateProgramText(files, root, "const x = 1;");
|
||||
});
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Completely);
|
||||
assert.deepEqual(program_2.getSemanticDiagnostics(), emptyArray);
|
||||
});
|
||||
|
||||
it("Target changes -> redirect broken", () => {
|
||||
const program_1 = createRedirectProgram();
|
||||
assert.deepEqual(program_1.getSemanticDiagnostics(), emptyArray);
|
||||
|
||||
const program_2 = updateRedirectProgram(program_1, files => {
|
||||
updateProgramText(files, axIndex, "export default class X { private x: number; private y: number; }");
|
||||
updateProgramText(files, axPackage, JSON.stringify('{ name: "x", version: "1.2.4" }'));
|
||||
});
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
assert.lengthOf(program_2.getSemanticDiagnostics(), 1);
|
||||
});
|
||||
|
||||
it("Underlying changes -> redirect broken", () => {
|
||||
const program_1 = createRedirectProgram();
|
||||
|
||||
const program_2 = updateRedirectProgram(program_1, files => {
|
||||
updateProgramText(files, bxIndex, "export default class X { private x: number; private y: number; }");
|
||||
updateProgramText(files, bxPackage, JSON.stringify({ name: "x", version: "1.2.4" }));
|
||||
});
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
assert.lengthOf(program_2.getSemanticDiagnostics(), 1);
|
||||
});
|
||||
|
||||
it("Previously duplicate packages -> program structure not reused", () => {
|
||||
const program_1 = createRedirectProgram({ bVersion: "1.2.4", bText: "export = class X { private x: number; }" });
|
||||
|
||||
const program_2 = updateRedirectProgram(program_1, files => {
|
||||
updateProgramText(files, bxIndex, "export default class X { private x: number; }");
|
||||
updateProgramText(files, bxPackage, JSON.stringify({ name: "x", version: "1.2.3" }));
|
||||
});
|
||||
assert.equal(program_1.structureIsReused, StructureIsReused.Not);
|
||||
assert.deepEqual(program_2.getSemanticDiagnostics(), []);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("host is optional", () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts.server {
|
||||
newLine: "\n",
|
||||
useCaseSensitiveFileNames: true,
|
||||
write(s): void { lastWrittenToHost = s; },
|
||||
readFile(): string { return void 0; },
|
||||
readFile: () => undefined,
|
||||
writeFile: noop,
|
||||
resolvePath(): string { return void 0; },
|
||||
fileExists: () => false,
|
||||
@@ -28,18 +28,6 @@ namespace ts.server {
|
||||
createHash: Harness.LanguageService.mockHash,
|
||||
};
|
||||
|
||||
const mockLogger: Logger = {
|
||||
close: noop,
|
||||
hasLevel(): boolean { return false; },
|
||||
loggingEnabled(): boolean { return false; },
|
||||
perftrc: noop,
|
||||
info: noop,
|
||||
startGroup: noop,
|
||||
endGroup: noop,
|
||||
msg: noop,
|
||||
getLogFileName: (): string => undefined
|
||||
};
|
||||
|
||||
class TestSession extends Session {
|
||||
getProjectService() {
|
||||
return this.projectService;
|
||||
@@ -55,10 +43,11 @@ namespace ts.server {
|
||||
host: mockHost,
|
||||
cancellationToken: nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: mockLogger,
|
||||
logger: projectSystem.nullLogger,
|
||||
canUseEvents: true
|
||||
};
|
||||
return new TestSession(opts);
|
||||
@@ -93,14 +82,15 @@ namespace ts.server {
|
||||
|
||||
session.executeCommand(req);
|
||||
|
||||
expect(lastSent).to.deep.equal(<protocol.Response>{
|
||||
const expected: protocol.Response = {
|
||||
command: CommandNames.Unknown,
|
||||
type: "response",
|
||||
seq: 0,
|
||||
message: "Unrecognized JSON command: foobar",
|
||||
request_seq: 0,
|
||||
success: false
|
||||
});
|
||||
};
|
||||
expect(lastSent).to.deep.equal(expected);
|
||||
});
|
||||
it("should return a tuple containing the response and if a response is required on success", () => {
|
||||
const req: protocol.ConfigureRequest = {
|
||||
@@ -405,10 +395,11 @@ namespace ts.server {
|
||||
host: mockHost,
|
||||
cancellationToken: nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: mockLogger,
|
||||
logger: projectSystem.nullLogger,
|
||||
canUseEvents: true
|
||||
});
|
||||
this.addProtocolHandler(this.customHandler, () => {
|
||||
@@ -472,10 +463,11 @@ namespace ts.server {
|
||||
host: mockHost,
|
||||
cancellationToken: nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: mockLogger,
|
||||
logger: projectSystem.nullLogger,
|
||||
canUseEvents: true
|
||||
});
|
||||
this.addProtocolHandler("echo", (req: protocol.Request) => ({
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("Symbol Walker", () => {
|
||||
function test(description: string, source: string, verifier: (file: SourceFile, checker: TypeChecker) => void) {
|
||||
it(description, () => {
|
||||
let {result} = Harness.Compiler.compileFiles([{
|
||||
unitName: "main.ts",
|
||||
content: source
|
||||
}], [], {}, {}, "/");
|
||||
let file = result.program.getSourceFile("main.ts");
|
||||
let checker = result.program.getTypeChecker();
|
||||
verifier(file, checker);
|
||||
|
||||
result = undefined;
|
||||
file = undefined;
|
||||
checker = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
test("can be created", `
|
||||
interface Bar {
|
||||
x: number;
|
||||
y: number;
|
||||
history: Bar[];
|
||||
}
|
||||
export default function foo(a: number, b: Bar): void {}`, (file, checker) => {
|
||||
let foundCount = 0;
|
||||
let stdLibRefSymbols = 0;
|
||||
const expectedSymbols = ["default", "a", "b", "Bar", "x", "y", "history"];
|
||||
const walker = checker.getSymbolWalker(symbol => {
|
||||
const isStdLibSymbol = forEach(symbol.declarations, d => {
|
||||
return getSourceFileOfNode(d).hasNoDefaultLib;
|
||||
});
|
||||
if (isStdLibSymbol) {
|
||||
stdLibRefSymbols++;
|
||||
return false; // Don't traverse into the stdlib. That's unnecessary for this test.
|
||||
}
|
||||
assert.equal(symbol.name, expectedSymbols[foundCount]);
|
||||
foundCount++;
|
||||
return true;
|
||||
});
|
||||
const symbols = checker.getExportsOfModule(file.symbol);
|
||||
for (const symbol of symbols) {
|
||||
walker.walkSymbol(symbol);
|
||||
}
|
||||
assert.equal(foundCount, expectedSymbols.length);
|
||||
assert.equal(stdLibRefSymbols, 1); // Expect 1 stdlib entry symbol - the implicit Array referenced by Bar.history
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace ts {
|
||||
return find(n);
|
||||
|
||||
function find(node: Node): Node {
|
||||
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.text === name) {
|
||||
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.escapedText === name) {
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
@@ -67,12 +67,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function flattenNodes(n: Node) {
|
||||
const data: (Node | NodeArray<any>)[] = [];
|
||||
const data: (Node | NodeArray<Node>)[] = [];
|
||||
walk(n);
|
||||
return data;
|
||||
|
||||
function walk(n: Node | Node[]): void {
|
||||
data.push(<any>n);
|
||||
function walk(n: Node | NodeArray<Node>): void {
|
||||
data.push(n);
|
||||
return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace ts {
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
context.onSubstituteNode = (hint, node) => {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (hint === EmitHint.Expression && node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "undefined") {
|
||||
if (hint === EmitHint.Expression && isIdentifier(node) && node.escapedText === "undefined") {
|
||||
node = createPartiallyEmittedExpression(
|
||||
addSyntheticTrailingComment(
|
||||
setTextRange(
|
||||
@@ -26,7 +26,7 @@ namespace ts {
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
context.onSubstituteNode = (hint, node) => {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "oldName") {
|
||||
if (isIdentifier(node) && node.escapedText === "oldName") {
|
||||
node = setTextRange(createIdentifier("newName"), node);
|
||||
}
|
||||
return node;
|
||||
@@ -74,6 +74,70 @@ namespace ts {
|
||||
}
|
||||
}).outputText;
|
||||
});
|
||||
|
||||
testBaseline("rewrittenNamespace", () => {
|
||||
return ts.transpileModule(`namespace Reflect { const x = 1; }`, {
|
||||
transformers: {
|
||||
before: [forceNamespaceRewrite],
|
||||
},
|
||||
compilerOptions: {
|
||||
newLine: NewLineKind.CarriageReturnLineFeed,
|
||||
}
|
||||
}).outputText;
|
||||
});
|
||||
|
||||
testBaseline("rewrittenNamespaceFollowingClass", () => {
|
||||
return ts.transpileModule(`
|
||||
class C { foo = 10; static bar = 20 }
|
||||
namespace C { export let x = 10; }
|
||||
`, {
|
||||
transformers: {
|
||||
before: [forceNamespaceRewrite],
|
||||
},
|
||||
compilerOptions: {
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
newLine: NewLineKind.CarriageReturnLineFeed,
|
||||
}
|
||||
}).outputText;
|
||||
});
|
||||
|
||||
testBaseline("synthesizedClassAndNamespaceCombination", () => {
|
||||
return ts.transpileModule("", {
|
||||
transformers: {
|
||||
before: [replaceWithClassAndNamespace],
|
||||
},
|
||||
compilerOptions: {
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
newLine: NewLineKind.CarriageReturnLineFeed,
|
||||
}
|
||||
}).outputText;
|
||||
|
||||
function replaceWithClassAndNamespace() {
|
||||
return (sourceFile: ts.SourceFile) => {
|
||||
const result = getMutableClone(sourceFile);
|
||||
result.statements = ts.createNodeArray([
|
||||
ts.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined),
|
||||
ts.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()]))
|
||||
]);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function forceNamespaceRewrite(context: ts.TransformationContext) {
|
||||
return (sourceFile: ts.SourceFile): ts.SourceFile => {
|
||||
return visitNode(sourceFile);
|
||||
|
||||
function visitNode<T extends ts.Node>(node: T): T {
|
||||
if (node.kind === ts.SyntaxKind.ModuleBlock) {
|
||||
const block = node as T & ts.ModuleBlock;
|
||||
const statements = ts.createNodeArray([...block.statements]);
|
||||
return ts.updateModuleBlock(block, statements) as typeof block;
|
||||
}
|
||||
return ts.visitEachChild(node, visitNode, context);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,28 @@ namespace ts.projectSystem {
|
||||
})
|
||||
};
|
||||
|
||||
const customSafeList = {
|
||||
path: <Path>"/typeMapList.json",
|
||||
content: JSON.stringify({
|
||||
"quack": {
|
||||
"match": "/duckquack-(\\d+)\\.min\\.js",
|
||||
"types": ["duck-types"]
|
||||
export const customTypesMap = {
|
||||
path: <Path>"/typesMap.json",
|
||||
content: `{
|
||||
"typesMap": {
|
||||
"jquery": {
|
||||
"match": "jquery(-(\\\\.?\\\\d+)+)?(\\\\.intellisense)?(\\\\.min)?\\\\.js$",
|
||||
"types": ["jquery"]
|
||||
},
|
||||
"quack": {
|
||||
"match": "/duckquack-(\\\\d+)\\\\.min\\\\.js",
|
||||
"types": ["duck-types"]
|
||||
}
|
||||
},
|
||||
})
|
||||
"simpleMap": {
|
||||
"Bacon": "baconjs",
|
||||
"bliss": "blissfuljs",
|
||||
"commander": "commander",
|
||||
"cordova": "cordova",
|
||||
"react": "react",
|
||||
"lodash": "lodash"
|
||||
}
|
||||
}`
|
||||
};
|
||||
|
||||
export interface PostExecAction {
|
||||
@@ -34,18 +48,18 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
export const nullLogger: server.Logger = {
|
||||
close: () => void 0,
|
||||
hasLevel: () => void 0,
|
||||
close: noop,
|
||||
hasLevel: () => false,
|
||||
loggingEnabled: () => false,
|
||||
perftrc: () => void 0,
|
||||
info: () => void 0,
|
||||
startGroup: () => void 0,
|
||||
endGroup: () => void 0,
|
||||
msg: () => void 0,
|
||||
perftrc: noop,
|
||||
info: noop,
|
||||
msg: noop,
|
||||
startGroup: noop,
|
||||
endGroup: noop,
|
||||
getLogFileName: (): string => undefined
|
||||
};
|
||||
|
||||
export const { content: libFileContent } = Harness.getDefaultLibraryFile(Harness.IO);
|
||||
const { content: libFileContent } = Harness.getDefaultLibraryFile(Harness.IO);
|
||||
export const libFile: FileOrFolder = {
|
||||
path: "/a/lib/lib.d.ts",
|
||||
content: libFileContent
|
||||
@@ -59,7 +73,7 @@ namespace ts.projectSystem {
|
||||
installTypingHost: server.ServerHost,
|
||||
readonly typesRegistry = createMap<void>(),
|
||||
log?: TI.Log) {
|
||||
super(installTypingHost, globalTypingsCacheLocation, safeList.path, throttleLimit, log);
|
||||
super(installTypingHost, globalTypingsCacheLocation, safeList.path, customTypesMap.path, throttleLimit, log);
|
||||
}
|
||||
|
||||
protected postExecActions: PostExecAction[] = [];
|
||||
@@ -118,7 +132,7 @@ namespace ts.projectSystem {
|
||||
return JSON.stringify({ dependencies });
|
||||
}
|
||||
|
||||
export function getExecutingFilePathFromLibFile(): string {
|
||||
function getExecutingFilePathFromLibFile(): string {
|
||||
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
|
||||
}
|
||||
|
||||
@@ -130,7 +144,7 @@ namespace ts.projectSystem {
|
||||
return map(fileNames, toExternalFile);
|
||||
}
|
||||
|
||||
export class TestServerEventManager {
|
||||
class TestServerEventManager {
|
||||
public events: server.ProjectServiceEvent[] = [];
|
||||
|
||||
handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => {
|
||||
@@ -143,7 +157,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestServerHostCreationParameters {
|
||||
interface TestServerHostCreationParameters {
|
||||
useCaseSensitiveFileNames?: boolean;
|
||||
executingFilePath?: string;
|
||||
currentDirectory?: string;
|
||||
@@ -186,26 +200,31 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler, cancellationToken?: server.ServerCancellationToken, throttleWaitMilliseconds?: number) {
|
||||
if (typingsInstaller === undefined) {
|
||||
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
|
||||
export function createSession(host: server.ServerHost, opts: Partial<server.SessionOptions> = {}) {
|
||||
if (opts.typingsInstaller === undefined) {
|
||||
opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/ 5, host);
|
||||
}
|
||||
const opts: server.SessionOptions = {
|
||||
|
||||
if (opts.eventHandler !== undefined) {
|
||||
opts.canUseEvents = true;
|
||||
}
|
||||
|
||||
const sessionOptions: server.SessionOptions = {
|
||||
host,
|
||||
cancellationToken: cancellationToken || server.nullCancellationToken,
|
||||
cancellationToken: server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
typingsInstaller,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: nullLogger,
|
||||
canUseEvents: projectServiceEventHandler !== undefined,
|
||||
eventHandler: projectServiceEventHandler,
|
||||
throttleWaitMilliseconds
|
||||
canUseEvents: false
|
||||
};
|
||||
return new TestSession(opts);
|
||||
|
||||
return new TestSession({ ...sessionOptions, ...opts });
|
||||
}
|
||||
|
||||
export interface CreateProjectServiceParameters {
|
||||
interface CreateProjectServiceParameters {
|
||||
cancellationToken?: HostCancellationToken;
|
||||
logger?: server.Logger;
|
||||
useSingleInferredProject?: boolean;
|
||||
@@ -216,9 +235,17 @@ namespace ts.projectSystem {
|
||||
|
||||
export class TestProjectService extends server.ProjectService {
|
||||
constructor(host: server.ServerHost, logger: server.Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean,
|
||||
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler) {
|
||||
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler, opts: Partial<server.ProjectServiceOptions> = {}) {
|
||||
super({
|
||||
host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler
|
||||
host,
|
||||
logger,
|
||||
cancellationToken,
|
||||
useSingleInferredProject,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller,
|
||||
typesMapLocation: customTypesMap.path,
|
||||
eventHandler,
|
||||
...opts
|
||||
});
|
||||
}
|
||||
|
||||
@@ -253,15 +280,15 @@ namespace ts.projectSystem {
|
||||
entries: FSEntry[];
|
||||
}
|
||||
|
||||
export function isFolder(s: FSEntry): s is Folder {
|
||||
function isFolder(s: FSEntry): s is Folder {
|
||||
return isArray((<Folder>s).entries);
|
||||
}
|
||||
|
||||
export function isFile(s: FSEntry): s is File {
|
||||
function isFile(s: FSEntry): s is File {
|
||||
return typeof (<File>s).content === "string";
|
||||
}
|
||||
|
||||
export function addFolder(fullPath: string, toPath: (s: string) => Path, fs: Map<FSEntry>): Folder {
|
||||
function addFolder(fullPath: string, toPath: (s: string) => Path, fs: Map<FSEntry>): Folder {
|
||||
const path = toPath(fullPath);
|
||||
if (fs.has(path)) {
|
||||
Debug.assert(isFolder(fs.get(path)));
|
||||
@@ -279,29 +306,29 @@ namespace ts.projectSystem {
|
||||
return entry;
|
||||
}
|
||||
|
||||
export function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
|
||||
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
|
||||
assert.equal(map.size, expectedKeys.length, `${caption}: incorrect size of map`);
|
||||
for (const name of expectedKeys) {
|
||||
assert.isTrue(map.has(name), `${caption} is expected to contain ${name}, actual keys: ${arrayFrom(map.keys())}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function checkFileNames(caption: string, actualFileNames: string[], expectedFileNames: string[]) {
|
||||
function checkFileNames(caption: string, actualFileNames: string[], expectedFileNames: string[]) {
|
||||
assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected ${JSON.stringify(expectedFileNames)}, got ${actualFileNames}`);
|
||||
for (const f of expectedFileNames) {
|
||||
assert.isTrue(contains(actualFileNames, f), `${caption}: expected to find ${f} in ${JSON.stringify(actualFileNames)}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) {
|
||||
function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) {
|
||||
assert.equal(projectService.configuredProjects.length, expected, `expected ${expected} configured project(s)`);
|
||||
}
|
||||
|
||||
export function checkNumberOfExternalProjects(projectService: server.ProjectService, expected: number) {
|
||||
function checkNumberOfExternalProjects(projectService: server.ProjectService, expected: number) {
|
||||
assert.equal(projectService.externalProjects.length, expected, `expected ${expected} external project(s)`);
|
||||
}
|
||||
|
||||
export function checkNumberOfInferredProjects(projectService: server.ProjectService, expected: number) {
|
||||
function checkNumberOfInferredProjects(projectService: server.ProjectService, expected: number) {
|
||||
assert.equal(projectService.inferredProjects.length, expected, `expected ${expected} inferred project(s)`);
|
||||
}
|
||||
|
||||
@@ -315,7 +342,7 @@ namespace ts.projectSystem {
|
||||
checkMapKeys("watchedFiles", host.watchedFiles, expectedFiles);
|
||||
}
|
||||
|
||||
export function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[]) {
|
||||
function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[]) {
|
||||
checkMapKeys("watchedDirectories", host.watchedDirectories, expectedDirectories);
|
||||
}
|
||||
|
||||
@@ -323,11 +350,11 @@ namespace ts.projectSystem {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, actual files`, project.getFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
export function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) {
|
||||
function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles);
|
||||
}
|
||||
|
||||
export class Callbacks {
|
||||
class Callbacks {
|
||||
private map: TimeOutCallback[] = [];
|
||||
private nextId = 1;
|
||||
|
||||
@@ -363,7 +390,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
export type TimeOutCallback = () => any;
|
||||
type TimeOutCallback = () => any;
|
||||
|
||||
export class TestServerHost implements server.ServerHost {
|
||||
args: string[] = [];
|
||||
@@ -438,24 +465,22 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[] {
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, (dir) => {
|
||||
const result: FileSystemEntries = {
|
||||
directories: [],
|
||||
files: []
|
||||
};
|
||||
const directories: string[] = [];
|
||||
const files: string[] = [];
|
||||
const dirEntry = this.fs.get(this.toPath(dir));
|
||||
if (isFolder(dirEntry)) {
|
||||
dirEntry.entries.forEach((entry) => {
|
||||
if (isFolder(entry)) {
|
||||
result.directories.push(entry.fullPath);
|
||||
directories.push(entry.fullPath);
|
||||
}
|
||||
else if (isFile(entry)) {
|
||||
result.files.push(entry.fullPath);
|
||||
files.push(entry.fullPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
return { directories, files };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -563,7 +588,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
clearOutput() {
|
||||
this.output.length = 0;
|
||||
clear(this.output);
|
||||
}
|
||||
|
||||
readonly readFile = (s: string) => (<File>this.fs.get(this.toPath(s))).content;
|
||||
@@ -634,7 +659,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
describe("tsserver-project-system", () => {
|
||||
describe("tsserverProjectSystem", () => {
|
||||
const commonFile1: FileOrFolder = {
|
||||
path: "/a/b/commonFile1.ts",
|
||||
content: "let x = 1"
|
||||
@@ -1481,9 +1506,8 @@ namespace ts.projectSystem {
|
||||
path: "/lib/duckquack-3.min.js",
|
||||
content: "whoa do @@ not parse me ok thanks!!!"
|
||||
};
|
||||
const host = createServerHost([customSafeList, file1, office]);
|
||||
const host = createServerHost([file1, office, customTypesMap]);
|
||||
const projectService = createProjectService(host);
|
||||
projectService.loadSafeList(customSafeList.path);
|
||||
try {
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, office.path]) });
|
||||
const proj = projectService.externalProjects[0];
|
||||
@@ -2233,13 +2257,16 @@ namespace ts.projectSystem {
|
||||
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
|
||||
let lastEvent: server.ProjectLanguageServiceStateEvent;
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
assert.equal(e.data.project.getProjectName(), config.path, "project name");
|
||||
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
assert.equal(e.data.project.getProjectName(), config.path, "project name");
|
||||
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
|
||||
});
|
||||
session.executeCommand(<protocol.OpenRequest>{
|
||||
seq: 0,
|
||||
@@ -2283,12 +2310,15 @@ namespace ts.projectSystem {
|
||||
host.getFileSize = (filePath: string) =>
|
||||
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
let lastEvent: server.ProjectLanguageServiceStateEvent;
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: e => {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||
return;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
|
||||
});
|
||||
session.executeCommand(<protocol.OpenRequest>{
|
||||
seq: 0,
|
||||
@@ -2334,6 +2364,50 @@ namespace ts.projectSystem {
|
||||
const navbar = projectService.externalProjects[0].getLanguageService(/*ensureSynchronized*/ false).getNavigationBarItems(f1.path);
|
||||
assert.equal(navbar[0].spans[0].length, f1.content.length);
|
||||
});
|
||||
|
||||
it("deleting config file opened from the external project works", () => {
|
||||
const site = {
|
||||
path: "/user/someuser/project/js/site.js",
|
||||
content: ""
|
||||
};
|
||||
const configFile = {
|
||||
path: "/user/someuser/project/tsconfig.json",
|
||||
content: "{}"
|
||||
};
|
||||
const projectFileName = "/user/someuser/project/WebApplication6.csproj";
|
||||
const host = createServerHost([libFile, site, configFile]);
|
||||
const projectService = createProjectService(host);
|
||||
|
||||
const externalProject: protocol.ExternalProject = {
|
||||
projectFileName,
|
||||
rootFiles: [toExternalFile(site.path), toExternalFile(configFile.path)],
|
||||
options: { allowJs: false },
|
||||
typeAcquisition: { "include": [] }
|
||||
};
|
||||
|
||||
projectService.openExternalProjects([externalProject]);
|
||||
|
||||
let knownProjects = projectService.synchronizeProjectList([]);
|
||||
checkNumberOfProjects(projectService, { configuredProjects: 1, externalProjects: 0, inferredProjects: 0 });
|
||||
|
||||
const configProject = projectService.configuredProjects[0];
|
||||
checkProjectActualFiles(configProject, [libFile.path]);
|
||||
|
||||
const diagnostics = configProject.getAllProjectErrors();
|
||||
assert.equal(diagnostics[0].code, Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
|
||||
|
||||
host.reloadFS([libFile, site]);
|
||||
host.triggerFileWatcherCallback(configFile.path, FileWatcherEventKind.Deleted);
|
||||
|
||||
knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info));
|
||||
checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 });
|
||||
|
||||
externalProject.rootFiles.length = 1;
|
||||
projectService.openExternalProjects([externalProject]);
|
||||
|
||||
checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 });
|
||||
checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Proper errors", () => {
|
||||
@@ -3028,7 +3102,10 @@ namespace ts.projectSystem {
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
|
||||
@@ -3055,7 +3132,10 @@ namespace ts.projectSystem {
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
});
|
||||
@@ -3074,7 +3154,10 @@ namespace ts.projectSystem {
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
|
||||
@@ -3463,6 +3546,93 @@ namespace ts.projectSystem {
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f.path]);
|
||||
});
|
||||
|
||||
it("inferred projects per project root", () => {
|
||||
const file1 = { path: "/a/file1.ts", content: "let x = 1;", projectRootPath: "/a" };
|
||||
const file2 = { path: "/a/file2.ts", content: "let y = 2;", projectRootPath: "/a" };
|
||||
const file3 = { path: "/b/file2.ts", content: "let x = 3;", projectRootPath: "/b" };
|
||||
const file4 = { path: "/c/file3.ts", content: "let z = 4;" };
|
||||
const host = createServerHost([file1, file2, file3, file4]);
|
||||
const session = createSession(host, {
|
||||
useSingleInferredProject: true,
|
||||
useInferredProjectPerProjectRoot: true
|
||||
});
|
||||
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: CommandNames.CompilerOptionsForInferredProjects,
|
||||
arguments: {
|
||||
options: {
|
||||
allowJs: true,
|
||||
target: ScriptTarget.ESNext
|
||||
}
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: CommandNames.CompilerOptionsForInferredProjects,
|
||||
arguments: {
|
||||
options: {
|
||||
allowJs: true,
|
||||
target: ScriptTarget.ES2015
|
||||
},
|
||||
projectRootPath: "/b"
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 3,
|
||||
type: "request",
|
||||
command: CommandNames.Open,
|
||||
arguments: {
|
||||
file: file1.path,
|
||||
fileContent: file1.content,
|
||||
scriptKindName: "JS",
|
||||
projectRootPath: file1.projectRootPath
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 4,
|
||||
type: "request",
|
||||
command: CommandNames.Open,
|
||||
arguments: {
|
||||
file: file2.path,
|
||||
fileContent: file2.content,
|
||||
scriptKindName: "JS",
|
||||
projectRootPath: file2.projectRootPath
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 5,
|
||||
type: "request",
|
||||
command: CommandNames.Open,
|
||||
arguments: {
|
||||
file: file3.path,
|
||||
fileContent: file3.content,
|
||||
scriptKindName: "JS",
|
||||
projectRootPath: file3.projectRootPath
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 6,
|
||||
type: "request",
|
||||
command: CommandNames.Open,
|
||||
arguments: {
|
||||
file: file4.path,
|
||||
fileContent: file4.content,
|
||||
scriptKindName: "JS"
|
||||
}
|
||||
});
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 3 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[1], [file1.path, file2.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]);
|
||||
assert.equal(projectService.inferredProjects[0].getCompilerOptions().target, ScriptTarget.ESNext);
|
||||
assert.equal(projectService.inferredProjects[1].getCompilerOptions().target, ScriptTarget.ESNext);
|
||||
assert.equal(projectService.inferredProjects[2].getCompilerOptions().target, ScriptTarget.ES2015);
|
||||
});
|
||||
});
|
||||
|
||||
describe("No overwrite emit error", () => {
|
||||
@@ -3656,7 +3826,7 @@ namespace ts.projectSystem {
|
||||
resetRequest: noop
|
||||
};
|
||||
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, /*projectServiceEventHandler*/ undefined, cancellationToken);
|
||||
const session = createSession(host, { cancellationToken });
|
||||
|
||||
expectedRequestId = session.getNextSeq();
|
||||
session.executeCommandSeq(<server.protocol.OpenRequest>{
|
||||
@@ -3696,7 +3866,11 @@ namespace ts.projectSystem {
|
||||
|
||||
const cancellationToken = new TestServerCancellationToken();
|
||||
const host = createServerHost([f1, config]);
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: () => { },
|
||||
cancellationToken
|
||||
});
|
||||
{
|
||||
session.executeCommandSeq(<protocol.OpenRequest>{
|
||||
command: "open",
|
||||
@@ -3829,7 +4003,12 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const cancellationToken = new TestServerCancellationToken(/*cancelAfterRequest*/ 3);
|
||||
const host = createServerHost([f1, config]);
|
||||
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken, /*throttleWaitMilliseconds*/ 0);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: () => { },
|
||||
cancellationToken,
|
||||
throttleWaitMilliseconds: 0
|
||||
});
|
||||
{
|
||||
session.executeCommandSeq(<protocol.OpenRequest>{
|
||||
command: "open",
|
||||
|
||||
@@ -44,6 +44,18 @@ namespace ts.projectSystem {
|
||||
});
|
||||
}
|
||||
|
||||
function trackingLogger(): { log(message: string): void, finish(): string[] } {
|
||||
const logs: string[] = [];
|
||||
return {
|
||||
log(message) {
|
||||
logs.push(message);
|
||||
},
|
||||
finish() {
|
||||
return logs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
import typingsName = TI.typingsName;
|
||||
|
||||
describe("local module", () => {
|
||||
@@ -310,7 +322,7 @@ namespace ts.projectSystem {
|
||||
content: "declare const lodash: { x: number }"
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const host = createServerHost([file1, file2, file3, customTypesMap]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { typesRegistry: createTypesRegistry("lodash", "react") });
|
||||
@@ -433,7 +445,7 @@ namespace ts.projectSystem {
|
||||
content: "declare const moment: { x: number }"
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file3, packageJson]);
|
||||
const host = createServerHost([file1, file2, file3, packageJson, customTypesMap]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { typesRegistry: createTypesRegistry("jquery", "commander", "moment", "express") });
|
||||
@@ -509,7 +521,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
|
||||
const typingFiles = [commander, express, jquery, moment, lodash];
|
||||
const host = createServerHost([lodashJs, commanderJs, file3, packageJson]);
|
||||
const host = createServerHost([lodashJs, commanderJs, file3, packageJson, customTypesMap]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { throttleLimit: 3, typesRegistry: createTypesRegistry("commander", "express", "jquery", "moment", "lodash") });
|
||||
@@ -588,7 +600,7 @@ namespace ts.projectSystem {
|
||||
typings: typingsName("gulp")
|
||||
};
|
||||
|
||||
const host = createServerHost([lodashJs, commanderJs, file3]);
|
||||
const host = createServerHost([lodashJs, commanderJs, file3, customTypesMap]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { throttleLimit: 1, typesRegistry: createTypesRegistry("commander", "jquery", "lodash", "cordova", "gulp", "grunt") });
|
||||
@@ -923,25 +935,26 @@ namespace ts.projectSystem {
|
||||
import * as cmd from "commander
|
||||
`
|
||||
};
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
const openRequest: server.protocol.OpenRequest = {
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "open",
|
||||
command: server.protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: f.path,
|
||||
fileContent: f.content
|
||||
}
|
||||
});
|
||||
};
|
||||
session.executeCommand(openRequest);
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
const proj = projectService.inferredProjects[0];
|
||||
const version1 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
|
||||
|
||||
// make a change that should not affect the structure of the program
|
||||
session.executeCommand(<server.protocol.ChangeRequest>{
|
||||
const changeRequest: server.protocol.ChangeRequest = {
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "change",
|
||||
command: server.protocol.CommandTypes.Change,
|
||||
arguments: {
|
||||
file: f.path,
|
||||
insertString: "\nlet x = 1;",
|
||||
@@ -950,7 +963,8 @@ namespace ts.projectSystem {
|
||||
endLine: 2,
|
||||
endOffset: 0
|
||||
}
|
||||
});
|
||||
};
|
||||
session.executeCommand(changeRequest);
|
||||
host.checkTimeoutQueueLength(1);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
|
||||
@@ -1015,6 +1029,8 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("discover typings", () => {
|
||||
const emptySafeList = emptyMap;
|
||||
|
||||
it("should use mappings from safe list", () => {
|
||||
const app = {
|
||||
path: "/a/b/app.js",
|
||||
@@ -1028,10 +1044,17 @@ namespace ts.projectSystem {
|
||||
path: "/a/b/chroma.min.js",
|
||||
content: ""
|
||||
};
|
||||
const cache = createMap<string>();
|
||||
|
||||
const safeList = createMapFromTemplate({ jquery: "jquery", chroma: "chroma-js" });
|
||||
|
||||
const host = createServerHost([app, jquery, chroma]);
|
||||
const result = JsTyping.discoverTypings(host, [app.path, jquery.path, chroma.path], getDirectoryPath(<Path>app.path), /*safeListPath*/ undefined, cache, { enable: true }, []);
|
||||
const logger = trackingLogger();
|
||||
const result = JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], getDirectoryPath(<Path>app.path), safeList, emptyMap, { enable: true }, emptyArray);
|
||||
assert.deepEqual(logger.finish(), [
|
||||
'Inferred typings from file names: ["jquery","chroma-js"]',
|
||||
"Inferred typings from unresolved imports: []",
|
||||
'Result: {"cachedTypingPaths":[],"newTypingNames":["jquery","chroma-js"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}',
|
||||
]);
|
||||
assert.deepEqual(result.newTypingNames, ["jquery", "chroma-js"]);
|
||||
});
|
||||
|
||||
@@ -1044,7 +1067,12 @@ namespace ts.projectSystem {
|
||||
const cache = createMap<string>();
|
||||
|
||||
for (const name of JsTyping.nodeCoreModuleList) {
|
||||
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enable: true }, [name, "somename"]);
|
||||
const logger = trackingLogger();
|
||||
const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(<Path>f.path), emptySafeList, cache, { enable: true }, [name, "somename"]);
|
||||
assert.deepEqual(logger.finish(), [
|
||||
'Inferred typings from unresolved imports: ["node","somename"]',
|
||||
'Result: {"cachedTypingPaths":[],"newTypingNames":["node","somename"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}',
|
||||
]);
|
||||
assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]);
|
||||
}
|
||||
});
|
||||
@@ -1060,7 +1088,12 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([f, node]);
|
||||
const cache = createMapFromTemplate<string>({ "node": node.path });
|
||||
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enable: true }, ["fs", "bar"]);
|
||||
const logger = trackingLogger();
|
||||
const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(<Path>f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"]);
|
||||
assert.deepEqual(logger.finish(), [
|
||||
'Inferred typings from unresolved imports: ["node","bar"]',
|
||||
'Result: {"cachedTypingPaths":["/a/b/node.d.ts"],"newTypingNames":["bar"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}',
|
||||
]);
|
||||
assert.deepEqual(result.cachedTypingPaths, [node.path]);
|
||||
assert.deepEqual(result.newTypingNames, ["bar"]);
|
||||
});
|
||||
@@ -1080,7 +1113,14 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([app, a, b]);
|
||||
const cache = createMap<string>();
|
||||
const result = JsTyping.discoverTypings(host, [app.path], getDirectoryPath(<Path>app.path), /*safeListPath*/ undefined, cache, { enable: true }, /*unresolvedImports*/ []);
|
||||
const logger = trackingLogger();
|
||||
const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(<Path>app.path), emptySafeList, cache, { enable: true }, /*unresolvedImports*/ []);
|
||||
assert.deepEqual(logger.finish(), [
|
||||
'Searching for typing names in /node_modules; all files: ["/node_modules/a/package.json"]',
|
||||
' Found package names: ["a"]',
|
||||
"Inferred typings from unresolved imports: []",
|
||||
'Result: {"cachedTypingPaths":[],"newTypingNames":["a"],"filesToWatch":["/bower_components","/node_modules"]}',
|
||||
]);
|
||||
assert.deepEqual(result, {
|
||||
cachedTypingPaths: [],
|
||||
newTypingNames: ["a"], // But not "b"
|
||||
|
||||
@@ -7,8 +7,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function lineColToPosition(lineIndex: server.LineIndex, line: number, col: number) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(line);
|
||||
return (lineInfo.offset + col - 1);
|
||||
return lineIndex.absolutePositionOfStartOfLine(line) + (col - 1);
|
||||
}
|
||||
|
||||
function validateEdit(lineIndex: server.LineIndex, sourceText: string, position: number, deleteLength: number, insertString: string): void {
|
||||
@@ -50,6 +49,12 @@ var q:Point=<Point>p;`;
|
||||
validateEditAtLineCharIndex = undefined;
|
||||
});
|
||||
|
||||
it("handles empty lines array", () => {
|
||||
const lineIndex = new server.LineIndex();
|
||||
lineIndex.load([]);
|
||||
assert.deepEqual(lineIndex.positionToLineOffset(0), { line: 1, offset: 1 });
|
||||
});
|
||||
|
||||
it(`change 9 1 0 1 {"y"}`, () => {
|
||||
validateEditAtLineCharIndex(9, 1, 0, "y");
|
||||
});
|
||||
@@ -298,20 +303,17 @@ and grew 1cm per day`;
|
||||
|
||||
it("Line/offset from pos", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
const lp = lineIndex.charOffsetToLineNumberAndPos(rsa[i]);
|
||||
const lp = lineIndex.positionToLineOffset(rsa[i]);
|
||||
const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
|
||||
assert.equal(lac.line + 1, lp.line, "Line number mismatch " + (lac.line + 1) + " " + lp.line + " " + i);
|
||||
assert.equal(lac.character, (lp.offset), "Charachter offset mismatch " + lac.character + " " + lp.offset + " " + i);
|
||||
assert.equal(lac.character, lp.offset - 1, "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i);
|
||||
}
|
||||
});
|
||||
|
||||
it("Start pos from line", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
for (let j = 0; j < lines.length; j++) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(j + 1);
|
||||
const lineIndexOffset = lineInfo.offset;
|
||||
const lineMapOffset = lineMap[j];
|
||||
assert.equal(lineIndexOffset, lineMapOffset);
|
||||
assert.equal(lineIndex.absolutePositionOfStartOfLine(j + 1), lineMap[j]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -209,14 +209,14 @@ namespace Utils {
|
||||
}
|
||||
}
|
||||
|
||||
readFile(path: string): string {
|
||||
readFile(path: string): string | undefined {
|
||||
const value = this.traversePath(path);
|
||||
if (value && value.isFile()) {
|
||||
return value.content.content;
|
||||
}
|
||||
}
|
||||
|
||||
readDirectory(path: string, extensions: string[], excludes: string[], includes: string[], depth: number) {
|
||||
readDirectory(path: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string>, includes: ReadonlyArray<string>, depth: number) {
|
||||
return ts.matchFiles(path, extensions, excludes, includes, this.useCaseSensitiveFileNames, this.currentDirectory, depth, (path: string) => this.getAccessibleFileSystemEntries(path));
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+170
-109
@@ -4,11 +4,11 @@
|
||||
/////////////////////////////
|
||||
|
||||
interface Account {
|
||||
displayName?: string;
|
||||
id?: string;
|
||||
displayName: string;
|
||||
id: string;
|
||||
imageURL?: string;
|
||||
name?: string;
|
||||
rpDisplayName?: string;
|
||||
rpDisplayName: string;
|
||||
}
|
||||
|
||||
interface Algorithm {
|
||||
@@ -35,11 +35,11 @@ interface CacheQueryOptions {
|
||||
}
|
||||
|
||||
interface ClientData {
|
||||
challenge?: string;
|
||||
challenge: string;
|
||||
extensions?: WebAuthnExtensions;
|
||||
hashAlg?: string | Algorithm;
|
||||
origin?: string;
|
||||
rpId?: string;
|
||||
hashAlg: string | Algorithm;
|
||||
origin: string;
|
||||
rpId: string;
|
||||
tokenBinding?: string;
|
||||
}
|
||||
|
||||
@@ -87,9 +87,9 @@ interface CustomEventInit extends EventInit {
|
||||
}
|
||||
|
||||
interface DeviceAccelerationDict {
|
||||
x?: number;
|
||||
y?: number;
|
||||
z?: number;
|
||||
x?: number | null;
|
||||
y?: number | null;
|
||||
z?: number | null;
|
||||
}
|
||||
|
||||
interface DeviceLightEventInit extends EventInit {
|
||||
@@ -97,30 +97,30 @@ interface DeviceLightEventInit extends EventInit {
|
||||
}
|
||||
|
||||
interface DeviceMotionEventInit extends EventInit {
|
||||
acceleration?: DeviceAccelerationDict;
|
||||
accelerationIncludingGravity?: DeviceAccelerationDict;
|
||||
interval?: number;
|
||||
rotationRate?: DeviceRotationRateDict;
|
||||
acceleration?: DeviceAccelerationDict | null;
|
||||
accelerationIncludingGravity?: DeviceAccelerationDict | null;
|
||||
interval?: number | null;
|
||||
rotationRate?: DeviceRotationRateDict | null;
|
||||
}
|
||||
|
||||
interface DeviceOrientationEventInit extends EventInit {
|
||||
absolute?: boolean;
|
||||
alpha?: number;
|
||||
beta?: number;
|
||||
gamma?: number;
|
||||
alpha?: number | null;
|
||||
beta?: number | null;
|
||||
gamma?: number | null;
|
||||
}
|
||||
|
||||
interface DeviceRotationRateDict {
|
||||
alpha?: number;
|
||||
beta?: number;
|
||||
gamma?: number;
|
||||
alpha?: number | null;
|
||||
beta?: number | null;
|
||||
gamma?: number | null;
|
||||
}
|
||||
|
||||
interface DOMRectInit {
|
||||
height?: any;
|
||||
width?: any;
|
||||
x?: any;
|
||||
y?: any;
|
||||
height?: number;
|
||||
width?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
}
|
||||
|
||||
interface DoubleRange {
|
||||
@@ -161,15 +161,15 @@ interface EventModifierInit extends UIEventInit {
|
||||
}
|
||||
|
||||
interface ExceptionInformation {
|
||||
domain?: string;
|
||||
domain?: string | null;
|
||||
}
|
||||
|
||||
interface FocusEventInit extends UIEventInit {
|
||||
relatedTarget?: EventTarget;
|
||||
relatedTarget?: EventTarget | null;
|
||||
}
|
||||
|
||||
interface FocusNavigationEventInit extends EventInit {
|
||||
navigationReason?: string;
|
||||
navigationReason?: string | null;
|
||||
originHeight?: number;
|
||||
originLeft?: number;
|
||||
originTop?: number;
|
||||
@@ -184,7 +184,7 @@ interface FocusNavigationOrigin {
|
||||
}
|
||||
|
||||
interface GamepadEventInit extends EventInit {
|
||||
gamepad?: Gamepad;
|
||||
gamepad?: Gamepad | null;
|
||||
}
|
||||
|
||||
interface GetNotificationOptions {
|
||||
@@ -192,8 +192,8 @@ interface GetNotificationOptions {
|
||||
}
|
||||
|
||||
interface HashChangeEventInit extends EventInit {
|
||||
newURL?: string;
|
||||
oldURL?: string;
|
||||
newURL?: string | null;
|
||||
oldURL?: string | null;
|
||||
}
|
||||
|
||||
interface IDBIndexParameters {
|
||||
@@ -203,19 +203,20 @@ interface IDBIndexParameters {
|
||||
|
||||
interface IDBObjectStoreParameters {
|
||||
autoIncrement?: boolean;
|
||||
keyPath?: IDBKeyPath;
|
||||
keyPath?: IDBKeyPath | null;
|
||||
}
|
||||
|
||||
interface IntersectionObserverEntryInit {
|
||||
boundingClientRect?: DOMRectInit;
|
||||
intersectionRect?: DOMRectInit;
|
||||
rootBounds?: DOMRectInit;
|
||||
target?: Element;
|
||||
time?: number;
|
||||
isIntersecting: boolean;
|
||||
boundingClientRect: DOMRectInit;
|
||||
intersectionRect: DOMRectInit;
|
||||
rootBounds: DOMRectInit;
|
||||
target: Element;
|
||||
time: number;
|
||||
}
|
||||
|
||||
interface IntersectionObserverInit {
|
||||
root?: Element;
|
||||
root?: Element | null;
|
||||
rootMargin?: string;
|
||||
threshold?: number | number[];
|
||||
}
|
||||
@@ -237,12 +238,12 @@ interface LongRange {
|
||||
}
|
||||
|
||||
interface MediaEncryptedEventInit extends EventInit {
|
||||
initData?: ArrayBuffer;
|
||||
initData?: ArrayBuffer | null;
|
||||
initDataType?: string;
|
||||
}
|
||||
|
||||
interface MediaKeyMessageEventInit extends EventInit {
|
||||
message?: ArrayBuffer;
|
||||
message?: ArrayBuffer | null;
|
||||
messageType?: MediaKeyMessageType;
|
||||
}
|
||||
|
||||
@@ -265,7 +266,7 @@ interface MediaStreamConstraints {
|
||||
}
|
||||
|
||||
interface MediaStreamErrorEventInit extends EventInit {
|
||||
error?: MediaStreamError;
|
||||
error?: MediaStreamError | null;
|
||||
}
|
||||
|
||||
interface MediaStreamEventInit extends EventInit {
|
||||
@@ -273,7 +274,7 @@ interface MediaStreamEventInit extends EventInit {
|
||||
}
|
||||
|
||||
interface MediaStreamTrackEventInit extends EventInit {
|
||||
track?: MediaStreamTrack;
|
||||
track?: MediaStreamTrack | null;
|
||||
}
|
||||
|
||||
interface MediaTrackCapabilities {
|
||||
@@ -350,7 +351,7 @@ interface MouseEventInit extends EventModifierInit {
|
||||
buttons?: number;
|
||||
clientX?: number;
|
||||
clientY?: number;
|
||||
relatedTarget?: EventTarget;
|
||||
relatedTarget?: EventTarget | null;
|
||||
screenX?: number;
|
||||
screenY?: number;
|
||||
}
|
||||
@@ -358,8 +359,8 @@ interface MouseEventInit extends EventModifierInit {
|
||||
interface MSAccountInfo {
|
||||
accountImageUri?: string;
|
||||
accountName?: string;
|
||||
rpDisplayName?: string;
|
||||
userDisplayName?: string;
|
||||
rpDisplayName: string;
|
||||
userDisplayName: string;
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
@@ -442,7 +443,7 @@ interface MSCredentialParameters {
|
||||
|
||||
interface MSCredentialSpec {
|
||||
id?: string;
|
||||
type?: MSCredentialType;
|
||||
type: MSCredentialType;
|
||||
}
|
||||
|
||||
interface MSDelay {
|
||||
@@ -652,8 +653,8 @@ interface MsZoomToOptions {
|
||||
contentX?: number;
|
||||
contentY?: number;
|
||||
scaleFactor?: number;
|
||||
viewportX?: string;
|
||||
viewportY?: string;
|
||||
viewportX?: string | null;
|
||||
viewportY?: string | null;
|
||||
}
|
||||
|
||||
interface MutationObserverInit {
|
||||
@@ -679,9 +680,9 @@ interface ObjectURLOptions {
|
||||
}
|
||||
|
||||
interface PaymentCurrencyAmount {
|
||||
currency?: string;
|
||||
currency: string;
|
||||
currencySystem?: string;
|
||||
value?: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface PaymentDetails {
|
||||
@@ -695,19 +696,19 @@ interface PaymentDetails {
|
||||
interface PaymentDetailsModifier {
|
||||
additionalDisplayItems?: PaymentItem[];
|
||||
data?: any;
|
||||
supportedMethods?: string[];
|
||||
supportedMethods: string[];
|
||||
total?: PaymentItem;
|
||||
}
|
||||
|
||||
interface PaymentItem {
|
||||
amount?: PaymentCurrencyAmount;
|
||||
label?: string;
|
||||
amount: PaymentCurrencyAmount;
|
||||
label: string;
|
||||
pending?: boolean;
|
||||
}
|
||||
|
||||
interface PaymentMethodData {
|
||||
data?: any;
|
||||
supportedMethods?: string[];
|
||||
supportedMethods: string[];
|
||||
}
|
||||
|
||||
interface PaymentOptions {
|
||||
@@ -722,9 +723,9 @@ interface PaymentRequestUpdateEventInit extends EventInit {
|
||||
}
|
||||
|
||||
interface PaymentShippingOption {
|
||||
amount?: PaymentCurrencyAmount;
|
||||
id?: string;
|
||||
label?: string;
|
||||
amount: PaymentCurrencyAmount;
|
||||
id: string;
|
||||
label: string;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
@@ -772,7 +773,7 @@ interface RequestInit {
|
||||
body?: any;
|
||||
cache?: RequestCache;
|
||||
credentials?: RequestCredentials;
|
||||
headers?: any;
|
||||
headers?: Headers | string[][];
|
||||
integrity?: string;
|
||||
keepalive?: boolean;
|
||||
method?: string;
|
||||
@@ -784,7 +785,7 @@ interface RequestInit {
|
||||
}
|
||||
|
||||
interface ResponseInit {
|
||||
headers?: any;
|
||||
headers?: Headers | string[][];
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
}
|
||||
@@ -869,15 +870,15 @@ interface RTCIceGatherOptions {
|
||||
}
|
||||
|
||||
interface RTCIceParameters {
|
||||
iceLite?: boolean;
|
||||
iceLite?: boolean | null;
|
||||
password?: string;
|
||||
usernameFragment?: string;
|
||||
}
|
||||
|
||||
interface RTCIceServer {
|
||||
credential?: string;
|
||||
credential?: string | null;
|
||||
urls?: any;
|
||||
username?: string;
|
||||
username?: string | null;
|
||||
}
|
||||
|
||||
interface RTCInboundRTPStreamStats extends RTCRTPStreamStats {
|
||||
@@ -1087,9 +1088,9 @@ interface RTCTransportStats extends RTCStats {
|
||||
}
|
||||
|
||||
interface ScopedCredentialDescriptor {
|
||||
id?: any;
|
||||
id: any;
|
||||
transports?: Transport[];
|
||||
type?: ScopedCredentialType;
|
||||
type: ScopedCredentialType;
|
||||
}
|
||||
|
||||
interface ScopedCredentialOptions {
|
||||
@@ -1100,29 +1101,29 @@ interface ScopedCredentialOptions {
|
||||
}
|
||||
|
||||
interface ScopedCredentialParameters {
|
||||
algorithm?: string | Algorithm;
|
||||
type?: ScopedCredentialType;
|
||||
algorithm: string | Algorithm;
|
||||
type: ScopedCredentialType;
|
||||
}
|
||||
|
||||
interface ServiceWorkerMessageEventInit extends EventInit {
|
||||
data?: any;
|
||||
lastEventId?: string;
|
||||
origin?: string;
|
||||
ports?: MessagePort[];
|
||||
source?: ServiceWorker | MessagePort;
|
||||
ports?: MessagePort[] | null;
|
||||
source?: ServiceWorker | MessagePort | null;
|
||||
}
|
||||
|
||||
interface SpeechSynthesisEventInit extends EventInit {
|
||||
charIndex?: number;
|
||||
elapsedTime?: number;
|
||||
name?: string;
|
||||
utterance?: SpeechSynthesisUtterance;
|
||||
utterance?: SpeechSynthesisUtterance | null;
|
||||
}
|
||||
|
||||
interface StoreExceptionsInformation extends ExceptionInformation {
|
||||
detailURI?: string;
|
||||
explanationString?: string;
|
||||
siteName?: string;
|
||||
detailURI?: string | null;
|
||||
explanationString?: string | null;
|
||||
siteName?: string | null;
|
||||
}
|
||||
|
||||
interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {
|
||||
@@ -1130,7 +1131,7 @@ interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformat
|
||||
}
|
||||
|
||||
interface TrackEventInit extends EventInit {
|
||||
track?: VideoTrack | AudioTrack | TextTrack;
|
||||
track?: VideoTrack | AudioTrack | TextTrack | null;
|
||||
}
|
||||
|
||||
interface TransitionEventInit extends EventInit {
|
||||
@@ -1140,7 +1141,7 @@ interface TransitionEventInit extends EventInit {
|
||||
|
||||
interface UIEventInit extends EventInit {
|
||||
detail?: number;
|
||||
view?: Window;
|
||||
view?: Window | null;
|
||||
}
|
||||
|
||||
interface WebAuthnExtensions {
|
||||
@@ -1520,9 +1521,9 @@ interface Cache {
|
||||
add(request: RequestInfo): Promise<void>;
|
||||
addAll(requests: RequestInfo[]): Promise<void>;
|
||||
delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;
|
||||
keys(request?: RequestInfo, options?: CacheQueryOptions): any;
|
||||
keys(request?: RequestInfo, options?: CacheQueryOptions): Promise<Request[]>;
|
||||
match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;
|
||||
matchAll(request?: RequestInfo, options?: CacheQueryOptions): any;
|
||||
matchAll(request?: RequestInfo, options?: CacheQueryOptions): Promise<Response[]>;
|
||||
put(request: RequestInfo, response: Response): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1534,7 +1535,7 @@ declare var Cache: {
|
||||
interface CacheStorage {
|
||||
delete(cacheName: string): Promise<boolean>;
|
||||
has(cacheName: string): Promise<boolean>;
|
||||
keys(): any;
|
||||
keys(): Promise<string[]>;
|
||||
match(request: RequestInfo, options?: CacheQueryOptions): Promise<any>;
|
||||
open(cacheName: string): Promise<Cache>;
|
||||
}
|
||||
@@ -2639,7 +2640,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven
|
||||
*/
|
||||
readonly compatMode: string;
|
||||
cookie: string;
|
||||
readonly currentScript: HTMLScriptElement | SVGScriptElement;
|
||||
readonly currentScript: HTMLScriptElement | SVGScriptElement | null;
|
||||
readonly defaultView: Window;
|
||||
/**
|
||||
* Sets or gets a value that indicates whether the document can be edited.
|
||||
@@ -3378,7 +3379,7 @@ interface DOMException {
|
||||
|
||||
declare var DOMException: {
|
||||
prototype: DOMException;
|
||||
new(): DOMException;
|
||||
new(message?: string, name?: string): DOMException;
|
||||
readonly ABORT_ERR: number;
|
||||
readonly DATA_CLONE_ERR: number;
|
||||
readonly DOMSTRING_SIZE_ERR: number;
|
||||
@@ -3884,7 +3885,7 @@ interface Headers {
|
||||
|
||||
declare var Headers: {
|
||||
prototype: Headers;
|
||||
new(init?: any): Headers;
|
||||
new(init?: Headers | string[][]): Headers;
|
||||
};
|
||||
|
||||
interface History {
|
||||
@@ -4044,7 +4045,7 @@ interface HTMLAppletElement extends HTMLElement {
|
||||
* Sets or retrieves a character string that can be used to implement your own declare functionality for the object.
|
||||
*/
|
||||
declare: boolean;
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the height of the object.
|
||||
*/
|
||||
@@ -4282,7 +4283,7 @@ interface HTMLButtonElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Overrides the action attribute (where the data on a form is sent) on the parent form element.
|
||||
*/
|
||||
@@ -4715,7 +4716,7 @@ interface HTMLFieldSetElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
name: string;
|
||||
/**
|
||||
* Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting.
|
||||
@@ -5294,7 +5295,7 @@ interface HTMLInputElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Overrides the action attribute (where the data on a form is sent) on the parent form element.
|
||||
*/
|
||||
@@ -5461,7 +5462,7 @@ interface HTMLLabelElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the object to which the given label object is assigned.
|
||||
*/
|
||||
@@ -5483,7 +5484,7 @@ interface HTMLLegendElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLegendElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
@@ -5917,7 +5918,7 @@ interface HTMLObjectElement extends HTMLElement, GetSVGDocument {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the height of the object.
|
||||
*/
|
||||
@@ -6016,7 +6017,7 @@ interface HTMLOptGroupElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the ordinal position of an option in a list box.
|
||||
*/
|
||||
@@ -6055,7 +6056,7 @@ interface HTMLOptionElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the ordinal position of an option in a list box.
|
||||
*/
|
||||
@@ -6099,7 +6100,7 @@ declare var HTMLOptionsCollection: {
|
||||
|
||||
interface HTMLOutputElement extends HTMLElement {
|
||||
defaultValue: string;
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
readonly htmlFor: DOMSettableTokenList;
|
||||
name: string;
|
||||
readonly type: string;
|
||||
@@ -6188,7 +6189,7 @@ interface HTMLProgressElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Defines the maximum, or "done" value for a progress element.
|
||||
*/
|
||||
@@ -6274,7 +6275,7 @@ interface HTMLSelectElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the number of objects in a collection.
|
||||
*/
|
||||
@@ -6745,7 +6746,7 @@ interface HTMLTextAreaElement extends HTMLElement {
|
||||
/**
|
||||
* Retrieves a reference to the form that the object is embedded in.
|
||||
*/
|
||||
readonly form: HTMLFormElement;
|
||||
readonly form: HTMLFormElement | null;
|
||||
/**
|
||||
* Sets or retrieves the maximum number of characters that the user can enter in a text control.
|
||||
*/
|
||||
@@ -7211,6 +7212,7 @@ interface IntersectionObserverEntry {
|
||||
readonly rootBounds: ClientRect;
|
||||
readonly target: Element;
|
||||
readonly time: number;
|
||||
readonly isIntersecting: boolean;
|
||||
}
|
||||
|
||||
declare var IntersectionObserverEntry: {
|
||||
@@ -7312,7 +7314,7 @@ interface MediaDevicesEventMap {
|
||||
|
||||
interface MediaDevices extends EventTarget {
|
||||
ondevicechange: (this: MediaDevices, ev: Event) => any;
|
||||
enumerateDevices(): any;
|
||||
enumerateDevices(): Promise<MediaDeviceInfo[]>;
|
||||
getSupportedConstraints(): MediaTrackSupportedConstraints;
|
||||
getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
|
||||
addEventListener<K extends keyof MediaDevicesEventMap>(type: K, listener: (this: MediaDevices, ev: MediaDevicesEventMap[K]) => any, useCapture?: boolean): void;
|
||||
@@ -9058,6 +9060,7 @@ interface Response extends Object, Body {
|
||||
readonly statusText: string;
|
||||
readonly type: ResponseType;
|
||||
readonly url: string;
|
||||
readonly redirected: boolean;
|
||||
clone(): Response;
|
||||
}
|
||||
|
||||
@@ -9512,7 +9515,7 @@ interface ServiceWorkerContainer extends EventTarget {
|
||||
onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any;
|
||||
readonly ready: Promise<ServiceWorkerRegistration>;
|
||||
getRegistration(clientURL?: USVString): Promise<any>;
|
||||
getRegistrations(): any;
|
||||
getRegistrations(): Promise<ServiceWorkerRegistration[]>;
|
||||
register(scriptURL: USVString, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>;
|
||||
addEventListener<K extends keyof ServiceWorkerContainerEventMap>(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
@@ -9548,7 +9551,7 @@ interface ServiceWorkerRegistration extends EventTarget {
|
||||
readonly scope: USVString;
|
||||
readonly sync: SyncManager;
|
||||
readonly waiting: ServiceWorker | null;
|
||||
getNotifications(filter?: GetNotificationOptions): any;
|
||||
getNotifications(filter?: GetNotificationOptions): Promise<Notification[]>;
|
||||
showNotification(title: string, options?: NotificationOptions): Promise<void>;
|
||||
unregister(): Promise<boolean>;
|
||||
update(): Promise<void>;
|
||||
@@ -11573,7 +11576,7 @@ declare var SVGZoomEvent: {
|
||||
};
|
||||
|
||||
interface SyncManager {
|
||||
getTags(): any;
|
||||
getTags(): Promise<string[]>;
|
||||
register(tag: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -11881,6 +11884,7 @@ interface ValidityState {
|
||||
readonly typeMismatch: boolean;
|
||||
readonly valid: boolean;
|
||||
readonly valueMissing: boolean;
|
||||
readonly tooShort: boolean;
|
||||
}
|
||||
|
||||
declare var ValidityState: {
|
||||
@@ -13742,13 +13746,13 @@ interface NavigatorUserMedia {
|
||||
|
||||
interface NodeSelector {
|
||||
querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;
|
||||
querySelector(selectors: string): Element | null;
|
||||
querySelector<E extends Element = Element>(selectors: string): E | null;
|
||||
querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];
|
||||
querySelectorAll(selectors: string): NodeListOf<Element>;
|
||||
querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;
|
||||
}
|
||||
|
||||
interface RandomSource {
|
||||
getRandomValues(array: ArrayBufferView): ArrayBufferView;
|
||||
getRandomValues<T extends Int8Array | Uint8ClampedArray | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array>(array: T): T;
|
||||
}
|
||||
|
||||
interface SVGAnimatedPoints {
|
||||
@@ -13823,17 +13827,37 @@ interface XMLHttpRequestEventTargetEventMap {
|
||||
}
|
||||
|
||||
interface XMLHttpRequestEventTarget {
|
||||
onabort: (this: XMLHttpRequestEventTarget, ev: Event) => any;
|
||||
onerror: (this: XMLHttpRequestEventTarget, ev: ErrorEvent) => any;
|
||||
onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;
|
||||
onloadend: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
|
||||
onloadstart: (this: XMLHttpRequestEventTarget, ev: Event) => any;
|
||||
onprogress: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
|
||||
ontimeout: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;
|
||||
onabort: (this: XMLHttpRequest, ev: Event) => any;
|
||||
onerror: (this: XMLHttpRequest, ev: ErrorEvent) => any;
|
||||
onload: (this: XMLHttpRequest, ev: Event) => any;
|
||||
onloadend: (this: XMLHttpRequest, ev: ProgressEvent) => any;
|
||||
onloadstart: (this: XMLHttpRequest, ev: Event) => any;
|
||||
onprogress: (this: XMLHttpRequest, ev: ProgressEvent) => any;
|
||||
ontimeout: (this: XMLHttpRequest, ev: ProgressEvent) => any;
|
||||
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
interface BroadcastChannel extends EventTarget {
|
||||
readonly name: string;
|
||||
onmessage: (ev: MessageEvent) => any;
|
||||
onmessageerror: (ev: MessageEvent) => any;
|
||||
close(): void;
|
||||
postMessage(message: any): void;
|
||||
addEventListener<K extends keyof BroadcastChannelEventMap>(type: K, listener: (this: BroadcastChannel, ev: BroadcastChannelEventMap[K]) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
declare var BroadcastChannel: {
|
||||
prototype: BroadcastChannel;
|
||||
new(name: string): BroadcastChannel;
|
||||
};
|
||||
|
||||
interface BroadcastChannelEventMap {
|
||||
message: MessageEvent;
|
||||
messageerror: MessageEvent;
|
||||
}
|
||||
|
||||
interface ErrorEventInit {
|
||||
message?: string;
|
||||
filename?: string;
|
||||
@@ -13924,8 +13948,7 @@ interface BlobPropertyBag {
|
||||
endings?: string;
|
||||
}
|
||||
|
||||
interface FilePropertyBag {
|
||||
type?: string;
|
||||
interface FilePropertyBag extends BlobPropertyBag {
|
||||
lastModified?: number;
|
||||
}
|
||||
|
||||
@@ -14201,6 +14224,44 @@ interface TouchEventInit extends EventModifierInit {
|
||||
changedTouches?: Touch[];
|
||||
}
|
||||
|
||||
interface HTMLDialogElement extends HTMLElement {
|
||||
open: boolean;
|
||||
returnValue: string;
|
||||
close(returnValue?: string): void;
|
||||
show(): void;
|
||||
showModal(): void;
|
||||
}
|
||||
|
||||
declare var HTMLDialogElement: {
|
||||
prototype: HTMLDialogElement;
|
||||
new(): HTMLDialogElement;
|
||||
};
|
||||
|
||||
interface HTMLMainElement extends HTMLElement {
|
||||
}
|
||||
|
||||
declare var HTMLMainElement: {
|
||||
prototype: HTMLMainElement;
|
||||
new(): HTMLMainElement;
|
||||
};
|
||||
|
||||
interface HTMLDetailsElement extends HTMLElement {
|
||||
open: boolean;
|
||||
}
|
||||
|
||||
declare var HTMLDetailsElement: {
|
||||
prototype: HTMLDetailsElement;
|
||||
new(): HTMLDetailsElement;
|
||||
};
|
||||
|
||||
interface HTMLSummaryElement extends HTMLElement {
|
||||
}
|
||||
|
||||
declare var HTMLSummaryElement: {
|
||||
prototype: HTMLSummaryElement;
|
||||
new(): HTMLSummaryElement;
|
||||
};
|
||||
|
||||
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
|
||||
|
||||
interface DecodeErrorCallback {
|
||||
@@ -14690,7 +14751,7 @@ type GLsizeiptr = number;
|
||||
type GLubyte = number;
|
||||
type GLuint = number;
|
||||
type GLushort = number;
|
||||
type HeadersInit = any;
|
||||
type HeadersInit = Headers | string[][];
|
||||
type IDBKeyPath = string;
|
||||
type KeyFormat = string;
|
||||
type KeyType = string;
|
||||
|
||||
Vendored
+1
-1
@@ -110,7 +110,7 @@ interface Map<K, V> {
|
||||
readonly [Symbol.toStringTag]: "Map";
|
||||
}
|
||||
|
||||
interface WeakMap<K extends object, V>{
|
||||
interface WeakMap<K extends object, V> {
|
||||
readonly [Symbol.toStringTag]: "WeakMap";
|
||||
}
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -216,7 +216,7 @@ interface ObjectConstructor {
|
||||
* Returns the names of the enumerable properties and methods of an object.
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
keys(o: any): string[];
|
||||
keys(o: {}): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -991,12 +991,12 @@ interface Array<T> {
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(this: readonly, ...items: T[][]): T[];
|
||||
concat(this: readonly, ...items: ReadonlyArray<T>[]): T[];
|
||||
/**
|
||||
* Combines two or more arrays.
|
||||
* @param items Additional items to add to the end of array1.
|
||||
*/
|
||||
concat(this: readonly, ...items: (T | T[])[]): T[];
|
||||
concat(this: readonly, ...items: (T | ReadonlyArray<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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user